AES加密 - 密钥与IV

Pet*_*ter 61 encryption aes

我正在处理的应用程序允许用户加密文件.文件可以是任何格式(电子表格,文档,演示文稿等).

对于指定的输入文件,我创建了两个输出文件 - 加密数据文件和密钥文件.您需要这两个文件才能获取原始数据.密钥文件必须仅适用于相应的数据文件.它不适用于来自同一用户或任何其他用户的任何其他文件.

AES算法需要两个不同的加密参数,一个密钥和一个初始化向量(IV).

我看到了创建密钥文件的三种选择:

  1. 在应用程序中嵌入硬编码IV并将密钥保存在密钥文件中.
  2. 在应用程序中嵌入硬编码密钥并将IV保存在密钥文件中.
  3. 将密钥和IV保存在密钥文件中.

请注意,它与不同客户使用的应用程序相同.

看起来所有三种选择都会实现相同的最终目标.但是,我想就正确的方法应该得到您的反馈.

Tai*_*ils 75

从其他答案中可以看出,每个加密文件具有唯一的IV是至关重要的,但为什么呢?

首先 - 让我们来看看为什么每个加密文件的唯一IV很重要.(维基百科四).IV为您的加密过程开始增加了随机性.当使用链式块加密模式(其中一个加密数据块包含先前的加密数据块)时,我们留下了关于第一个块的问题,这是IV进入的地方.

如果您没有IV,并且仅使用密钥使用链式块加密,则以相同文本开头的两个文件将生成相同的第一个块.如果输入文件在中途发生了变化,那么从该点开始到加密文件的末尾,两个加密文件将开始变得不同.如果有人在开始时注意到了这种相似性,并且知道其中一个文件是从哪个开始的,那么他就可以推断出其他文件的起源.知道明文文件的开头是什么以及相应的密文是什么,可以让该人确定密钥,然后解密整个文件.

现在添加IV - 如果每个文件使用随机IV,它们的第一个块将是不同的.上述情况遭到挫败.

现在如果每个文件的IV相同怎么办?好吧,我们再次遇到问题.每个文件的第一个块将加密到相同的结果.实际上,这与完全不使用IV没有什么不同.

现在让我们来看看你提出的选择:

选项1.在应用程序中嵌入硬编码IV并将密钥保存在密钥文件中.

选项2.在应用程序中嵌入硬编码密钥,并将IV保存在密钥文件中.

这些选项非常相似.如果两个以相同文本开头的文件生成以相同密文开头的加密文件,那么您就会被软管化.这将在这两个选项中发生.(假设有一个主密钥用于加密所有文件).

选项3.将密钥和IV保存在密钥文件中.

如果您为每个密钥文件使用随机 IV,那么您就是好的.没有两个密钥文件是相同的,每个加密文件必须有它的密钥文件.不同的密钥文件将无法使用.

PS:一旦你使用选项3和随机IV - 开始研究如何确定解密是否成功.从一个文件中获取密钥文件,并尝试使用它来解密其他加密文件.您可能会发现解密进行并产生垃圾结果.如果发生这种情况,请开始研究经过验证的加密.

  • 但是,(至少在CBC模式下)错误的IV只会破坏第一个块,您仍然可以解密剩余的文件内容. (5认同)
  • @Rich - 我知道我的评论晚了 4 年,但是......我尝试使用损坏的 IV 使用 .NET AES 库进行解密。只有第一个块被破坏。这是因为,加密块是 CBC 中下一个块的 IV ......并且在解密第一个块之外的其他块时,您总是拥有加密的前一个块。 (5认同)
  • @Les - 也许晚了 4 年,但你是绝对正确的。我的上述评论对 CBC 来说是完全错误的。不知道我在想什么。谢谢。 (3认同)
  • 解密需要IV。 (2认同)
  • 我在这里的几个地方看到了与上面类似的评论(“错误的 IV 只会损坏第一个块,您仍然可以解密剩余的文件内容”)。这不是真的。由于加密的第一个块是第二个块(依此类推)的 IV,未知的 IV 意味着无法解密任何块。维基百科上的 CBC 图非常清楚地说明了这一点:[链接](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29) (2认同)

