11.5. 密码学算法与协议

通常,密码学算法和协议对于保持系统安全是必要的,尤其是在通过不受信任的网络(如互联网)进行通信时。在可能的情况下,使用密码学技术来验证信息的真实性并保持信息的私密性(但不要认为简单的加密会自动验证身份)。通常,您需要使用一套可用的工具来保护您的应用程序。

对于背景信息和代码,您应该查看经典著作《应用密码学》[Schneier 1996]。新闻组“sci.crypt”有一系列常见问题解答 (FAQ);您可以在许多位置找到它们,包括 http://www.landfield.com/faqs/cryptography-faq。Linux 相关的资源包括 Linux 加密 HOWTO,网址为 http://marc.mutz.com/Encryption-HOWTO/。有关协议如何使用基本算法的讨论,请参见 [Opplinger 1998]。有关如何在协议中应用密码学的有用论文集,请参见 [Stallings 1996]。以下只是一些评论;这些领域相当专业,并在其他地方进行了更全面的介绍。

密码学协议和算法很难正确实现,因此不要创建您自己的。相反,如果可以,请使用广泛使用、经过深入分析并被公认为安全的协议和算法。当您必须创建任何东西时,请进行广泛的公开审查,并确保专业的安全分析师检查是否存在问题。特别是,除非您是密码学专家,了解自己在做什么,并计划花费数年时间对算法进行专业审查,否则不要创建您自己的加密算法。创建(任何好的)加密算法是专家的任务。

许多算法都已获得专利;即使所有者目前允许“免费使用”,但如果没有签署合同,他们总是可以在以后改变主意,使您以后面临极大的风险。一般来说,应避免所有已获得专利的算法——在大多数情况下,都有一种未获得专利的方法,其技术上至少与已获得专利的方法一样好甚至更好,并且这样做可以避免大量的法律问题。

另一个复杂之处在于,许多国家都以某种方式监管或限制密码学。有关法律问题的调查可在“密码法调查”网站 http://rechten.kub.nl/koops/cryptolaw/ 上找到。

通常,您的软件应提供一种拒绝“太小”密钥的方法,并让用户设置“太小”的含义。对于 RSA 密钥,512 位太小而无法使用。越来越多的证据表明,1024 位 RSA 密钥也不够用;Bernstein 提出了简化暴力破解 RSA 的技术,以及基于此的其他工作(例如 Shamir 和 Tromer 的“使用 TWIRL 设备分解大数”),现在表明 1024 位密钥可以在一年内被价值 1000 万美元的设备破解。如果您真的想要一个安全的系统,您可能需要将 2048 位作为 RSA 的最小值,如果您计划在 2015 年之后使用这些密钥,则尤其应该这样做。有关 RSA 的更多信息,请参阅 RSA 对 Bernstein 工作的评论。有关密钥长度和其他一般密码学算法问题的更一般性讨论,请参阅 NIST 2001 年 11 月的密钥管理研讨会

11.5.1. 密码学协议

当您需要安全协议时,请尝试使用符合标准的协议,例如 IPSec、SSL(即将成为 TLS)、SSH、S/MIME、OpenPGP/GnuPG/PGP 和 Kerberos。每种协议都有其优点和缺点;它们中的许多协议在功能上有些重叠,但每种协议都倾向于在不同的领域中使用

这些协议中的许多协议都允许您选择许多不同的算法,因此您仍然需要为算法选择合理的默认值(例如,用于加密)。

11.5.2. 对称密钥加密算法

许多国家/地区都限制加密算法实现的用途、出口和/或进口,并且法律可能会快速变化。在尝试构建使用密码学的应用程序之前,请先了解规则。

