是否有为互联网流等设计的高速密码而不牺牲安全性?有很多选项可以在流模式下运行。如何选择密码?
如何选择流密码
默认情况下使用 AES。AES 是一种分组密码,即在给定密钥的情况下,将块值(在 AES 的情况下为 128 位)映射到相同大小的其他块值的函数。要加密消息,必须以链接模式使用分组密码,该模式告诉输入数据应如何拆分、加密和再次组合。几乎所有模式都允许流式传输(在旅途中加密大量消息,而不必将其完全存储在 RAM 或磁盘中)。好的模式结合了加密和完整性检查,请参阅EAX和GCM。在传统的纯加密模式中,目前是CBC,较新的是CTR;CTR 的优点是不需要填充,因为它将x字节的序列完全加密为x字节,对于所有x,而 CBC 需要长度为块大小倍数的输入。
我的 PC 上有一个 2.4 GHz Core2 Intel CPU。这远不是目前最好的,而且很快就会接近“过时”,至少在商业上是这样。不过,当我运行 OpenSSL 基准测试工具时:
$ openssl speed aes-128-cbc
(...)
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
aes-128 cbc 108028.29k 147211.99k 161986.82k 166308.90k 167286.10k
因此处理器可以以每秒 167 MB 的惊人速度加密数据;那是使用单核。我的 PC 有四个核心,因此即使以可以通过千兆以太网的最大带宽加密数据也只会使用 15% 的 CPU 资源。真正使加密成为瓶颈需要一个非常特殊的应用程序。
在带有AES-NI指令的更新的 x86 处理器上,事情甚至会快一个数量级。这些指令允许以每个数据字节少于 2 个时钟周期的速率加密数据;如果您愿意,它可以超过每秒千兆字节。请注意,这比典型硬盘的速度快 10 倍左右。AES-NI 指令还包括pclmulqdq操作码,这在处理 GCM 模式时有很大帮助。
然而,在某些特殊情况下,AES 的原始速度是不够的(当然,包括没有AES-NI 指令的机器)。对于这些,人们可能会说分组密码是一种通用的原语,也许一种专门为加密长流而设计的算法,但不能做任何其他事情,可能会更快地处理数据。这些被称为流密码。一个古老的、众所周知的、稍弱的、实际上不是那么快的流密码是RC4。电子流项目从 2004 年到 2008 年作为一种公开竞赛进行,有流密码候选者和公开评论和研讨会,并产生了从安全和性能角度来看“看起来不错”的流密码组合(他们没有在比 AES 更严格,但他们仍然得到了公平的份额)。有四个针对软件平台优化的密码,三个针对硬件设计。它们都未获得专利并且可以免费使用(Rabbit 正在申请专利,但在 2008 年 10 月它被发布到公共领域)。
流密码比分组密码具有优势的应用示例实际上与安全无关:这是繁重的数字模拟,需要稳定的高质量随机值流。流密码产生高质量的随机性(它们的设计使得即使故意寻找它们也不会发现偏差,而定制的非加密随机数生成器往往依赖于运气——手头的问题不会发生达到 RNG 的已知偏差之一)。为此,我成功地使用了 eSTREAM 组合流密码之一 Sosemanuk。
无论哪种方式,分组密码和流密码都需要适当的IV管理。IV 是一个不需要保密但必须具有某些特定属性的参数。对于某些密码,没有两条消息使用相同的密钥和相同的 IV 加密就足够了。其他一些(包括CBC模式)需要更多一点,即在可能的IV空间中以均匀概率为每条消息选择IV。无论如何,IV 必须为接收者所知,因此习惯上在加密消息的标头中发送它。RC4 流密码没有 IV:一个给定的密钥绝不能用于多个消息。IV 管理是您会遇到安全问题的地方,因为它经常被忽视并且不容易做到正确。
总结:使用适当加密模式的AES;您还需要完整性检查,因此 GCM 等组合模式是个好主意。注意你的静脉注射。仅当您发现 AES 是不可避免的瓶颈时,才设想切换到其他东西,因为这种情况很可能不会发生。