生成 IV 的两种方法

信息安全 随机的 初始化向量
2021-09-09 19:30:49

我正在查看一些代码,在特定情况下,代码需要生成两个 IV。

第二个 IV 生成代码仅使用 C# Rijndael GenerateIV()

第一个 IV 生成代码虽然获取了 MAC 地址的一部分和当前时间的一部分,但将这些数据的片段插入到一个 16 字节的数组中。

然后,在这两段代码中,生成的 IV 通过获取 IV 的散列,然后获取一些随机字节并重新散列来处理恒定的 X 次。

问题

  • 您看到两种生成 IV 的方法有什么好处吗?
  • 后 IV 生成散列是必要的还是矫枉过正的?- 它是标准化的东西还是一些晦涩的想法?
  • 是否存在 GenerateIV 函数不提供随机数据的任何场景或配置?

笔记:

  • 这些 IV 旨在用于加密
  • CipherMode 是 CBC
2个回答

为 CBC 模式生成 IV 的正确方法是使用密码安全的随机生成器。在某些情况下,非随机 IV 是可以的,但除非您仔细分析您的系统以确保您属于这些情况,否则您应该使用随机 IV。在极少数情况下,使用非随机 IV 无论如何都会有任何好处,因此请使用随机 IV。

我不熟悉C#API,但鉴于该文件GenerateIV状态,它“产生一个随机的初始化向量(IV)使用的算法”,它似乎产生了CBC的IV的有效方法(但CreateEncryptor已经做了同样的工作)。

严格来说,采用这些随机字节的散列是一种风险,因为它会降低 IV 的熵:加密散列不知道是满射的。(我假设您的意思是加密哈希,例如 SHA-256;非加密哈希肯定会有问题。)但是,我认为这没有任何具体问题:实际上,我认为它是无害的。

附加一些随机字节并再次重复散列应该同样安全。然而,这是不必要的复杂性。不必要的复杂性应该在任何安全环境中敲响警钟。这增加了实现错误的风险,例如泄漏机密数据(虽然这里不是一个大问题,因为 IV 不需要保密,但如果您正在生成密钥,这将是一个明确的考虑因素),覆盖数据由于缓冲区溢出或不正确的指针计算,在至少需要一次迭代时将迭代计数设为 0,等等。

如果没有额外的随机散列步骤,您提出的第二种方法绝对不安全。MAC 地址和时间是可预测的,而CBC 需要不可预测的 IV针对具有可预测 IV 的 CBC 的攻击并不适用于所有系统(它们依赖于对手能够提交消息进行加密),但为什么要冒险呢?此外,MAC 地址和时间不一定是唯一的:想想克隆的虚拟机、多线程程序、在同一时钟滴答中服务两个客户端的快速进程等。

通过额外的随机散列步骤,从 MAC 地址和时间开始应该与随机无法区分,前提是注入了足够的随机数据。但我们又回到了复杂性问题:你有多确定你做对了?

如果这种额外复杂性的原因是“让它更随机”……随机不会那样工作。你不能仅仅通过弄乱它来让随机变得更加随机,你会很容易把它弄乱并让它变得不那么随机。

除了随机 IV(例如使用GenerateIV之外,做任何事情都会增加维护成本(从您现在担心它所花费的时间开始)、降低性能并增加风险。因此,只需使用随机 IV。

如果部署代码的更新版本很昂贵,这不是一个关键问题。(如果 IV 只是 MAC+时间,它可能会或可能不会很关键,这取决于整个系统。)但它应该在代码库中修复并在下一个正常版本中部署。

安全的伪随机数生成器(CSPRNG) 与您将获得的一样安全。您指向的两个参考都是 CSPRNG,因此对于 IV 来说应该足够了。散列不会使随机变得更加随机。使用两种不同的机制是没有意义的,而且犯错的机会会加倍。

在 的情况下GenerateIV,事情已经是随机的,因此随后的散列和添加更多随机数据无济于事。

使用 MAC 地址和时间来创建初始数组似乎毫无意义,因为它们都远非秘密。如果攻击者知道计算机的 MAC 地址和时间,他们就可以快速猜出确切的时间戳。所以这个 IV 创建的所有随机性都来自最后添加的随机字节。也许这就足够了,如果没有看到实际代码,我就无法判断。

请注意,根据Kercckhoff 原理,使用秘密算法不会获得额外的好处。

我的建议是简单地使用来自GenerateIV您的 IV 的数据,并在所有情况下都这样做。