spring-projects/spring-security · error · IllegalStateException

Private key must be provided for decryption

Error message

Private key must be provided for decryption

What it means

RsaRawEncryptor.decrypt(String) requires an RSA private key to perform decryption. The encryptor was constructed without one (privateKey == null), so the method refuses to run and throws this IllegalStateException.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java:103

		this.privateKey = (RSAPrivateKey) privateKey;
		this.defaultCharset = Charset.forName(DEFAULT_ENCODING);
		this.algorithm = algorithm;
	}

	@Override
	public String getPublicKey() {
		return RsaKeyHelper.encodePublicKey(this.publicKey, "application");
	}

	@Override
	public String encrypt(String text) {
		return new String(Base64.getEncoder().encode(encrypt(text.getBytes(this.charset))), this.defaultCharset);
	}

	@Override
	public String decrypt(String encryptedText) {
		if (this.privateKey == null) {
			throw new IllegalStateException("Private key must be provided for decryption");
		}
		return new String(decrypt(Base64.getDecoder().decode(encryptedText.getBytes(this.defaultCharset))),
				this.charset);
	}

	@Override
	public byte[] encrypt(byte[] byteArray) {
		return encrypt(byteArray, this.publicKey, this.algorithm);
	}

	@Override
	public byte[] decrypt(byte[] encryptedByteArray) {
		return decrypt(encryptedByteArray, this.privateKey, this.algorithm);
	}

	private static byte[] encrypt(byte[] text, PublicKey key, RsaAlgorithm alg) {
		ByteArrayOutputStream output = new ByteArrayOutputStream(text.length);
		try {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Construct the encryptor with an RSAPrivateKey (e.g. load from PEM/PKCS#8 keystore) before decrypting.
  2. Ensure key-loading code does not swallow exceptions and fall back to null.
  3. Use separate encryptor instances: public-key encryptor for encrypt, private-key decryptor for decrypt.
  4. Add a startup validation that the private key is present when decryption is required.

Example fix

// before
RsaRawEncryptor e = new RsaRawEncryptor(publicKey);
String plain = e.decrypt(cipher); // IllegalStateException
// after
RSAPrivateKey priv = loadPrivateKey("keystore.p12", "pass");
RsaRawEncryptor e = new RsaRawEncryptor(publicKey, priv);
String plain = e.decrypt(cipher);
Defensive patterns

Strategy: try-catch

Validate before calling

Objects.requireNonNull(privateKey, "RSAPrivateKey required for decryption");

Type guard

boolean canDecrypt(RsaRawEncryptor e, RSAPrivateKey configured) {
    return configured != null;
}

Try / catch

try {
    return encryptor.decrypt(encryptedText);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Private key must be provided")) {
        throw new ConfigException("No private key configured for RsaRawEncryptor decryption");
    }
    throw e;
}

Prevention

When it happens

Trigger: Creating RsaRawEncryptor with only a public key (or via a constructor that leaves privateKey unset) and then calling decrypt on ciphertext.

Common situations: Service configured for encryption-only (has the peer's public key) but code path attempts to decrypt incoming payloads; wiring errors where the keystore entry or PEM private key failed to load and null was passed silently.

Related errors


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