对于密钥(批量数据)加密算法,仅使用已公开出版并经受多年攻击的加密算法,并检查其专利状态。我建议使用新的高级加密标准 (AES),也称为 Rijndahl——许多密码学家对其进行了分析,没有发现任何严重的弱点,并且我相信它已经过充分的分析,现在可以信任了。但是,在 2002 年 8 月,研究人员 Fuller 和 Millar 发现了一种密码的数学属性,虽然不是攻击,但可能会被利用进行攻击(这种方法实际上可能对其他一些算法也产生严重后果)。因此,值得继续关注未来的工作。AES 的一个很好的替代方案是 Serpent 算法,它速度稍慢,但非常抗攻击。对于许多应用程序,三重 DES 是一种非常好的加密算法;它具有相当长的密钥(112 位)、没有专利问题,并且具有非常长的抵御攻击的历史(它抵御攻击的时间比公共文献中任何其他具有合理密钥长度的加密算法都长得多,因此它可能是最安全的公开可用的对称加密算法,如果实现得当的话)。但是,三重 DES 在软件实现中非常慢,因此三重 DES 可以被认为是“最安全但最慢的”。Twofish 似乎是一种很好的加密算法,但仍存在一些挥之不去的问题——Sean Murphy 和 Fauzan Mirza 表明 Twofish 具有使许多学者担忧的特性(尽管到目前为止,还没有人设法利用这些特性)。MARS 对“新颖”攻击具有很强的抵抗力,但它更复杂,在小容量智能卡上不切实际。目前,我将避免使用 Twofish——很可能这种情况永远不会被利用,但这很难确定,并且还有其他没有这些担忧的替代算法。不要使用 IDEA——它受美国和欧洲专利的保护。不要使用愚蠢的算法,例如与常量或常量字符串进行异或运算、ROT(循环移位)方案、维吉尼亚密码等等——这些算法很容易被今天的计算机破解。不要使用“双重 DES”(使用两次 DES)——这会受到三重 DES 避免的“中间人”攻击。无论如何,您的协议应支持多种加密算法;这样,当加密算法被破解时,用户可以切换到另一种算法。

对于对称密钥加密(例如,用于批量加密),如果您希望信息在 2016 年之前保持秘密,则不要使用少于 90 位的密钥长度(每增加 18 个月的安全性,再增加一位)[Blaze 1996]。对于加密无价值的数据,旧的 DES 算法有一些价值,但使用现代硬件,使用暴力破解 DES 的 56 位密钥太容易了。如果您正在使用 DES,不要只是使用 ASCII 文本密钥作为密钥——奇偶校验位在最低(而不是最高)有效位中,因此大多数 DES 算法将使用攻击者熟知的密钥值进行加密;相反,创建密钥的哈希值并正确设置奇偶校验位(并注意来自您的加密例程的错误报告)。所谓的“可导出”加密算法的有效密钥长度仅为 40 位,基本上毫无价值;在 1996 年,攻击者可以花费 10,000 美元在 12 分钟内破解此类密钥,或者使用空闲计算机时间在几天内破解它们,并且在任何一种情况下,破解时间每 18 个月减半。

分组加密算法可以在多种不同的模式下使用,例如“电子密码本” (ECB) 和“密码分组链接” (CBC)。在几乎所有情况下,都使用 CBC,并且不要使用 ECB 模式——在 ECB 模式下,相同的数据块总是会在流中返回相同的结果,这通常足以泄露加密的内容。许多模式,包括 CBC 模式,都需要一个“初始化向量” (IV)。IV 不需要是秘密的,但它需要是攻击者无法预测的。不要跨会话重用 IV——每次启动会话时都使用新的 IV。

有许多不同的流加密算法,但其中许多算法都有专利限制。我不知道 WAKE 存在任何专利或技术问题。RC4 曾是 RSA Data Security Inc 的商业秘密;它自那时起已被泄露,并且我不知道对其使用有任何真正的法律障碍,但 RSA Data Security 经常威胁要对用户采取法律行动(目前尚不清楚 RSA Data Security 可以做什么,但毫无疑问,他们可以将用户卷入毫无价值的诉讼案件中)。如果您使用 RC4,请按预期使用它——特别是,始终丢弃它生成的前 256 个字节,否则您将容易受到攻击。SEAL 已获得 IBM 的专利——因此不要使用它。SOBER 已获得专利;专利所有者声称,如果请求许可,它将允许许多用途免费使用,但这为以后的使用设置了障碍。更有趣的是,分组加密算法可以以将它们变成流密码的模式使用,并且想要流密码的用户应该考虑这种方法(您将能够在更多公开可用的算法之间进行选择)。

