spring-projects/spring-security · error · IllegalStateException

Unable to invoke Cipher due to bad padding

Error message

Unable to invoke Cipher due to bad padding

What it means

CipherUtils wraps JCE Cipher operations and rethrows checked exceptions as unchecked IllegalStateException. This error means Cipher.doFinal() threw BadPaddingException: the decrypted data's padding bytes did not match the padding scheme (e.g. PKCS5Padding) specified for the transform. It almost always indicates wrong key, corrupted/truncated ciphertext, or mismatched padding configuration between encryptor and decryptor.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/CipherUtils.java:144

		}
		catch (InvalidAlgorithmParameterException ex) {
			throw new IllegalStateException("Unable to initialize due to invalid decryption parameter spec", ex);
		}
	}

	/**
	 * Invokes the Cipher to perform encryption or decryption (depending on the
	 * initialized mode).
	 */
	static byte[] doFinal(Cipher cipher, byte[] input) {
		try {
			return cipher.doFinal(input);
		}
		catch (IllegalBlockSizeException ex) {
			throw new IllegalStateException("Unable to invoke Cipher due to illegal block size", ex);
		}
		catch (BadPaddingException ex) {
			throw new IllegalStateException("Unable to invoke Cipher due to bad padding", ex);
		}
	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Verify the decryptor uses the exact same password/key and transform as the encryptor
  2. Check the ciphertext string was not altered: compare byte length / Base64 integrity before decrypting
  3. Confirm the JCE provider supports the configured padding and unlimited-strength policy is available
  4. Wrap decryption in try-catch for IllegalStateException and treat as corrupt input rather than retrying

Example fix

// before
String plain = encryptor.decrypt(corruptedCipherText);
// after
try {
    String plain = encryptor.decrypt(cipherText);
} catch (IllegalStateException ex) {
    if (ex.getCause() instanceof BadPaddingException) {
        throw new IOException("Ciphertext is corrupted or key mismatch", ex);
    }
    throw ex;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify ciphertext round-trips before relying on it
try {
    decrypt(encrypt(sample));
} catch (IllegalStateException e) {
    throw new IllegalArgumentException("Cipher transform/key mismatch", e);
}

Try / catch

try { String plain = encryptor.decrypt(cipherText); } catch (IllegalStateException ex) { /* treat as corrupt input / key mismatch, do not retry */ }

Prevention

When it happens

Trigger: Calling TextEncryptor/CipherUtils decrypt with a ciphertext produced by a different key, a different padding mode, or data that was truncated/re-encoded (e.g. Base64 mangled), so the final block fails the padding check.

Common situations: Rotated or mismatched encryption keys across environments; ciphertext round-tripped through a medium that altered bytes (URL encoding, charset conversion); decrypting data encrypted with a different provider or JCE policy (e.g. pre-JDK8 256-bit limits); switching transform from ECB/PKCS5 to CBC/NoPadding.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/ebb47a428d0c9c72. Report an issue: GitHub.