AES解密报错:Given final block not properly padded及CardHolderName为null问题
解密CardHolderName参数时出现填充错误问题
问题现象
解密CardHolderName参数时触发错误,错误信息:
Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
报错堆栈:
Given final block not properly padded. Such issues can arise if a bad key is used during decryption. at com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975) at com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056) at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853) at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at javax.crypto.Cipher.doFinal(Cipher.java:2164) at com.example.encryptdecrypt.utils.AES.decrypt(AES.java:79) at com.example.encryptdecrypt.service.EncryptionServiceimpl.decrypt(EncryptionServiceimpl.java:36) at com.example.encryptdecrypt.EncryptionController.EncryptionController.userDecryptusingKey(EncryptionController.java:56) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
当前能正常解密CVV值,但CardHolderName解密后返回null。已尝试修改doFinal()和update()方法,问题仍未解决。
相关代码片段
Controller层代码
@PostMapping("/userdecryptusingKey") public User userDecryptusingKey(@RequestBody Map<String,String> secretKeybody) { String secretKey = secretKeybody.get("secretKey"); User user1 = encryptionService.getUserByKey(secretKey); System.out.println(user1.getCardHolderName()); user1.setCardHolderName(encryptionService.decrypt(user1.getCardHolderName(),secretKey)); user1.setCvv(encryptionService.decrypt(user1.getCvv().toString(),secretKey)); return user1; }
密钥生成与转换函数
private void setKey() throws GeneralSecurityException { try { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); secretKey = keyGenerator.generateKey(); } catch (Exception e) { e.printStackTrace(); } }
public static SecretKey convertStringToSecretKey(String encodedKey) { //System.out.println("encoded key"+ encodedKey); byte[] decodedKey = Base64.getDecoder().decode(encodedKey); SecretKey originalKey = new SecretKeySpec(decodedKey,"AES"); return originalKey; }
解密函数
public String decrypt(String strToDecrypt,String key){ try { SecretKey secretKey1 = convertStringToSecretKey(key); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); byte[] iv = new byte[16]; IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey1); return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))); } catch ( InvalidKeyException |IllegalBlockSizeException |NoSuchAlgorithmException| NoSuchPaddingException | BadPaddingException e) { System.out.println("error decr" + e.getMessage()); e.printStackTrace(); } return null; }
问题分析与解决方案
清理冗余代码
解密代码中初始化了IvParameterSpec但未使用(ECB模式不需要IV),删除这部分冗余代码,避免逻辑混淆:// 移除以下两行无用代码 byte[] iv = new byte[16]; IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);验证加密数据完整性
- 打印
user1.getCardHolderName()的原始值,确认是完整合法的Base64编码字符串。如果数据在存储/传输时被截断、篡改,会直接导致解密填充错误。 - 对比CVV和CardHolderName的加密逻辑,确保两者使用完全相同的密钥、加密模式(
AES/ECB/PKCS5PADDING)、Base64编码规则。
- 打印
确认密钥一致性
- 验证解密时传入的
secretKey与加密CardHolderName时使用的密钥完全一致:可以在加密时保存密钥的Base64编码,解密前打印传入的secretKey编码值,对比两者是否匹配。 - 检查
convertStringToSecretKey方法的Base64解码逻辑,确保密钥编码/解码过程无错误。
- 验证解密时传入的
指定字符串编码
解密后转换字符串时显式指定UTF-8编码,避免默认编码导致的解析异常:return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt)), StandardCharsets.UTF_8);优化异常排查
在异常捕获分支中区分BadPaddingException,明确是密钥不匹配还是数据损坏,方便定位问题:catch (BadPaddingException e) { System.out.println("解密填充错误:密钥不匹配或加密数据损坏"); e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者Anusha k
相关产品推荐
相关产品推荐

