Cipher类是JCE核心组件,统一执行加解密;AES需严格匹配算法/模式/填充、密钥(16/24/32字节并用SecretKeySpec包装)、IV(CBC模式下16字节且必须与加密时完全相同),解密前须Base64解码、解密后按UTF-8转字符串。

Java 中的 Cipher 类是 JCE(Java Cryptography Extension)的核心组件,用于统一执行对称加密(如 AES、DES)和非对称加密(如 RSA)的加解密操作。它不直接处理密钥生成或编码转换,但通过标准化的初始化和调用流程,让不同算法具备一致的使用方式。
AES 加密与解密的关键配置
AES 是当前主流的对称加密算法,推荐使用 128 位(16 字节)及以上密钥长度。实际使用中必须明确三要素:
-
算法/模式/填充:例如
"AES/CBC/PKCS5Padding",其中CBC模式需配合初始化向量(IV),PKCS5Padding保证明文长度适配分组要求(AES 分组固定为 128 位) -
密钥规格:用
SecretKeySpec包装字节数组,密钥长度必须为 16、24 或 32 字节(对应 AES-128/AES-192/AES-256);若字符串密钥不足长度,不可简单截断或补空格,应通过 SHA-256 等哈希后取前 N 字节 - 初始化向量(IV):CBC、CTR 等模式必需,长度必须等于分组大小(AES 为 16 字节)。IV 不需要保密,但每次加密应随机生成并随密文一起传输;解密时需使用**完全相同**的 IV
DES 和 3DES 的注意事项
DES 已属淘汰算法,仅限兼容旧系统使用;3DES(Triple DES)作为过渡方案仍被部分金融系统支持。它们的 Cipher 配置逻辑类似,但参数约束更严格:
- DES 密钥必须为 8 字节(56 位有效),且不能含弱密钥(如全 0、全 F);JDK 默认策略限制密钥长度,如需使用 3DES(112 或 168 位密钥),需确认 JCE Unlimited Strength Policy 已启用(现代 JDK 8u161+ 及 JDK 9+ 默认支持)
- 工作模式推荐
CBC,避免使用ECB—— 后者对相同明文块生成相同密文块,会暴露数据模式 - 填充方式常用
PKCS5Padding(与 PKCS7Padding 在 8 字节分组下等价),不可省略;若指定NoPadding,则明文长度必须严格为分组长度整数倍
加解密流程的通用写法
无论 AES 还是 DES,Cipher 实例的生命周期都遵循固定步骤,核心在于 init() 的参数匹配:
- 加密:先调用
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec),再传入原始字节数组执行doFinal() - 解密:使用**完全相同的**
keySpec和ivSpec初始化,传入 Base64 解码后的密文字节数组,doFinal()返回明文字节 - 异常处理必须覆盖
InvalidKeyException、InvalidAlgorithmParameterException和BadPaddingException(后者常因密钥/IV 错误或填充损坏触发) - 敏感操作如密钥构造、IV 生成建议使用
SecureRandom,而非Random,防止可预测性风险
常见错误与规避方式
实际开发中最容易踩坑的地方集中在参数不一致和编码混乱:
- 密钥或 IV 使用字符串
getBytes()时未指定字符集(如 UTF-8),导致不同环境字节序列不一致 → 始终显式传入"UTF-8" - 加密用
CBC模式却在init()中漏掉IvParameterSpec→ 抛出InvalidAlgorithmParameterException - Base64 编解码混用不同实现(如 Apache Commons Codec vs Java 8+
java.util.Base64)→ 结果无法互通,应统一使用标准 JDK 接口 - 将加密后的字节数组直接转成 String(如
new String(encrypted))→ 产生乱码甚至截断,必须用 Base64 或 Hex 编码后再传输

















