为 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+时间,它可能会或可能不会很关键,这取决于整个系统。)但它应该在代码库中修复并在下一个正常版本中部署。