{"record":{"id":"e2c3f9986c516062","repo":"spring-projects/spring-security","slug":"private-key-must-be-provided-for-decryption","errorCode":null,"errorMessage":"Private key must be provided for decryption","messagePattern":"Private key must be provided for decryption","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java","lineNumber":103,"sourceCode":"\t\tthis.privateKey = (RSAPrivateKey) privateKey;\n\t\tthis.defaultCharset = Charset.forName(DEFAULT_ENCODING);\n\t\tthis.algorithm = algorithm;\n\t}\n\n\t@Override\n\tpublic String getPublicKey() {\n\t\treturn RsaKeyHelper.encodePublicKey(this.publicKey, \"application\");\n\t}\n\n\t@Override\n\tpublic String encrypt(String text) {\n\t\treturn new String(Base64.getEncoder().encode(encrypt(text.getBytes(this.charset))), this.defaultCharset);\n\t}\n\n\t@Override\n\tpublic String decrypt(String encryptedText) {\n\t\tif (this.privateKey == null) {\n\t\t\tthrow new IllegalStateException(\"Private key must be provided for decryption\");\n\t\t}\n\t\treturn new String(decrypt(Base64.getDecoder().decode(encryptedText.getBytes(this.defaultCharset))),\n\t\t\t\tthis.charset);\n\t}\n\n\t@Override\n\tpublic byte[] encrypt(byte[] byteArray) {\n\t\treturn encrypt(byteArray, this.publicKey, this.algorithm);\n\t}\n\n\t@Override\n\tpublic byte[] decrypt(byte[] encryptedByteArray) {\n\t\treturn decrypt(encryptedByteArray, this.privateKey, this.algorithm);\n\t}\n\n\tprivate static byte[] encrypt(byte[] text, PublicKey key, RsaAlgorithm alg) {\n\t\tByteArrayOutputStream output = new ByteArrayOutputStream(text.length);\n\t\ttry {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java#L85-L121","documentation":"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.","triggerScenarios":"Creating RsaRawEncryptor with only a public key (or via a constructor that leaves privateKey unset) and then calling decrypt on ciphertext.","commonSituations":"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.","solutions":["Construct the encryptor with an RSAPrivateKey (e.g. load from PEM/PKCS#8 keystore) before decrypting.","Ensure key-loading code does not swallow exceptions and fall back to null.","Use separate encryptor instances: public-key encryptor for encrypt, private-key decryptor for decrypt.","Add a startup validation that the private key is present when decryption is required."],"exampleFix":"// before\nRsaRawEncryptor e = new RsaRawEncryptor(publicKey);\nString plain = e.decrypt(cipher); // IllegalStateException\n// after\nRSAPrivateKey priv = loadPrivateKey(\"keystore.p12\", \"pass\");\nRsaRawEncryptor e = new RsaRawEncryptor(publicKey, priv);\nString plain = e.decrypt(cipher);","handlingStrategy":"try-catch","validationCode":"Objects.requireNonNull(privateKey, \"RSAPrivateKey required for decryption\");","typeGuard":"boolean canDecrypt(RsaRawEncryptor e, RSAPrivateKey configured) {\n    return configured != null;\n}","tryCatchPattern":"try {\n    return encryptor.decrypt(encryptedText);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Private key must be provided\")) {\n        throw new ConfigException(\"No private key configured for RsaRawEncryptor decryption\");\n    }\n    throw e;\n}","preventionTips":["Construct encryptors used for decryption with both keys or a private-key-only constructor.","Fail at startup if privateKey loading returned null.","Separate encrypt-only and decrypt-only encryptor instances per role.","Log key presence (not contents) during configuration validation."],"tags":["rsa","decryption","missing-key","illegal-state"],"backgroundTag":"missing-credentials","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}