11.5.3. 公钥算法

对于公钥密码学(除其他外,用于签名和发送密钥),只有少数几种广泛部署的算法。最广泛使用的算法之一是 RSA;RSA 的算法已获得专利,但仅在美国获得专利,并且该专利已于 2000 年 9 月到期,因此 RSA 可以自由使用。永远不要使用 RSA 直接解密或签名攻击者直接给您的原始值并公开结果,因为这可能会泄露私钥(这在实践中不是问题,因为大多数协议都涉及签名用户计算的哈希值——而不是原始值——或者不公开结果)。永远不要多次解密或签名完全相同的原始值(原始值可能会被泄露)。所有这些都可以通过始终添加随机填充(PGP 就是这样做的)来解决——通常的方法称为最佳非对称加密填充 (OAEP)。

Diffie-Hellman 密钥交换算法被广泛用于允许双方就一个会话密钥达成一致。就其本身而言,它不能保证各方是他们所说的那样,也不能保证没有中间人,但它确实有助于抵御被动监听者;其专利已于 1997 年到期。如果您使用 Diffie-Hellman 创建共享密钥,请务必先对其进行哈希处理(如果您直接使用其共享值,则会受到攻击)。

NIST 开发了数字签名标准 (DSS)(它是 ElGamal 密码系统的修改版),用于数字签名生成和验证;其开发条件之一是无专利。

与典型的对称密钥相比,RSA、Diffie-Hellman 和 El Gamal 的技术需要更多的密钥位才能获得同等安全性;在这些系统中,1024 位密钥应该大致相当于 80 位对称密钥。512 位 RSA 密钥被认为是完全不安全的;Nicko van Someren 已经证明,使用仅有的现有办公硬件(更不用说为这项工作设计的设备),可以在 6 周内分解如此小的 RSA 密钥。过去,1024 位 RSA 密钥被认为是相当安全的,但最近在分解算法方面的进步(例如,D. J. Bernstein 的进步)引发了人们的担忧,即 1024 位对于 RSA 密钥来说可能还不够。当然,如果您的应用程序需要高度安全或持续到 2015 年以后,您应该使用 2048 位密钥。

如果您需要需要更少位数的公钥(例如,对于智能卡),那么您可以使用椭圆曲线密码学(IEEE P1363 有一些建议的曲线;找到曲线很困难)。但是,请注意——椭圆曲线密码学没有获得专利,但某些加速技术已获得专利。椭圆曲线密码学速度足够快,以至于它实际上不需要这些加速,即可用于加密会话/批量加密密钥的常用用途。一般来说,您不应该尝试使用椭圆曲线密钥进行批量加密;对称算法速度更快,并且经过更好的批量加密测试。

11.5.4. 密码学哈希算法

某些程序需要单向密码学哈希算法,即一种接受“任意”数量的数据并生成固定长度数字的函数,攻击者很难反转该数字(例如,攻击者很难创建不同的数据集来生成相同的值)。多年来,MD5 一直是首选,但最近的努力表明,其 128 位长度可能不够用 [van Oorschot 1994],并且某些攻击会削弱 MD5 的保护 [Dobbertin 1996]。事实上,有传言说一位顶级行业密码学家已经破解了 MD5,但受雇员协议的约束而保持沉默(请参阅 John Viega 于 2000 年 8 月 22 日发布的 Bugtraq 帖子)。任何人都可以制造谣言,但已经发现的弱点足以使完成破解的想法变得合理。如果您正在编写新代码,请使用 SHA-1 而不是 MD5。不要使用原始 SHA(现在称为“SHA-0”);SHA-0 具有与 MD5 相同的弱点。如果您需要在哈希算法中使用更多位,请使用 SHA-256、SHA-384 或 SHA-512;您可以在 NIST FIPS PUB 180-2 中获得规范。

11.5.5. 完整性检查

