认证加密





5.00/5 (33投票s)
使用 Crypto++ 执行认证加密。
引言
验证加密数据完整性的概念在20世纪70年代出现在银行业。ANSI X9委员会详细研究了这个问题,后来由Katz和Yung [13] 正式化。银行不想传输数据并允许攻击者在不被发现的情况下翻转一个位。在这种情况下,攻击者**不会**解密消息,而是只会翻转一个位,以便将加密消息“Post $100”更改为“Post $700”。
尽管数据认证的概念已经存在一段时间,但直到最近十年,认证加密才成为“单一的加密操作”,而不是两种不同操作的组合。本文将介绍 Crypto++ 中提供的三种认证加密模式:EAX、CCM 和 GCM。本文还将探讨错误组合加密和认证的示例。
许多没有正式接触过密码学的初学者常常犯只加密数据的错误。不包含认证数据的明显原因在于,大多数示例代码只提供加密(或许还有解密)函数的示例,缺乏任何上下文。认证步骤是文档中其他地方的另一个主题。初学者根本不知道加密必须与认证结合使用。
对于那些包含身份验证保证的人来说,正确地将其纳入可能很困难。正如 Bellare、Rogaway 和 Wagner 在《一种传统的认证加密模式》中写道
...当人们试图将传统的(仅提供隐私的)加密方案和消息认证码(MAC)结合起来时,做得相当糟糕。[1]
在《CWC 认证加密(关联数据)模式》中,Kohno、Whiting 和 Viega 写道
...将安全的加密方案与安全的 MAC 意外结合,仍然很容易得到不安全的认证加密方案。[12]
许多人说,密码学很少是一个系统中最薄弱的部分。对于一个好的实现来说,这通常是正确的。但之所以提供本文,是因为由于经验不足的程序员实现他们不理解的系统(审查 MSDN 示例不足以设计安全组件),领域中存在大量糟糕的密码学。有很多方法可以搞砸这些东西,有时以不易察觉的微妙方式。因为密码学很容易出错,所以我不想引导人们走上另一个糟糕实现的道路。但经验不足的人应该了解加密最佳实践。本文所讨论的大部分内容都是我在实践中遇到的。
最后,如果您**确实**有一个可行的应用程序,您应该考虑咨询一名执业密码学家或安全顾问。在大学和 Usenet 的 sci.crypt 上可以找到许多这样的人。
背景
认证加密,也称为 **authenc**,是同时加密和认证数据的过程。该过程将一个认证器(也称为 **tag**)与数据关联起来。明文通过认证器转换为密文。因此,认证加密操作的输出是 {密文,tag} 对。当需要解密数据时,密文将使用 tag 进行验证。设想认证器最简单的方法是将其视为共享密钥或对称密钥系统中的数字签名。
认证加密主要分为两大类:**AE** [13,14] 和 **AEAD** [15]。AE 家族是一种使用对称密钥将消息 *M* 转换为密文 *C* 的认证加密方案,其中 *C* 提供保密性和认证保证。后来,人们意识到并非所有数据都需要加密,这导致了 AEAD 方案的开发。AEAD 系统提供与 AE 方案类似的常规认证加密,以及对**关联数据**(AEAD 中的“AD”)的认证保证。关联数据也称为**头部**、**附加数据**和**附加认证数据**。附加数据不加密——它只进行认证——并以明文形式发送。
EAX、CCM 和 GCM 都是 AEAD 方案。如果只需要认证加密或仅需认证,我们仍然可以使用这些模式。我们只需将缺失成员的长度指定为 0。这些方案旨在提供这种级别的灵活性。最后,这些模式通常会指定一个默认的标签大小以实现互操作性。默认大小通常为 12 或 16 字节(96 或 128 位)。使用较小的标签时,会对完整标签大小进行简单的截断。由接收方决定是否接受截断(但有效)的标签。
NIST 和 FIPS
在实际应用中,有许多可用的认证加密模式——访问 NIST 的模式开发页面就列出了11种。请注意,并非所有这11种模式都获得美国联邦政府的批准使用。提议的模式包括 EAX、CWC 和 OCB。但只有 CCM 和 GCM 获得了美国联邦政府的批准使用。CCM 模式在SP 800-38C中指定,GCM 模式在SP 800-38D中指定。
认证加密是一种指定分组密码操作的算法——因此它被称为操作模式。大多数模式,如ECB、CBC、OFB、CFB和CTR,我们都已经很熟悉了。这五种模式被称为加密模式——它们只提供隐私。除了加密模式和认证加密模式,NIST还认可一种认证模式(不含加密)。这种模式是CMAC,它在SP 800-38B中指定。
Crypto++
Crypto++ 由 Wei Dai 编写。源文件可以从 www.cryptopp.com 下载,或者从 SourceForge SVN 仓库获取。本文要求使用库版本 5.6。有关编译和集成问题,请访问 将 Crypto++ 集成到 Microsoft Visual C++ 环境中。本文基于前面提到的文章中提出的假设。对于对其他 C++ 加密库感兴趣的人,请参阅 Peter Gutmann 的 Cryptlib 或 Victor Shoup 的 NTL。
人们似乎在设置头文件和库路径方面遇到最多的问题,所以请务必阅读上面的文章。如果您遇到编译或链接错误,上面的文章列出了几乎所有可能遇到的问题及其解决方案。要了解 Crypto++ 支持的其他机密操作模式,请参阅应用 Crypto++:分组密码。
使用 Crypto++ 时,请理解该库采用管道式设计:数据从源流向汇。这种设计类似于 Unix 管道。源和汇之间是转换数据的过滤器。在下面的代码中,源和汇以及过滤器都相当明显。`StringSource` 中的 `true` 参数只是指示源立即发送所有数据——不要缓冲数据。最后,过滤器需要一个加密或解密对象作为参数——这些对象类似于函数指针,但没有令人不快的声明和语法。
GCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(...);
StringSource( plaintext, true,
new AuthenticatedEncryptionFilter(
encryptor,
new StringSink( ciphertext )
)
);
在上面的代码中,`AuthenticatedEncryptionFilter` 为我们处理了一切:从填充到输出缓冲区的大小调整。我们通过 `ciphertext.data()` 访问密文的字节,其大小为 `ciphertext.size()`。密文可能包含嵌入的 `NULL`,但这对于标准库字符串来说无关紧要——字符串有明确的长度。最后,使用 `new` 创建的对象会自动销毁。无需管理指针。
仅加密是不够的
如果您是认证加密的新手,请考虑以下仅使用加密的示例。我们的目标只是发送加密消息或将加密数据持久化到磁盘。为了强调消息认证的重要性,该示例将以许可系统的形式进行阐述。由于 .NET/XML 流行,我们还将使用人类可读的字符串来模拟 XML 文档。我们的字符串是:**Licenses: 10**。我发现这个示例**总是**能引起管理层的注意。
下面的代码可以作为示例1获取。我们使用Crypto++在随机密钥和随机IV下加密许可证字符串。我们使用NIST批准的分组密码(AES)和NIST批准的操作模式(CFB)。然后我们篡改第11个字节。最后,我们检查恢复的文本。
![]() |
图1:篡改后恢复的明文
|
尽管我们加密了 _Licenses:10_,但我们恢复了 _Licenses: 30_。最令人担忧的是无法检测到修改——密文总是解密为 _Licenses: 10_ 或 _Licenses: 30_,两者都看起来有效。如果攻击者选择 `ciphertext[10] |= 4`,他可以强制恢复为 _Licenses: 50_。
![]() |
图2:修改密文1位的影响
|
图2显示了第一个样本的多次运行。请注意,从未遇到不可打印字符。更糟糕的是,概率甚至不是50%:攻击者有超过60%的时间可以从系统中获得_Licenses: 30_(并且随着对第11个字节中的位进行更多修改,情况会变得更糟)。在图3中,密文中的两位被修改:`ciphertext[10] |= 6`。这种更改导致升级87%的时间,并引入了两个额外的值:30和70!
![]() |
图3:修改密文2位的影响
|
任何使用“如果解密正确,则有效”方法的人都大错特错。事实上,《应用密码学手册》明确警告我们这种方法
一个常见的误解是,加密提供数据源认证和数据完整性,理由是如果一条消息使用只与方 A 共享的密钥解密,并且该消息有意义,那么它一定源自 A。[2]
糟糕的密码学的另一个副作用是主机被入侵。假设我们加密一条定义为以下内容的消息
struct {
int length;
byte* data
} MESSAGE, PMESSAGE;
我们选择了 AES,并在 CBC 模式下操作该密码。由于攻击者无需解密消息即可篡改消息,他会篡改字节 [0-3] 来修改长度,并可能用 shell 代码修改密文。应用程序执行解密并使用数据,即使长度尚未验证。应用程序的内部解析器将解释消息,但它没有任何机会。
如果您的业务线属于安全软件领域,那么这是您最不希望在 Security Focus 的 BugTraq 邮件列表中看到报告的内容。想象一下,一条加密消息——没有保障——被利用导致缓冲区溢出,以便攻击者随后可以获取 root 权限。在我看来,这听起来像是“整理你的简历”的时刻。
虽然很容易通过其他操作模式和冗余信息来纠正系统最初的不足,但该示例应该作为一个警告:**仅加密是不够的**。存在更复杂的攻击,它们将破坏其他操作模式并修改内置冗余,从而无法检测到篡改。
仅进行完整性检查是不够的
在研究为什么需要认证加密之前,我们应该快速查看两种通常不安全的方法。第一种方法使用 MAGIC 值,第二种方法使用哈希。
在上述示例中,我们篡改了字节 11,而字节 [0-9] 未受影响。在这方面,前 10 个字节是 MAGIC 值,证明了恢复文本的完整性。正如在构造下所 trivially 证明的那样,该机制存在缺陷(`C = Enc(MAGIC||m)` 也是如此)。
对于 HAC 中提供的构造,加密消息及其哈希的串联可能不安全。根据加州大学伯克利分校的 Wagner 博士的说法,“对于 Ek 的某些操作模式,Ek(h(m)||m) 可能是安全的,但细节可能有点复杂”[16]。因此,最好不要使用这些机制。
请注意,当 HAC 最初编写时,附加哈希以进行完整性验证的做法是可以接受的。不幸的是,情况发生了变化,该部分需要修订。有关该方法遭受的扩展攻击的讨论,请参阅 sci.crypt 上的_消息机密性和完整性 - 预置哈希与附加哈希_ [16]。
下表中,**Enc(x)** 为加密,**Hash(x)** 为无密钥哈希(如 SHA 或 Whirlpool)。请注意,以下列表不包括简单加密。
方法 | 协议 | 操作 (Operation) | 传输 |
魔法 | - | C = 加密(m||MAGIC) | C |
HAC, 9.6† | - | h = Hash(m), C = Enc(m||h) | C |
†《应用密码学手册》,第9.6节
先加密后认证
2001年,Hugo Krawczyk发表了《保护通信的加密和认证顺序》。在该论文中,Krawczyk提出了**通用组合**的概念。通用组合本质上将标准 CTR 模式加密与 CBC-MAC 消息认证的变体结合起来。使用通用组合,可以证明认证机制是安全的还是不安全的。
在论文过程中,Krawczyk 审查了三种常用的确保数据真实性的方法(这暗示了数据完整性)。每种方法都用于一个众所周知的协议,并显示在下面。请注意,下面的列表不包括简单的加密。
- 先认证后加密 (AtE) - SSL
- 先加密后认证 (EtA) - IPSec
- 加密和认证 (E&A) - SSH
该论文的结果证明,“先加密后认证”(IPSec)是安全的,在某些构造下,“先认证后加密”(SSL)也是安全的。然而,该论文还指出,“加密和认证”(SSH)是不安全的。两种可证明安全的“先认证后加密”构造是:
- 以 CBC 模式运行的分组密码
- 将数据与伪随机填充进行 XOR 运算的流密码
协议执行的操作如下所列。**Enc(x)** 是加密,**Auth(x)** 是消息认证码(也称为 MAC 或带密钥哈希)。
方法 | 协议 | 操作 (Operation) | 传输 |
AtE | SSL | a = Auth(m), C = Enc(m||a) | C |
EtA | IPSec | C = Enc(m), a = Auth(C) | C||a |
E&A | SSH | C = Enc(m), a = Auth(m) | C||a |
在 Krawczyk 的模型下,带有 CBC-MAC(正确构造)的计数器模式加密被证明是安全的。理解未提及的内容也很重要。例如,CFB 和 OCB 模式并非不安全。要确定其他模式的安全性,应分析组件之间的交互和整个系统。
CBC-MAC
MAC 是**消息认证码**。它是数字签名的对称密钥等效物(数字签名存在于公钥/私钥领域)。MAC 提供真实性和来源保证。如果收到密文并且密文上的 MAC 有效,我们以很高的概率假定消息来自我们的对等方并且未被篡改。
CBC-MAC 使用已知 IV 下的 CBC 加密残余来创建 MAC。残余是所有明文加密后剩余的反馈块。即使没有明文剩余,仍然有一个反馈块可用于下一次加密操作。残余将与密钥进行异或运算以生成 MAC。Wiki 和 Code Project 都包含对 CBC-MAC 的讨论。
在加密和认证合并为单一密码操作之前,系统通常会使用第一个密钥加密数据,然后使用第二个密钥对数据进行第二次处理。历史表明,CBC-MAC 有很多出错的方式。事实上,《应用密码学手册》再次警告我们
必须谨慎确保 MAC 和加密算法之间的依赖关系不会导致安全漏洞,并且通常建议这些算法应该独立。[5]
使用 CBC-MAC 时,有许多事情需要考虑。CBC-MAC 对于固定长度的消息是安全的;但单独使用时,CBC-MAC 对于可变长度的消息是不安全的。HAC 对这些考虑因素有很好的处理,并且是以下列表的来源。由于以下所有信息都来自《应用密码学手册》,因此仅引用页码。
- 加密操作和MAC操作互不影响——如果在认证机制中发现漏洞,加密数据不应受到影响(反之亦然)[p.367]
- 密钥必须独立——使用**相同的密钥**同时加密数据和认证数据(这将允许对数据进行**单次处理**)会导致密文独立于明文。因此,认证机制完全不安全 [p.367]
- CBC与异或校验和(CBCC)——由于认证机制的缺陷而不安全[p.368]
- CBC 与模 2n-1 校验和——由于选择明文攻击而不安全 [p.368]
- 明文-密文块链 (PCBC) - 由于已知明文攻击而不安全 [p.368]
- CBC-Pad - 对于可变消息长度不安全 [17]
语义认证
1996 年,David Wagner 和 Bruce Schneier 发表了《SSL 3.0 协议分析》。在论文中,Wagner 和 Schneier 引入了霍顿原则,即**语义认证**的概念。语义认证简单来说就是认证所表达的含义,而不是所说的话语。
例如,假设有明文需要保护。明文被填充到分组密码的大小,然后加密。填充操作引出了一个问题:_应该认证什么?_ 是仅明文还是明文和填充?根据 Wagner 和 Schneier 的说法,明文和填充都应该被认证(所表达的含义),而不仅仅是明文(所说的话语)。而逆否命题有助于我们找到无关数据:如果数据不需要加密或认证(即它没有价值),那么数据就不需要持久化或通信。
下面是两个我们如何应用霍顿原则的例子。以下假设各方之间存在共享密钥。在这些场景中加密或认证的内容并非完整清单。在使用基于 TCP/IP 的互联网时,您还需要担心删除、注入、重新排序和回放。TCP 虽然是面向连接的服务,但并非密码学上安全。
媒体 | 待加密 | 待认证 |
磁盘文件 | 明文消息, 消息长度 |
IV,磁盘扇区 |
互联网数据报 | 明文消息, 消息长度 |
IV,源IP/端口, 目的IP/端口 |
在上面的列表中,请注意长度是加密的而不是认证的。这样做是为了不泄露明文的实际大小(如果长度只经过认证,就会出现这种情况)。长度的处理(加密与认证)只是对实现整体安全性产生影响的细节之一。如果我们要使用 PKCS #5 等填充系统,我们就不需要显式的长度字段,因为填充可以以明确的方式移除。根据场景,{长度、明文、填充} 或 {明文、填充} 被加密和认证。
Crypto++ 实现
如果你已经走到这一步,你很可能相信认证加密是个好东西,CBC-MACs 棘手(但通过适当的计数器模式加密器可证明其安全性),并且最好使用现成的解决方案。这里是现成的解决方案。示例使用 AES,因为它是 NIST 唯一批准的分组密码。如果需要,可以使用 NESSIE 或 ISO 批准的分组密码,例如 Cameilla。此外,代码只执行认证加密——它不加密附加数据。有关使用两个通道(完整的 AEAD)的示例,请访问 Crypto++ wiki。
我们还擅自假定各方之间存在秘密密钥。摘录省略了密钥生成,但示例使用随机密钥和 IV。在实践中,密钥交换、密钥传输和密钥管理充其量是棘手的。回想 CBC-MAC 的讨论,需要两个独立的密钥:一个用于加密过程,一个用于认证过程。幸运的是,EAX、CCM 和 GCM 操作模式只需要一个密钥(就像使用保密模式一样)。认证加密模式将根据各自的规范为组件派生密钥。
AutoSeededRandomPool rng;
byte key[AES::DEFAULT_KEYLENGTH];
rng.GenerateBlock( key, sizeof(key) );
byte iv[AES::BLOCKSIZE];
rng.GenerateBlock( iv, sizeof(iv) );
EAX
要研究的第一个模式是 Bellare、Rogaway 和 Wagner 的 EAX。代码可在示例 2 中找到。EAX 在认证加密模式选择过程中被提交给 NIST。该模式未被选为 FIPS 标准。使用 EAX 的更详细信息,例如指定认证标签长度、使用任意大小的 IV 和使用附加数据,可在 Crypto++ wiki 中的EAX 模式下找到。
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
StringSource( plaintext, true,
new AuthenticatedEncryptionFilter(
encryptor,
new StringSink( ciphertext )
)
);
在上面的代码中,AES/EAX 加密器用于创建 { 密文,标签 } 对。过滤器会根据需要为我们处理填充,因此无需自行填充。与传统的 Crypto++ 模式(如 CBC)一样,我们可以使用 `SetKeyWithIV(key, sizeof(key), iv)` 来设置密码密钥。但是,EAX 提供无限 IV,因此最好使用重载:`SetKeyWithIV(key, sizeof(key), iv, sizeof(iv))`。解密同样容易执行,如下所示。
StringSource( ciphertext, true,
new AuthenticatedDecryptionFilter(
decryptor,
new StringSink( recovered )
)
);
如果操作没有抛出异常,则数据是真实的且可以使用。所有 Crypto++ 异常都派生自 std::exception,因此应该捕获 CryptoPP::Exception 或 std::exception。
GCM
GCM 是由 McGrew 和 Viega 创建的 Galois/计数器模式。它是一种 NIST 批准的模式,在伽罗瓦域上运行。代码可在示例 3 中找到。GCM 实现的独特之处在于,通过使用更大的预计算(以内存权衡为代价),可以提高模式的吞吐量。使用 GCM 的更详细信息,例如指定认证标签长度、使用任意大小的 IV、指定表大小和使用附加数据,可在Crypto++ wiki 中的GCM 模式下找到。
Crypto++ 的美妙之处在于组件可以轻松地替换。在下面,代码中唯一的更改是换入 GCM。所以我们现在有一个 AES/GCM 密码
GCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key, sizeof(key), iv);
StringSource( plaintext, true,
new AuthenticatedEncryptionFilter(
encryptor,
new StringSink( ciphertext )
)
);
///////////////////////////////////
// Transmit or persist ciphertext
///////////////////////////////////
GCM<AES>::Decryption decryptor;
decryptor.SetKeyWithIV(key, sizeof(key), iv);
StringSource( ciphertext, true,
new AuthenticatedDecryptionFilter(
decryptor,
new StringSink( recovered )
)
);
CCM
CCM 是带有 CBC-MAC 的计数器模式,由 R. Housley、D. Whiting 和 N. Ferguson 于 2002 年提出。CCM 使用格式化函数创建描述明文数据和附加数据的格式化头部。这意味着明文数据和附加数据都必须准备好进行加密——数据不能流式传输到加密器。这被称为**离线**。EAX 和 GCM 都是在线操作模式。
与EAX和GCM不同,由于格式化函数,我们必须在加密或解密之前调用`SpecifyDataLengths(...)`。由于我们只研究认证加密,`aad length`和`footer length`参数将为0。我们还指定了标签大小,尽管Crypto++默认标签大小也很好。我们这样做是因为在解密时需要考虑其大小:`SpecifyDataLengths(0, ciphertext.size()-TAG_SIZE)`,这是控制标签大小最简单的方法之一。
const int TAG_SIZE = 12; // 96 bit authenticator
CCM<AES,TAG_SIZE>::Encryption encryptor;
encryptor.SetKeyWithIV(key, sizeof(key), iv);
encryptor.SpecifyDataLengths( 0, plaintext.size() );
StringSource( plaintext, true,
new AuthenticatedEncryptionFilter(
encryptor,
new StringSink( ciphertext )
)
);
...
CCM<AES, TAG_SIZE>::Decryption decryptor;
decryptor.SetKeyWithIV(key, sizeof(key), iv);
decryptor.SpecifyDataLengths( 0, ciphertext.size()-TAG_SIZE );
StringSource( ciphertext, true,
new AuthenticatedDecryptionFilter(
decryptor,
new StringSink( recovered )
)
);
代码可在示例4中找到。如果您选择此模式,请访问Crypto++ wiki以详细了解CCM模式。此模式还施加了其他限制,例如最大明文长度以及在特定密钥下调用分组密码。
其他图书馆
如果您正在使用其他库,我深表同情。下面我们探讨 Microsoft CAPI、Microsoft CNG、Java JCE、OpenSSL 和 Certicom 的 SecurityBuilder 可用的功能。
Microsoft CAPI 和 CNG
Microsoft Windows CAPI 1.0 和 2.0 仅提供保密模式(ECB、CBC 等)。Vista 和 Server 2008 附带的 CNG 算法支持 CCM 和 GCM 模式 [6,7]。
Java JCE
根据 Java 6 的《Java™ 密码学架构 (JCA) 参考指南》,不提供对 CCM 或 GCM 的支持 [8]。这很可能是一个文档尚未修订的情况。
OpenSSL
根据 OpenSSL 邮件列表,GCM 模式已提交到 HEAD(大约在 2010 年初),因此 GCM 很可能会在 OpenSSL 1.1 中提供。目前似乎没有计划包含 CCM 或其他模式,如 EAX。
Certicom SecurityBuilder
Certicom 的 SecurityBuilder 确实支持 CCM 和 GCM 模式,尽管数据表并未明确说明这一事实。
致谢
- 魏岱,Crypto++ 的作者和维护者
- David Wagner 博士,感谢他在 sci.crypt 上的贡献和帮助
- Brooke Stephens 博士,我以前的密码学老师
参考文献
通常参考文献部分只提供书目。对于本文,参考文献部分扩展为包含在哪里可以找到好的参考文献,以及在哪里可能会找到错误信息。
好的参考资料
Bruce Schneier 写了《应用密码学》,这是 HAC 的一个很好的热身。我发现它缺乏实现所需的大部分细节和实质内容。尽管有点过时,但《应用密码学手册》是圣经。
如果使用特定的算法,例如 AES,请从作者处获取参考实现和测试向量。最后,sci.crypt 和学术界提供了丰富的信息。对于 sci.crypt,您将了解到谁持续提供好的建议。
不良参考资料
不良参考资料很多,尤其是当搜索引擎的唯一标准是流行度时,所以要小心。警惕持有 Security+、CISSP 认证等网络安全人员。虽然他们可能是非常优秀的白帽黑客,但他们的课程还有待提高。我读过学习指南,几乎所有人在密码学领域都惨败(在我们的案例中,达到 80% 并不意味着通过——这意味着 20% 被扭曲并需要关注)。
您还应该质疑 Wiki 上的任何内容,因为它通常未经编辑。不要犯那个在 sci.crypt 上发帖的人的错误,他声称 Adler 博士的 ADLER-32 参考实现是错误的,因为 Wiki 中存在差异。来自_需要同行评审:可能在 Adler-32 中发现了错误!_
这封信是寄给 Adler 先生、他在 zlib 的朋友们、相关的 comp.compression 和 sci.crypt 新闻组,以及 sci.math 和 sci.math.num-analysis 新闻组的……这篇帖子涉及可疑的计算…… [11]
请验证您在本文中阅读到的所有内容。我不是博士,但我有幸与我的前密码学老师讨论详细的主题。如果您发现错误或遗漏,请指出,以便为下一位读者进行更正。
参考文献
[1] M. Bellare, P. Rogaway, and D. Wagner. A Conventional Authenticated-Encryption Mode, http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf[^], 2003。
[2] A. Menezes, P. van Oorschot, and S. Vanstone. Handbook of Applied Cryptography, ISBN 0-8493-8253-7, p. 364.
[3] H. Krawczyk. The Order of Encryption and Authentication for Protecting Communications, http://www.iacr.org/archive/crypto2001/21390309.pdf[^], 2001。
[4] D. Wagner and B. Schneier. Analysis of the SSL 3.0 Protocol, http://www.schneier.com/paper-ssl.html[^], 1996。
[5] A. Menezes, P. van Oorschot, and S. Vanstone. Handbook of Applied Cryptography, ISBN 0-8493-8253-7, p. 367.
[6] 密码学基本属性标识符, http://msdn.microsoft.com/en-us/library/aa376211(VS.85).aspx[^].
[7] CNG 功能, http://msdn.microsoft.com/en-us/library/bb204775(VS.85).aspx[^].
[8] Java" Cryptography Architecture, http://java.sun.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html[^].
[9] openssl(1), https://openssl.ac.cn/docs/apps/openssl.html[^].
[10] crypto(3), https://openssl.ac.cn/docs/crypto/crypto.html[^].
[11] D. Walker. Need peer review: May have found mistake in Adler-32!, Usenet posting, http://groups.google.com/group/comp.compression/browse_thread/thread/5a37a9fcd32786fd[^], 2008。
[12] Kohno, Viega, Whiting. The CWC Authenticated Encryption (Associated Data) Mode, http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/cwc/cwc-spec.pdf[^], 2003。
[13] J. Katz and M.Yung. Unforgeable encryption and chosen ciphertext secure modes of operation, 2000。
[14] M. Bellare and C. Namprempre. Authenticated encryption: Relations among notions and analysis of the generic composition paradigm, 2000。
[15] P. Rogaway. Authenticated Encryption with Associated Data, http://www.cs.ucdavis.edu/~rogaway/papers/ad.ps[^], 2002。
[16] D. Wagner, Message Confidentiality and Integrity - Prepend Hash versus Append Hash, http://groups.google.com/group/sci.crypt/browse_thread/thread/c6c5329f7793e4f4[^], 2007。
[17] S. Vaudenay. CBC Padding: Security Flaws in SSL, IPSEC, WTLS, ..., http://infoscience.epfl.ch/record/52417[^], 2002。