初始化向量-最佳实践(对称密码学)

que*_*ery 6 cryptography aes encryption-symmetric

我想询问有关使用初始化向量 (IV) 和对称加密算法密钥的最佳实践。

\n\n

我想接受来自客户端的消息,对其进行加密并存储在后端。这将在一段时间内完成,稍后会有请求汇集消息并以可读的形式返回它们。

\n\n

据我所知,在加密多个单独的消息时,密钥可以是相同的。IV 应该随着每个新的加密而改变。然而,这会导致问题,因为每条消息都需要不同的 IV 以便稍后解密。

\n\n

我\xe2\x80\x99d想知道这是否是最好的方法。有没有办法避免在每条消息中存储 IV,从而简化加密/解密的整个过程?

\n

Gil*_*il' 7

IV 选择有点复杂,因为具体要求取决于操作模式。但是,有一些一般规则:

\n\n
    \n
  • 使用随机 IV 不会出错\xc2\xb9,除非在允许这样做的模式下使用较短的 IV。
  • \n
  • 切勿将相同的 IV 与相同的密钥一起使用。
  • \n
  • 如果您只使用给定密钥加密单个消息,则 IV 的选择并不重要\xc2\xb2。
  • \n
  • 选择独立于要加密的数据的 IV。
  • \n
  • 永远不要使用欧洲央行。
  • \n
\n\n

最常见的具体操作模式:

\n\n
    \n
  • CBC要求IV统一随机生成。不要使用计数器作为 CBC 的 IV。此外,如果您要加密的某些数据包含从第三方收到的部分,请在完全收到数据之前不要透露 IV。
  • \n
  • CTR使用IV作为计数器的初始值,该值针对每个块而不是每个消息递增,并且每个块的计数器值需要是唯一的。对于所有现代对称密码(包括 AES,无论密钥大小),一个块都是 16 个字节。因此,对于 CTR,如果您使用 0 作为 IV 加密 3 块消息(33 到 48 字节),则下一条消息必须以 IV=3(或更大)开始,而不是 IV=1。
  • \n
  • Chacha20、GCM、CCM、SIV 等现代模式使用随机数作为其 IV。当一种模式被描述为使用随机数而不是 IV 时,这意味着唯一的要求是 IV 永远不会与相同的密钥一起重复使用。它不一定是随机的。
  • \n
\n\n

当加密数据库中的数据时,使用行 ID(或从中派生的值)作为 IV 通常是不安全的。仅当行从未更新或删除时,使用行 ID 才是安全的,因为否则第二次使用相同 ID 存储数据时,将会重复 IV。看到使用相同密钥和 IV 加密的两条不同消息的对手很可能能够解密这两条消息(详细信息取决于模式以及攻击者可以猜测消息内容的程度;请注意,即使是较弱的猜测,例如 \ xe2\x80\x9cit\ 的可打印 UTF-8\xe2\x80\x9d 可能就足够了)。

\n\n

除非您有充分的理由不这样做(仅每行保存几个字节并不能算是一个很好的理由)并且密码学家已经审查了您存储和检索数据的具体方式:

\n\n
    \n
  • 使用经过身份验证的加密模式,例如 GCM、CCM、SIV 或 Chacha20+Poly1305。

  • \n
  • 如果您可以在某处存储一个计数器,并确保只要您继续使用相同的加密密钥,它就永远不会重置,那么每次加密消息时:

    \n\n
      \n
    1. 增加计数器。
    2. \n
    3. 使用计数器的新值作为经过身份验证的加密的随机数。
    4. \n
    \n\n

    先递增计数器的原因是,如果进程被中断,会导致跳过计数器值,这不是问题。如果在没有执行步骤 1 的情况下执行步骤 2,则会导致重复随机数,这是不好的。使用此方案,如果模式允许,您可以将随机数长度减少几个字节,只要长度对于您要加密的消息数量来说足够大。

  • \n
  • 如果您没有这样的计数器,则使用最大随机数长度并生成随机计数器。使用最大随机数长度的原因是,由于生日悖论,当消息数量接近 2 n /2时,随机的n位随机数预计会重复。

  • \n
  • 无论哪种情况,您都需要将随机数存储在行中。

  • \n
\n\n

\xc2\xb9假设一切都正确实现,例如需要使用适合密码学的随机生成器生成随机值。
\n\xc2\xb2只要它不是以依赖于密钥的方式选择的。

\n