0

问题和应用程序 BG:所以我正在创建一个 nodeJS 应用程序来存储一些敏感数据,并且我想加密所有内容。但是当我尝试用错误的密钥解密一些数据时,我得到一个 TypeError: DecipherFinal 失败错误。

以下是我的应用程序的安全工作方式:(请注意,这是针对 AppJS 而不是面向 Web 的应用程序)

  1. 用户可以“创建帐户”,即创建一个新文件;文件的第一行用作标识符: encrypt("Somestring" + username)

  2. 用户可以登录,打开文件并使用他们的密码解密第一行。如果它恰好是“Somestring”+ 用户名,那么我们将用户登录。

只要我不使用错误的密钥,这就会正常工作,这会导致 DecipherFinal 失败错误。

问题:

  1. 甚至有可能做我想做的事吗?我假设如果我使用不正确的密钥通过解密函数运行数据,我只会得到不正确的数据。

  2. 这是一个糟糕的设计吗?我在某处读到,您不应该将散列密码存储在与使用该密码加密的数据相同的数据库中,因此我认为用户根本不需要存储密码,而是可以跟踪它,并且他们可以解密预期的消息授权。数据的性质使得其他人无法获取数据非常重要,但用户可以恢复他们的数据并不是很重要。

  3. 这是“滚动我自己的加密货币”吗?这是否意味着坚持已知模式或仅仅坚持经过验证的原语和算法?如果这是我自己的,是否有任何可用于 Node 的加密容器的实现?

代码:

https://gist.github.com/sanarothe/5993384

非常感谢,

卡梅伦

4

1 回答 1

2

至于为什么解密失败,AES256 的块大小为 16 字节(即它只能加密 16 字节块中的数据)由于您的数据不一定是可被 16 整除的大小,因此加密库已打开自动填充功能添加一些填充数据(在本例中为 PKCS)以使长度可被 16 整除。

填充的构造是这样的,当解密到数据的末尾时,它确切地知道要删除哪些字节以在正确的字节处切断消息,而不是在最后返回垃圾。问题是当它以随机数据结束时,“unpadding”检测到它找不到结束标记并且解密失败。请注意,完全随机的数据实际上可能包含一个有效的标记,因此您不能以任何方式保证此检查即使在随机数据上也会失败。

cipher.setautopadding(false)如果您真的不希望解密因填充不匹配而失败,您可以确保数据的长度可被 16 整除(通过以您喜欢的任何方式自行填充)并在调用final加密和解密之前关闭自动填充。这样,您将不会遇到解密失败,并且在您尝试时,您必须自己检测加密失败。

至于设计,对我来说,整个方案听起来有点像滚动你自己的安全性。例如,如果您添加可以检查有效性的数据(就像您对第一行已知数据所做的那样),您就是在帮助攻击者在已知位置使用(或多或少)已知的纯文本在流中测试键。AES256 目前对已知的纯文本攻击相当安全,但几年后你永远不会知道。

第二件事,你会想要使用 AES-256-CBC 或类似的,我不确定加密模块默认使用什么操作模式。

于 2013-07-14T06:54:57.957 回答