javascript - 验证解密的字符串

标签 javascript encryption cryptography

我正在使用 Node.js 加密库通过 AES-256-ctr 加密较大的文件。我现在遇到的一个问题是验证解密是否成功。目前,如果我使用错误的密码,我无法知道解密失败,直到我查看文本并意识到它不可读,但这使得以编程方式检查并要求重试密码变得困难。

到目前为止我从研究中收集到的内容(如果我错了,请纠正我):

  • 我可以使用 HMAC 来验证解密消息的完整性
  • 我应该始终在加密后运行 HMAC 函数,因为在加密数据之前对任何内容进行哈希处理,而不加密哈希本身会破坏加密的目的
  • 不要使用相同的 key 进行加密和 MAC

我的问题: 这是错误的吗?如果是的话,为什么只是在我想要加密的消息中添加一个字符串,然后在解密时检查它是否存在。这似乎是一个简单的检查,但我无法理解为什么不应该这样做。

例如。

加密:

  1. “ Hello World ”
  2. (前置所述字符串)'ENCRYPTED:hello world'
  3. (加密消息)
  4. 'iv:abc123'

解密:

  1. 'iv:abc123' ->(解密)
  2. decStr = 'ENCRYPTED:hello world' 或 'ab/12c879312sc/!/'
  3. if (decStr.split(':')[0] === 'ENCRYPTED') { 正确解密 }

createHmac() 函数中的“ secret ”应该使用什么?我不想要求用户持有两个密码。一种用于加密,一种用于验证。我可以使用通过 scrypt 加密密码而获得的派生 key 吗?

我无法判断这是一个愚蠢的问题还是我只是没有寻找正确的东西,但一些类似的问题只是说使用 aes-gcm 以避免担心这个问题。我主要只是好奇如何做到这一点。

最佳答案

您可能不想只在消息前面添加一个字符串。这是因为攻击者可以篡改初始字符串之外的消息,而您仍然无法检测到它。由于 CTR 模式使用 XOR 与 key 流进行加密,因此这很简单。

您想要执行以下两种操作之一:使用 AEAD 进行加密,例如 AES-GCM 或 ChaCha20-Poly1305,或者使用 CTR 模式和 HMAC 对加密数据进行加密。请注意,如果您这样做,您绝不能重复使用加密的 key -随机数对,否则您将失去所有安全性。

最简单、最简单的方法是使用 AES-GCM。您可以以适当的方式生成单个加密安全 key 。然后,从系统 CSPRNG 生成随机 256 位盐。然后执行此操作(|| 是连接):

PRK = HMAC-SHA-256(salt, initial-key)
key = HMAC-SHA-256(PRK, "encryption key" || 0x01)
IV = HMAC-SHA-256(PRK, "nonce" || 0x01)

这使用 HKDF生成加密 key 、IV(您需要将其 chop 为 12 字节)。加密数据,并发出 32 字节盐和加密消息。

这样,只要您始终为每次加密选择随机盐,是否使用相同的初始 key 并不重要,因为您几乎永远不会重复使用 key -IV 对。

如果这些文件太大,以至于您迫不及待地检查整个加密以查看它们是否正确,请添加一个额外的 32 字节值:

check-value = HMAC-SHA-256(PRK, "check value" || 0x01)

然后,发出盐、检查值和使用 AES-GCM 加密的数据。验证密码时,检查校验值是否相同,如果不一致则错误。如果 ChaCha20-Poly1305 更适合您的环境(ARM 系统或没有 AES 加速的其他系统),所有这些方法也可以使用 ChaCha20-Poly1305 来完成。

额外的 0x01 字节严格来说是不必要的,但使用它意味着您正在使用 HKDF,这意味着您可以说您正在使用受到广泛尊重的标准方法。

关于javascript - 验证解密的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65556689/

相关文章:

java - 带有 GWT Sprite 的视网膜图像?

c++ - 使用字母字符加密/解密 XOR

java - 将 BKS 与 keytool 一起使用导致无法从回复建立链

javascript - 影响多个 div 的 jQuery 单击函数

javascript - 使用 Ryan Fait 代码的动态粘性页脚高度

mysql - MySQL 和 MariaDB 之间密码散列的差异

c - 如何在服务器端使用 openssl 完全禁用重新协商(重新握手)?

security - 这是否意味着我的大学不安全地存储密码?

Java 到 Win32 加密 API

javascript - 如何获取父/包装对象的引用?