AES - Advanced Encryption Standard
AES 是取代 DES 称为新标准的一种对称密码算法
AES 的选拔
AES 由 NIST (National Institute of Standards and Technology, 国家标准技术研究所) 组织公开竞选,最终所选拔的密码算法,成为美国的国家标准,即联邦信息处理标准(FIPS), 但最终成为一个世界性的标准。
AES 选拔对全世界公开,参加者提供密码算法的详细规格书、算法强度的证明和实现代码,由全世界的企业和密码学家共同完成评审。2000 年, Rijndael 算法被 NIST 从最终候选算法名单中选定成为 AES 标准。
被选为 AES 密码算法必须无条件地免费供全世界使用。
Rijndael 密码算法
两位比利时密码学家设计,也属于*分组密码算法 *(block cipher)
分组长度: 128 比特位
密钥长度: 128、192 和 256 比特
Rijndael 的加密和解密
和 DES 一样,Rijndael 算法由多轮构成,其中每一轮分为 SubBytes、ShiftRows、MixColumns 和 AddRoundKey 个步骤。并且使用了一种称为 SPN 结构。
1. SubBytes-逐字节替换
Rijndael 的分组是 128 比特位,即 16 字节。对 16 个字节进行 SubBytes 处理,就是将每个字节所代表的无符号整数值(0-255)作为索引,从一个拥有 256 个值的替换表 (S-Box, S盒) 中查找对应的值。简单来说,就是每个字节查表映射为新的值。
2. ShiftRows-平移行
将以 4 字节为单位的行 (row) 按照一定的规则向左平移,且每一行平移的字节数是不同的。图示为对其中一行进行处理的情形:
3. MixColumns-混合列
对一个 4 字节的值进行比特运算,将其变为另一个 4 字节的值,图示为对其中一列(column)进行处理的情形:
4. AddRoundKey-轮密钥异或运算
将 MixColumns 的输出与轮密钥进行 XOR,图示为对其中一个字节进行处理的情形:
输入的所有比特在一轮中都会被加密,相比于 DES 的 Feistel 网络相比(每一轮只加密一半输入的比特位),加密所需的轮数更少,一般重复进行10 到 14 轮,而且其中的步骤,可以分别以字节、行和列为单位进行并行计算。
注:并行计算也是衡量密码算法的一个重要指标,并行意味着加密解密的速度块。
加密的过程:
1 | SubBytes --> SbiftRows --> MixColumns --> AddRoundKey |
解密,就是按照相反的顺序来进行就可以:
1 | AddRoundKey --> InvMixColumns --> InvShiftRows --> InvSubBytes |
Rijndael 的算法背后有着严谨的数学结构,明文到密文的过程可以全部用数学公式来表达,此外,轮密钥的计算也涉及到稍微复杂的过程,没有在这里涉及。
使用 openssl 和 JCA 进行加密解密的验证
opesnssl 加密和解密
1 | # 使用 openssl 加密 'hello' 字符串 |
使用 JCA (Java Cryptography Architecture) 进行验证
openssl 会生成 8 个比特的 salt,并以 Salted__${salt}
附加在加密的密文前,一共占 16 个字节,验证如下:
1 | $ echo -n "U2FsdGVkX182McnaOCzkh7BPMUJaKwGCIc8cAGAtbNw=" | base64 -d | hexdump -C |
所以实际加密后密文的 16 进制为:b04f31425a2b018221cf1c00602d6cdc
使用 JCA 进行解密验证:
1 | public class AESCryptoTest { |