1. 引言

Java中的Cipher类是提供加密解密功能的核心类。本文将探讨使用该类时可能遇到的常见异常,并提供解决方案。

2. NoSuchAlgorithmException:找不到支持X算法的提供者

当使用虚构算法获取Cipher实例时:

Cipher.getInstance("ABC");

会抛出如下异常:

java.security.NoSuchAlgorithmException: Cannot find any provider supporting ABC
    at javax.crypto.Cipher.getInstance(Cipher.java:543)

核心原因

  • 算法名称无效:传入的算法转换字符串必须符合官方文档的规范
  • 拼写错误:即使查阅文档后仍报错,需检查算法名称拼写
  • 模式/填充参数错误:可指定算法模式和填充方式,但需确保组合有效

有效与无效示例对比

Cipher.getInstance("AES/ABC"); // ❌ 无效模式
Cipher.getInstance("AES/CBC/ABC"); // ❌ 无效填充
Cipher.getInstance("AES/CBC/PKCS5Padding"); // ✅ 有效组合

默认值警告

  • 算法模式默认为ECB(存在安全风险)
  • 填充方式默认为NoPadding
  • ⚠️ 生产环境应显式指定安全模式(如CBC)

3. IllegalBlockSizeException:输入长度不是X字节的倍数

3.1 解密时的异常

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherTextBytes);

当密文长度不符合要求时:

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
    at com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1109)

根本原因

  • AES是分组密码,固定处理16字节块
  • ❌ 最后一个分组长度不足16字节
  • ⚠️ 通常表明原始数据加密过程有误

处理建议

  • 必须捕获此异常(编译器强制要求)
  • 注意:约1/16的错误密文会因巧合长度而绕过此异常

3.2 加密时的异常

String plainText = "https://www.baeldung.com/";
byte[] plainTextBytes = plainText.getBytes();
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plainTextBytes);

当明文长度不是16字节倍数时抛出相同异常。

解决方案

  • 启用填充:使用PKCS5Padding等填充方案
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // ✅ 启用填充
    
  • ⚠️ 加解密必须使用相同填充方式

3.3 其他排查技巧

  • 检查Java文档确认填充方案有效性
  • 验证Java版本与文档匹配(不同版本支持方案可能不同)

4. BadPaddingException:最终块填充不正确

4.1 填充方式不匹配

// 加密使用ISO10126Padding
Cipher cipher = Cipher.getInstance("AES/ECB/ISO10126Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherTextBytes = cipher.doFinal(plainTextBytes);

// 解密使用PKCS5Padding
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
return cipher.doFinal(cipherTextBytes); // ❌ 抛出异常

异常信息:

javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.

4.2 密钥不匹配(最常见原因)

SecretKey encryptionKey = CryptoUtils.getKeyForText("BaeldungIsASuperCoolSite");
SecretKey differentKey = CryptoUtils.getKeyForText("ThisGivesUsAnAlternative");

// 加密
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
byte[] cipherTextBytes = cipher.doFinal(plainTextBytes);

// 解密使用不同密钥
cipher.init(Cipher.DECRYPT_MODE, differentKey);
return cipher.doFinal(cipherTextBytes); // ❌ 抛出异常

4.3 算法/模式不匹配

// 加密使用CBC模式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherTextBytes = cipher.doFinal(plainTextBytes);

// 解密使用ECB模式
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(cipherTextBytes); // ❌ 抛出异常

统一排查思路

✅ 确保解密时使用的:

  • 密钥与加密时完全相同
  • 算法名称/模式/填充方式完全匹配

5. InvalidKeyException

5.1 参数缺失(缺少IV)

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, encryptionKey); // ❌ 缺少IV参数
cipher.doFinal(cipherTextBytes);

异常信息:

java.security.InvalidKeyException: Parameters missing

解决方案

  • ✅ 添加初始化向量(IV): ```java byte[] ivBytes = new byte[]{'B', 'a', 'e', 'l', 'd', 'u', 'n', 'g', 'I', 's', 'G', 'r', 'e', 'a', 't', '!'}; IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, encryptionKey, ivParameterSpec); // ✅ 添加IV

- ⚠️ IV长度必须为16字节(AES要求)
- ⚠️ 加解密必须使用相同IV

### 5.2 密钥长度无效
```java
java.security.InvalidKeyException: Invalid AES key length: X bytes

解决方案

  • ✅ 确保密钥长度为16字节(128位)
  • ⚠️ Java默认仅支持128位加密

6. 总结

本文系统分析了Java加密API中的常见异常:

  1. NoSuchAlgorithmException:算法名称/模式/填充无效
  2. IllegalBlockSizeException:数据长度不符合分组要求
  3. BadPaddingException:通常由密钥/算法不匹配引起
  4. InvalidKeyException:密钥长度错误或缺少必要参数

关键排查原则:

  • ✅ 严格匹配加解密参数(密钥/算法/模式/填充/IV)
  • ⚠️ 异常信息可能具有误导性(如填充问题实际是密钥错误)
  • 📖 始终参考官方文档验证参数有效性

完整示例代码可在GitHub项目中获取。


原始标题:Common Exceptions of Crypto APIs in Java | Baeldung