bdo*_*lan 29

关于IV的重要一点是你绝不能对两条消息使用相同的IV.其他一切都是次要的 - 如果你能确保独特性,随机性就不那么重要了(但仍然是一件非常好的事情!).IV不需要(实际上,在CBC模式下不可能)秘密.

因此,你不应该将密钥与密钥一起保存 - 这意味着你对每条消息都使用相同的IV,这就违背了IV的要求.通常,您只需将IV添加到加密文件中即可.

如果您打算使用这样的自己的密码模式,请阅读相关标准.NIST在这里有一个关于密码模式的好文档:http://dx.doi.org/10.6028/NIST.SP.800-38A IV生成记录在附录C中.密码学是一种微妙的艺术.不要试图在正常的密码模式上创建变体; 99%的时间你会创造看起来更安全但实际上不太安全的东西.

  • @Peter,这不是IV的用途.特别是,如果IV未知,但密钥已知,则在CBC模式下,黑客将无法恢复明文的第一个块.但是,他们将能够恢复其余的明文.IV的唯一目的是扰乱文件,以便重复加密不会产生相同的输出(因此,攻击者无法通过看到密文相同来判断两个文件具有相同的内容). (5认同)
  • 编辑:我删除了之前的评论。我同意,阅读我 http://cwe.mitre.org/data/definitions/329.html 表明您应该使用随机 IV 而不是重复使用它。将其基于密码、盐等会违反这一点。 (2认同)
  • 如果您只使用静态IV来加密随机数据(会话密钥或其他派生密钥),那么使用静态IV是有意义的.否则,您应该使用随机IV,如果您为每个加密消息获得了额外<blocksize>字节的空间,那么您也可以一直使用一个. (2认同)
  • 根据所使用的操作模式,IV 具有不同的用途。在 CTR 中,它必须是唯一的,以防止 [多次填充](http://crypto.stackexchange.com/q/6020/13022)。在 CBC 中,它是 [不可预测的](http://crypto.stackexchange.com/q/6702/13022) 并且不是唯一的。消息计数器是唯一的,适用于 CTR 模式,但不适用于 CBC 模式。 (2认同)

gpe*_*che 12

当你使用IV时,最重要的是IV应该尽可能独特,所以在实践中你应该使用随机IV.这意味着将其嵌入您的应用程序不是一种选择.我会将IV保存在数据文件中,因为只要IV是随机/唯一的,它就不会损害安全性.

  • IV不是'确保黑客无法打开加密文件'.这是为了确保,如果您对同一文件进行两次加密,它将产生不同的加密输出. (10认同)

Rus*_*ing 7

密钥/IV 对可能是加密领域中最令人困惑的。简单来说,密码=密钥+iv。这意味着您需要匹配密钥和 iv 才能解密加密消息。互联网似乎暗示你只需要 iv 来加密并把它扔掉,但它也需要解密。吐出 key/iv 值的原因是为了可以使用相同的密钥加密相同的消息,但使用不同的 Iv 来获得不相等的加密消息。因此,Encrypt("message", key, iv) != Encrypt("message", key, differentIv)。这个想法是在每次加密消息时使用新的随机 Iv 值。但如何管理不断变化的 Iv 值呢?有一百万种可能性,但最合乎逻辑的方法是将 16 字节 Iv 嵌入到加密消息本身中。因此,加密 = Iv + 加密消息。这样,可以从加密消息中提取并删除内容变化的 Iv 值,然后进行解密。所以decryptedMessage = Decrypt("messageWithoutIv", key, IvFromEncryptedMessage)。或者,如果将加密消息存储在数据库中,则可以将 Iv 存储在该字段中。尽管其真正的 Iv 是秘密的一部分,但与 32 位密钥相比它很小,并且从未重复使用,因此公开暴露实际上是安全的。请记住,iv 与 encruotion 无关,它与具有相同内容的消息的屏蔽加密有关。