【问题标题】:Key salt and initial value AES密钥盐和初始值 AES
【发布时间】:2012-01-31 07:24:08
【问题描述】:

我正在使用 256 位密钥在 cbc 模式下使用 AES 创建加密方案。在了解 CBC 模式和初始值之前,我计划为每个加密操作创建一个 32 位盐并存储盐。然后,密码/输入的密钥将被这个盐填充到 32 位。

即。如果输入的密码/密钥是“树”,而不是用 28 个 0 填充它,它将用该盐的前 28 个字符填充。

但是,这是在我了解 iv 之前,在某些地方也称为盐。对我来说,现在出现的问题是,这种早期的腌制方法在原则上是否已经成为 IV 的多余。这将假设盐和 iv 将与密文一起存储,因此理论上的暴力攻击不会被阻止。

存储这个密钥并使用它而不是 0 是一个需要付出努力的步骤,所以值得一问我认为这是否是一个实际上无用的措施。就目前的知识而言,似乎无法为 AES 生成任何暴力解密表,甚至 16 位盐也无法创建 md5 表。

谢谢, 以利亚

【问题讨论】:

    标签: encryption cryptography


    【解决方案1】:

    很高兴您了解 CBC,因为它肯定比使用 ECB 模式加密更好(尽管也存在更好的模式,例如认证模式 GCM 和 EAX)。

    我认为有几件事你应该知道,所以我将在这里解释它们。


    密钥和密码不一样。通常,您使用密钥派生函数从密码中创建用于对称加密的密钥。这里讨论的最常见的是 PBKDF2(基于密码的密钥派生函数 #2),它用于 PBE(基于密码的加密)。这是 RSA 实验室在最新的开放 PKCS#5 标准中定义的。输入密码前需要检查密码是否正确翻译成字节(字符编码)。

    盐用作密钥推导函数的另一个输入。它用于防止使用“彩虹表”的暴力攻击,其中密钥是为特定密码预先计算的。由于盐,攻击者不能使用预先计算的值,因为他不能为每个盐生成一个。 salt 通常应为 8 字节(64 位)或更长;使用 128 位 salt 将为您提供最佳安全性。 salt 还确保(不同用户的)相同密码不会派生相同的密钥。

    密钥派生函数的输出是dkLen字节的秘密,其中dkLen是要生成的密钥的长度,以字节为单位。由于 AES 密钥不包含这些字节以外的任何内容,因此 AES 密钥将与生成的密钥相同。对于 AES 的密钥长度,dkLen 应为 16、24 或 32 字节:128、192 或 256 位。


    好的,现在您终于可以使用 AES 密钥了。但是,如果您只是使用此密钥加密每个纯文本块,如果纯文本块相同,您将获得相同的结果。 CBC 模式通过在进行加密之前将下一个纯文本块与最后一个加密块进行异或运算来解决此问题。最后一个加密块是“向量”。这不适用于第一个块,因为 没有最后一个加密块。这就是为什么您需要指定第一个向量:“初始化向量”或 IV。

    AES 的块大小是 16 个字节独立的密钥大小。因此,包括初始化向量在内的向量也需要为 16 个字节。现在,如果您只使用密钥进行加密,例如单个文件,则 IV 可以简​​单地包含 16 个字节,其值为 00h。

    这不适用于多个文件,因为如果文件包含相同的文本,您将能够检测到加密文件的第一部分是相同的。这就是为什么您需要为使用密钥执行的每个加密指定不同的 IV。它包含什么并不重要,只要它是唯一的,16 个字节并且对于执行解密的应用程序是已知的。

    [6 年后编辑] 上面的部分并不完全正确:对于 CBC,IV 需要对攻击者来说是不可预测的,但事实并非如此只是需要是独一无二的。因此,例如不能使用计数器。

    现在有一个技巧可以让您始终对 IV 使用全零:对于您使用 AES-CBC 加密的每个纯文本,您可以使用相同的密码但使用不同的盐来计算密钥。在这种情况下,您只会将生成的密钥用于一条信息。如果您无法为实现基于密码的加密的库提供 IV,这可能是个好主意。

    [EDIT] 另一个常用的技巧是使用 PBKDF2 的附加输出来导出 IV。这样就满足了官方建议,即 CBC 的 IV 不应被对手预测。但是,您应该确保要求 PBKDF2 函数的输出超过底层哈希函数可以提供的输出。 PBKDF2 的弱点会使对手在这种情况下获得优势。因此,如果 SHA-256 用作 PBKDF2 的散列函数,则不要要求超过 256 位。请注意,SHA-1 是 PBKDF2 的常见默认值,因此只允许使用单个 128 位 AES 密钥。


    IV's 和 salts 是完全独立的术语,尽管经常混淆。在您的问题中,您还将位和字节、密钥大小和块大小以及彩虹表与 MD5 表混淆(没有人说加密很容易)。有一件事是肯定的:在密码学中,尽可能安全是值得的;冗余安全通常不是问题,除非你真的(真的)负担不起额外的资源。


    当您了解这一切的工作原理后,我会认真地为您找到一个执行 PBE 加密的库。您可能只需要输入密码、盐、纯数据和 - 如果单独配置 - IV。

    [编辑] 你现在应该寻找一个使用 Argon2 的库。 PBKDF2 仍然被认为是安全的,但在某些情况下它确实给攻击者带来了不公平的优势,让攻击者执行的计算少于该函数的普通用户。对于 PBKDF / 密码哈希来说,这不是一个好的属性。

    【讨论】:

    • 我已经了解了 AES 加密,所以你的回答有点冗长。如果我混淆了任何术语,那只是出于表达的懒惰/模糊。我已经同意冗余安全性并将使用盐。
    • 它必须很长,因为你的问题有几个问题需要处理,我看不到人们的想法。此外,它可能会帮助其他有类似问题的人。无论如何,我每分钟输入 > 300 个字符(在好日子)。
    • @MaartenBodewes 经过几个小时的谷歌搜索,我终于明白了盐和 IV 到底是什么。在 CBC 链接模式下,IV 的大小是否始终为 16 字节。
    • 嗯,似乎错过了最后一条评论。 CBC 模式下 IV 的大小确实必须始终为 16 个字节 - 否则您将无法与它(在加密期间)对一个完整的明文块进行异或。通常,实现会检查 IV 是否具有此特定大小。
    【解决方案2】:

    如果您在谈论 AES-CBC,那么它是一个初始化向量 (IV),而不是 Salt。通常的做法是将 IV 作为加密消息的第一个块以明文形式发送。 IV不需要保密。然而,它应该随着每条消息而改变——一个恒定的 IV 意味着你的第一个块实际上是在 ECB 模式下加密的,这并不安全。

    【讨论】:

    • 是的,但我的问题是,如果密钥小于 32 位,我是否也应该对密钥加盐而不是填充它。 iv 和可能的 salt 都是随机的,并与每条消息一起存储。
    • @user1122069 AES 的密钥必须是 128、192 或 256 位。您是在说这里的密钥派生函数,它需要一些用户输入的密码并将其转换为密钥?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2011-08-22
    • 2011-01-03
    相关资源
    最近更新 更多