问题和应用BG:所以我正在创建一个存储一些敏感数据的nodeJS应用程序,我想加密所有内容。但是当我尝试用错误的密钥解密某些数据时,我得到一个TypeError:DecipherFinal失败错误。
以下是我的应用程序的安全性如何工作:(请注意,这是针对AppJS而不是面向Web的应用程序)
用户可以'创建帐户',创建新文件;该文件的第一行用作标识符:encrypt(“Somestring”+ username)
用户可以登录,打开文件并使用密码解密第一行。如果它恰好是“Somestring”+用户名,那么我们将用户登录。
只要我不使用错误的密钥,这就可以正常工作,这会导致DecipherFinal失败错误。
问题:
甚至可以做我想做的事情吗?我假设如果我使用不正确的密钥通过解密函数运行数据,我会得到不正确的数据。
这是一个糟糕的设计吗?我在某处读到你不应该在与使用该密码加密的数据相同的数据库中存储散列密码,因此根本不存储密码我认为用户可以只跟踪它,并且他们可以解密预期的消息授权。数据的本质是非常重要的,没有其他人可以得到它,但用户可以恢复他们的数据并不是非常重要。
这是“滚动我自己的加密”吗?这是否意味着坚持已知模式或只是坚持已经证明的原语和算法?如果这是我自己的,那么我可以用于Node的加密容器的实现吗?
代码:
https://gist.github.com/sanarothe/5993384
非常感谢,
卡梅伦
答案 0 :(得分:2)
至于解密失败的原因,AES256的块大小为16字节(即,它只能加密偶数16字节块中的数据)由于您的数据不一定是可被16整除的大小,因此加密库具有{ {3}}开启添加一些填充数据(本例中为PKCS),使长度可被16整除。
填充的构造使得当解密到达数据的末尾时,它确切地知道要删除哪些字节以在正确的字节处切断消息而不在末尾返回垃圾。问题是,当它以随机数据结束时,“unpadding”检测到它无法找到结束标记并且无法解密。请注意,完全随机数据实际上可能包含有效标记,因此即使对随机数据也不能保证此检查失败。
如果你真的不希望解密在填充不匹配时失败,你可以确保数据的长度可以被16整除(通过你喜欢的任何方式自己填充)并使用autopadding关闭自动添加在加密和解密时调用final
之前。这样,您就不会遇到解密失败,并且在您尝试时,必须自己检测加密失败。
至于设计,对我来说整个方案听起来有点像滚动你自己的安全。例如,如果您添加可以检查其有效性的数据(就像您对已知数据的第一行所做的那样),那么您可以通过允许攻击者在已知位置使用(或多或少)已知纯文本来帮助攻击者在流中测试密钥。 AES256目前对于已知的纯文本攻击是相当安全的,但是你在几年内就不会知道了。
第二件事,你会想要使用AES-256-CBC或类似的,我不确定加密模式默认使用cipher.setautopadding(false)
。