Javascript 验证解密字符串

Javascript 验证解密字符串,javascript,encryption,cryptography,Javascript,Encryption,Cryptography,我正在使用Node.js加密库使用AES-256-ctr加密较大的文件。我现在遇到的一个问题是验证解密是否成功。目前,如果我使用了错误的密码,我无法知道解密失败,直到我查看文本并意识到它不可读,但这使得以编程方式检查和请求密码重试变得困难 到目前为止,我从我的研究中收集到了什么(如果我错了,请纠正我): 我可以使用HMAC来验证解密消息的完整性 我应该始终在加密后运行HMAC函数,因为在加密数据之前对任何内容进行哈希,而不加密哈希本身会破坏加密的目的 加密和MAC不要使用相同的密钥 我的问题

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

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

  • 我可以使用HMAC来验证解密消息的完整性
  • 我应该始终在加密后运行HMAC函数,因为在加密数据之前对任何内容进行哈希,而不加密哈希本身会破坏加密的目的
  • 加密和MAC不要使用相同的密钥
我的问题是: 在我要加密的消息前加上一个字符串,然后在解密时检查它是否在那里,这是否是错误的,如果是,原因是什么。这看起来像是一个简单的检查,但我不明白为什么不应该这样做

加密:

  • “你好,世界”
  • (前置表示字符串)“加密:hello world”
  • (加密消息)
  • “四:abc123”
  • 解密:

  • 'iv:abc123'->(解密)
  • decStr='ENCRYPTED:hello world'或'ab/12c879312sc/!/'
  • 如果(decStr.split(':')[0]='ENCRYPTED'){正确解密}
  • createHmac()函数中的“secret”应该使用什么?我不想要求用户持有两个密码。一个用于加密,一个用于验证。我可以使用从使用scrypt加密密码中获得的派生密钥吗


    我不知道这是一个愚蠢的问题,还是我只是没有寻找正确的东西,但是一些类似的问题只是说使用aes gcm来避免担心这个问题。我很好奇怎么做。

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

    您需要做两件事中的一件:使用AEAD进行加密,如AES-GCM或ChaCha20-Poly1305,或使用CTR模式对加密数据使用HMAC。请注意,如果这样做,则决不能重复使用加密的密钥对,否则将失去所有安全性

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

    这用于生成一个加密密钥,即IV(需要将其截断为12个字节)。加密数据,并发出32字节的salt和加密消息

    这样,只要您总是为每个加密选择一个随机的salt,那么您是否使用相同的初始密钥并不重要,因为您实际上永远不会重复使用密钥对

    如果这些文件太大,以至于您无法等着检查整个加密是否正确,那么再添加一个32字节的值:

    check-value = HMAC-SHA-256(PRK, "check value" || 0x01)
    
    然后,发出salt、检查值和使用AES-GCM加密的数据。要验证密码,请检查检查值是否相同,如果不相同,则为错误。如果ChaCha20-Poly1305更适合您的环境(ARM系统或其他没有AES加速的系统),那么所有这些方法也可以通过ChaCha20-Poly1305实现


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

    使用node.js加密库是否正确?我相信您提到的一些技术在某种程度上已经融入了函数中,比如“setAuthTag()”,但我可能错了。我对你上一次的评论很感兴趣,不过我只是想检查一个连接到文件末尾的32字节的值。是的,所有这些看起来都很好。您正在使用scrypt或CSPRNG生成所有内容,因此您应该是优秀的。
    check-value = HMAC-SHA-256(PRK, "check value" || 0x01)