AES-GCM解密报错:Parameters missing问题排查求助
解决AES-GCM解密时的
InvalidKeyException: Parameters missing异常 我来帮你搞定这个问题!你遇到的java.security.InvalidKeyException: Parameters missing是AES-GCM模式的典型坑——GCM属于AEAD(认证加密带关联数据)算法,它要求解密时必须使用和加密时完全相同的初始化向量(IV),而你的代码里漏掉了IV的传递,导致Cipher无法完成解密初始化。
问题根源分析
当你调用AES_cipherInstance.init(Cipher.ENCRYPT_MODE, secretKey)时,Java的Cipher会自动生成一个随机的IV(GCM推荐用12字节长度),但这个IV并没有被你保存或传递给解密方法。解密时你只传入了密文和密钥,没有提供加密时使用的IV,Cipher就会抛出“参数缺失”的异常。
另外,AES-GCM加密后的结果其实包含IV + 密文 + 认证标签(GCM自动生成认证标签用于完整性校验),解密时需要正确拆分这些部分才能正常工作。
修复方案
我们需要修改代码,在加密时获取并传递IV,解密时用这个IV来初始化Cipher:
步骤1:加密时保存IV并与密文拼接
加密完成后,获取Cipher生成的IV,把IV和加密后的字节数组(包含密文和认证标签)拼接在一起,再传递给解密方法。
步骤2:解密时拆分IV和密文
从传入的字节数组中先拆分出IV(前12字节,GCM推荐长度),剩下的部分是密文+认证标签,然后用IV和密钥初始化解密模式的Cipher。
修改后的完整代码
import javax.crypto.*; import javax.crypto.spec.GCMParameterSpec; import java.security.*; import java.io.UnsupportedEncodingException; public class AES256_GCM { // GCM推荐的IV长度是12字节 private static final int GCM_IV_LENGTH = 12; public String encrypt(String cleartext) { try { byte[] clearTextBytes = cleartext.getBytes("UTF-8"); final SecureRandom secureKeyRandomness = SecureRandom.getInstanceStrong(); final KeyGenerator AES_keyInstance = KeyGenerator.getInstance("AES"); AES_keyInstance.init(128, secureKeyRandomness); final SecretKey secretKey = AES_keyInstance.generateKey(); final Cipher AES_cipherInstance = Cipher.getInstance("AES/GCM/NoPadding"); // 初始化加密模式,指定SecureRandom生成IV AES_cipherInstance.init(Cipher.ENCRYPT_MODE, secretKey, secureKeyRandomness); byte[] encryptedText = AES_cipherInstance.doFinal(clearTextBytes); // 获取加密时自动生成的IV byte[] iv = AES_cipherInstance.getIV(); // 拼接IV和密文:IV在前,密文在后 byte[] ivPlusEncrypted = new byte[iv.length + encryptedText.length]; System.arraycopy(iv, 0, ivPlusEncrypted, 0, iv.length); System.arraycopy(encryptedText, 0, ivPlusEncrypted, iv.length, encryptedText.length); // 调用解密方法,传入拼接后的字节数组和密钥 return decrypt(ivPlusEncrypted, secretKey); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | InvalidAlgorithmParameterException e) { e.printStackTrace(); } return "something went wrong with encrypt"; } public String decrypt(byte[] ivPlusEncrypted, SecretKey secretKey) { try { // 拆分IV和密文:前12字节是IV,剩余部分是密文+认证标签 byte[] iv = new byte[GCM_IV_LENGTH]; byte[] encryptedText = new byte[ivPlusEncrypted.length - GCM_IV_LENGTH]; System.arraycopy(ivPlusEncrypted, 0, iv, 0, GCM_IV_LENGTH); System.arraycopy(ivPlusEncrypted, GCM_IV_LENGTH, encryptedText, 0, encryptedText.length); final Cipher AES_cipherInstance = Cipher.getInstance("AES/GCM/NoPadding"); // 使用IV参数初始化解密模式的Cipher(128是认证标签的长度,单位:位) GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); AES_cipherInstance.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec); byte[] decryptedText = AES_cipherInstance.doFinal(encryptedText); return new String(decryptedText, "UTF-8"); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException | InvalidAlgorithmParameterException e) { e.printStackTrace(); } return "something went wrong with decrypt"; } }
关键说明
- IV的作用:GCM模式的IV不需要保密,但必须保证每次加密使用不同的IV(
SecureRandom生成的IV满足这个要求),相同密钥+不同IV加密相同明文会得到不同密文,能有效提高安全性。 - 认证标签:GCM模式自动生成128位的认证标签,它和密文一起被
doFinal()返回,解密时会自动校验标签,确保密文没有被篡改。 - 参数初始化:解密时必须用
GCMParameterSpec指定IV和标签长度,这样Cipher才能正确完成初始化,彻底解决参数缺失的异常。
内容的提问来源于stack exchange,提问作者temp acct
相关产品推荐
相关产品推荐