通信时,您需要某种完整性检查(不要仅仅依赖加密,因为攻击者可以诱导信息更改为“随机”值)。这可以使用哈希算法来完成,但不要直接使用哈希函数(这会将用户暴露于“扩展”攻击——攻击者可以使用哈希值,添加他们选择的数据,并计算新的哈希值)。常用的方法是“HMAC”,它将完整性检查计算为
  H(k xor opad, H(k xor ipad, data)).
其中 H 是哈希函数(通常为 MD5 或 SHA-1),k 是密钥。因此,完整性检查通常是 HMAC-MD5 或 HMAC-SHA-1。请注意,虽然 MD5 有一些弱点,但据我所知,MD5 在此构造中使用时不会受到攻击,因此 HMAC-MD5(据我所知)是可以的。这在 IETF RFC 2104 中有详细定义。

请注意,在 HMAC 方法中,接收者可以伪造与发送者相同的数据。这通常不是问题,但如果必须避免这种情况,则使用公钥方法,并让发送者使用发送者私钥“签名”数据——这避免了这种伪造攻击,但成本更高,并且对于大多数环境来说不是必需的。

11.5.6. 随机消息身份验证模式 (RMAC)

NIST 开发并提出了一种新的模式,用于使用称为 随机消息身份验证码 (RMAC) 的密码学算法。RMAC 旨在用作消息身份验证码技术。

尽管有一个正式证明表明 RMAC 是安全的,但该证明取决于高度成问题的假设,即底层密码学算法符合“理想密码模型”——特别是,该算法可以抵抗各种专门的攻击,包括相关密钥攻击。不幸的是,对于许多算法,相关密钥攻击的研究不足;这不是大多数人在分析密码学算法时会担心的那种属性或攻击。众所周知,三重 DES 没有此属性,并且不清楚 AES 等其他广泛接受的算法是否具有此属性(似乎 AES 至少比通常的攻击更弱地抵抗相关密钥攻击)。

目前最好的建议是“不要使用 RMAC”。还有其他方法可以进行消息身份验证,例如 HMAC 与密码学哈希算法相结合(例如,HMAC-SHA1)。HMAC 不是同一回事(例如,从技术上讲,它不包括 nonce,因此您应该更快地重新密钥),但 HMAC 的理论弱点仅仅是理论上的,而 RMAC 中的问题在现实世界中似乎更为重要。

11.5.7. 其他密码学问题

您应该对重要数据进行加密并包含完整性检查。不要依赖加密也提供完整性——攻击者可能能够将位更改为不同的值,尽管攻击者可能无法将其更改为特定值,但仅更改值可能就足够了。一般来说,您应该对完整性和保密性使用不同的密钥,以避免某些微妙的攻击。

一个经常被忽视的问题是“流量分析”问题。也就是说,即使消息被加密并且加密未被破解,对手也可能仅从加密消息中了解大量信息。例如,如果两家公司的总裁开始交换许多加密电子邮件,则可能表明这两家公司正在考虑合并。再举一个例子,许多 SSH 实现已被发现存在交换密码的弱点:观察者可以查看数据包并确定密码的长度(或长度范围),即使他们无法确定密码本身。他们还可以确定有关密码的其他信息,这些信息极大地帮助了破解密码。

务必不要使问题可以分部分解决,并在信任环境(谁受信任)发生变化时使用不同的密钥。不要长时间使用相同的密钥——过一段时间后,更改会话密钥或密码,以便对手必须重新开始。

通常,您应该压缩您将要加密的内容——这确实添加了一个固定的标头,这不是很好,但它消除了消息其余部分中的许多模式,并使结果更小,因此如果压缩可能会使结果更小,那么它通常被视为“双赢”。

在相关说明中,如果您必须创建自己的通信协议,请检查以前发生的问题。诸如 Bellovin [1989] 对 TCP/IP 协议套件中安全问题的回顾、Bruce Schneier [1998] 以及 Mudge 对 Microsoft 的 PPTP 实现的破解及其后续工作等经典著作可能会对您有所帮助。同样,请务必对任何新协议进行广泛的公开审查,并尽可能重用您可以重用的内容。