一.前言
AES(Advanced Encryption Standard),高级加密标准,是美国政府用于替换DES的一种加密算法标准,Java SDK中包含了部分AES的实现,但javadoc对于算法的描述非常少,本文将解释Java AES实现的使用和原理。
二.示例代码
三.代码分析
JDK AES加密主要是几个步骤:
1.key变换
将传入的明文key做变换,AES的key固定为128bit,但变换后的key为加密位数的一倍,128bit的加密变换后key为256bit。注意加密和解密的key变换不一样。
2.加密解密
选择加密的模式和补齐填充方法生成加密实例,加密得到密文。
四.密码块工作模式
块密码工作模式(Block cipher mode of operation),是对于按块处理密码的加密方式的一种扩充,不仅仅适用于AES,包括DES, RSA等加密方法同样适用。
名称 | 英文 | 全名 | 方法 | 优点 | 缺点 |
ECB | Electronic codebook | 电子密码本 | 每块独立加密 | 1.分块可以并行处理 | 1.同样的原文得到相同的密文,容易被攻击 |
CBC | Cipher-block chaining | 密码分组链接 | 每块加密依赖于前一块的密文 | 1.同样的原文得到不同的密文 | 1.加密需要串行处理 |
PCBC | Propagating cipher-block chaining | 填充密码块链接 | CBC的扩种,较少使用 | 1.同样的原文得到不同的密文 | 1.加密需要串行处理 |
CFB | Cipher feedback | 密文反馈 |
|
|
|
OFB | Output feedback | 输出反馈模式 | 加密后密文与原文异或XOR |
| 1.能够对密文进行校验 |
CTR | Counter mode | 计数器模式 | 增加一个序列函数对所有密文快做XOR |
|
|
五.填充
填充(Padding),是对需要按块处理的数据,当数据长度不符合块处理需求时,按照一定方法填充满块长的一种规则。
名称 | 方法 | 示例 |
Zero padding | 最常见的方式,全填充0x00 | AA AA AA AA 00 00 00 00 |
ANSI X.923 | Zero的改进,最后一个字节为填充字节个数 | AA AA AA AA 00 00 00 04 |
ISO 10126 | 随机填充 | AA AA AA AA 81 A6 23 04 |
PKCS7 | ANSI X.923的变体 | AA AA AA AA AA AA AA 01 |
ISO/IEC 7816-4 | 以0x80开始作为填充开始标记,后续全填充0x00 | AA AA AA AA AA AA AA 80 |
六.JDK AES实现
1.实现支持
AES理论上支持128,192,256三种长度的密钥,几乎全部密码块工作模式和填充方法,但JDK 7中只实现如下四种AES加密算法:
(1)AES/CBC/NoPadding (128)
(2)AES/CBC/PKCS5Padding (128)
(3)AES/ECB/NoPadding (128)
(4)AES/ECB/PKCS5Padding (128)
2.使用须知
(1)缺省模式和填充为“AES/ECB/PKCS5Padding”,Cipher.getInstance(“AES”)与Cipher.getInstance(“AES/ECB/PKCS5Padding”)等效。
(2)JDK的PKCS5Padding实际是上述的PKCS7的实现。
(3)由于AES是按照16Byte为块进行处理,对于NoPadding而言,如果需要加密的原文长度不是16Byte的倍数,将无法处理抛出异常,其实是由用户自己选择Padding的算法。密文则必然是16Byte的倍数,否则密文肯定异常。
(4)如果加密为PKCS5Padding,解密可以选择NoPadding,也能解密成功,内容为原文加上PKCS5Padding之后的结果。
(5)如果原文最后一个字符为>=0x00&&<=0x10的内容,PKCS5Padding的解密将会出现异常,要么是符合PKCS5Padding,最后的内容被删除,要么不符合,则解密失败抛出异常。对此有两种思路,一是原文通过Base64编码为可见字符,二是原文自带长度使用NoPadding解密。