Open moooofly opened 5 years ago
当我们有一段明文,需要对其进行 AES 加密时,需要对明文进行分组,分组长度可为 128,256 或 512bits。采用 ECB 模式的分组密码算法加密过程如下图:
由上图可以看出,明文中重复的排列会反映在密文中。并且,当密文被篡改时,解密后对应的明文分组也会出错,且解密者察觉不到密文被篡改了。也就是说,ECB 不能提供对密文的完整性校验。因此,在任何情况下都不推荐使用 ECB 模式。
在计数器模式下,我们不再对明文进行加密,而是对一个逐次累加的计数器进行加密,用加密后的比特序列与明文分组进行 XOR 得到密文。过程如下图:
计数器模式下,每次与明文分组进行 XOR 的比特序列是不同的,因此,计数器模式解决了 ECB 模式中,相同的明文会得到相同的密文的问题。CBC,CFB,OFB 模式都能解决这个问题;
但 CTR 的另两个优点是:
但 CTR 仍然不能提供密文消息完整性校验的功能。
有的人可能会想到,如果将密文的 hash 值随密文一起发送,密文接收者对收到的密文计算 hash 值,与收到的 hash 值进行比对,这样是否就能校验消息的完整性呢?
再仔细想想,就能发现这其中的漏洞。当篡改者截获原始的密文消息时,先篡改密文,而后计算篡改后的密文 hash,替换掉原始消息中的密文 hash 。这样,消息接收者仍然没有办法发现对源密文的篡改。可见,使用单向散列函数计算 hash 值仍然不能解决消息完整性校验的问题。
想要校验消息的完整性,必须引入另一个概念:消息验证码。消息验证码是一种与秘钥相关的单项散列函数。
密文的收发双发需要提前共享一个秘钥。密文发送者将密文的 MAC 值随密文一起发送,密文接收者通过共享秘钥计算收到密文的 MAC 值,这样就可以对收到的密文做完整性校验。当篡改者篡改密文后,没有共享秘钥,就无法计算出篡改后的密文的 MAC 值。
如果生成密文的加密模式是 CTR ,或者是其他有初始 IV 的加密模式,别忘了将初始的计数器(值)或初始向量的值作为附加消息与密文一起计算 MAC 。
对应到上图中的消息认证码,GMAC 就是利用伽罗华域(Galois Field,GF,有限域)乘法运算来计算消息的 MAC 值。假设秘钥长度为 128bits,当密文大于 128bits 时,需要将密文按 128bits 进行分组。应用流程如下图:
GCM 中的 G 就是指 GMAC,C 就是指 CTR 。
GCM 可以提供对消息的加密和完整性校验,另外,它还可以提供附加消息的完整性校验。在实际应用场景中,有些信息是我们不需要保密,但信息的接收者需要确认它的真实性的,例如源IP,源端口,目的IP,IV,等等。因此,我们可以将这一部分作为附加消息加入到 MAC 值的计算当中。下图的 Ek 表示用对称秘钥 k 对输入做 AES 运算。最后,密文接收者会收到密文、IV(计数器 CTR 的初始值)、MAC 值。
AES 加密
简史
confidentiality mode
ECB、CBC、OFB 和 CFB 这四种是属于 DES 时代就存在的操作模式;
后来,随着 AES 也加入到 block cipher 中,又增加了 CTR 这种操作模式;
再后来,又增加了 XTS-AES 操作模式;
authenticity mode
操作模式提供的是保密功能,但无法针对意外修改或恶意篡改提供保护;
这种需要通过 MAC 或 digital signature 数字签名进行保护;
Authenticated encryption
社区发现单纯的将一种 confidentiality mode 和一种 authenticity mode 组合在一起是有一定困难的,并且容易出错;因此,社区开始研究如何将两者合二为一,这种 combined modes 被称作 authenticated encryption ;
AE mode 的代表有:
参考:
block cipher 有五种操作模式:
下文中使用的符号和对应含义
参考:
推荐
示例代码
https://github.com/moooofly/playground/tree/master/crypto_example
https://play.golang.org/p/EVsUdbCTfaT