spring-projects/spring-security · error · IllegalStateException
unable to encrypt/decrypt
Error message
unable to encrypt/decrypt
What it means
Thrown by BouncyCastleAesGcmBytesEncryptor.process when the GCM cipher's doFinal reports an InvalidCipherTextException, i.e. GCM tag verification failed. With AES-GCM this specifically indicates authentication failure: wrong key, corrupted or truncated ciphertext, or mismatched associated data. GCM detects tampering, so this is often a sign of intentional modification or key mismatch.
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/BouncyCastleAesGcmBytesEncryptor.java:72
}
@Override
public byte[] decrypt(byte[] encryptedBytes) {
byte[] iv = EncodingUtils.subArray(encryptedBytes, 0, this.ivGenerator.getKeyLength());
encryptedBytes = EncodingUtils.subArray(encryptedBytes, this.ivGenerator.getKeyLength(), encryptedBytes.length);
AEADBlockCipher blockCipher = GCMBlockCipher.newInstance(AESEngine.newInstance());
blockCipher.init(false, new AEADParameters(this.secretKey, 128, iv, null));
return process(blockCipher, encryptedBytes);
}
private byte[] process(AEADBlockCipher blockCipher, byte[] in) {
byte[] buf = new byte[blockCipher.getOutputSize(in.length)];
int bytesWritten = blockCipher.processBytes(in, 0, in.length, buf, 0);
try {
bytesWritten += blockCipher.doFinal(buf, bytesWritten);
}
catch (InvalidCipherTextException ex) {
throw new IllegalStateException("unable to encrypt/decrypt", ex);
}
if (bytesWritten == buf.length) {
return buf;
}
byte[] out = new byte[bytesWritten];
System.arraycopy(buf, 0, out, 0, bytesWritten);
return out;
}
}
View on GitHub (pinned to 96852e8860)
Solutions
- Ensure the same password and secure-random salt bytes are used on both encrypt and decrypt paths.
- If ciphertext travels through text channels, always Base64-encode/decode — never new String(bytes) round-trips.
- Re-encrypt stored data if the key was rotated; keep old key available for migration.
- Treat the failure as tampered/unrecognized input: catch and return an authentication error.
- Verify you decrypt with the same encryptor class that encrypted (CBC vs GCM outputs are incompatible).
Example fix
// before
byte[] plain = gcmEncryptor.decrypt(rawBytesFromRequest);
// after
try {
byte[] plain = gcmEncryptor.decrypt(rawBytesFromRequest);
} catch (IllegalStateException ex) {
throw new SecurityException("Ciphertext failed GCM authentication (wrong key or tampered)", ex);
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify ciphertext integrity markers before decrypt
if (cipherBytes == null || cipherBytes.length < 28) throw new IllegalArgumentException("ciphertext too short"); Try / catch
try {
return gcmEncryptor.decrypt(cipherBytes);
} catch (IllegalStateException ex) {
throw new SecurityException("GCM authentication failed: wrong key or tampered data", ex);
} Prevention
- Never round-trip ciphertext through new String(bytes); always use Base64.
- Pin key material in one place; avoid per-service password drift.
- Detect tampering explicitly: GCM failure means data was modified or key mismatched.
- Test decryption after every key rotation deployment.
When it happens
Trigger: Calling decrypt on bytes whose GCM authentication tag does not verify: different password/salt than encryption, bit rot or truncation of stored ciphertext, tampered token, or decrypting CBC-encrypted data with the GCM encryptor.
Common situations: Password or secret rotated without re-encrypting stored values; encrypted cookie/JWT-like tokens modified by a client; data passed through systems that alter bytes (e.g. treating binary as a String instead of Base64); cross-environment data copies.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Bad salt length
- Invalid prefix
- Invalid log_rounds
- unable to encrypt/decrypt
- Not a valid encryption algorithm
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/52a3f8e6787419e3.
Report an issue: GitHub.