{"record":{"id":"7212726084283b05","repo":"spring-projects/spring-security","slug":"encryptor-is-not-configured-for-decryption","errorCode":null,"errorMessage":"Encryptor is not configured for decryption","messagePattern":"Encryptor is not configured for decryption","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaSecretEncryptor.java","lineNumber":160,"sourceCode":"\t\tthis.algorithm = algorithm;\n\t\tthis.salt = isHex(salt) ? salt : new String(Hex.encode(salt.getBytes(this.defaultCharset)));\n\t\tthis.gcm = gcm;\n\t}\n\n\t@Override\n\tpublic String getPublicKey() {\n\t\treturn RsaKeyHelper.encodePublicKey((RSAPublicKey) 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 (!canDecrypt()) {\n\t\t\tthrow new IllegalStateException(\"Encryptor is not configured 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, this.salt, this.gcm);\n\t}\n\n\t@Override\n\tpublic byte[] decrypt(byte[] encryptedByteArray) {\n\t\tif (!canDecrypt()) {\n\t\t\tthrow new IllegalStateException(\"Encryptor is not configured for decryption\");\n\t\t}\n\t\treturn decrypt(encryptedByteArray, this.privateKey, this.algorithm, this.salt, this.gcm);\n\t}\n","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaSecretEncryptor.java#L142-L178","documentation":"RsaSecretEncryptor.decrypt(String) checks canDecrypt() and throws IllegalStateException(\"Encryptor is not configured for decryption\") when the encryptor was created with only a public key, so it has no PrivateKey to perform decryption. This is a fail-fast guard before Base64 decoding and RSA decryption.","triggerScenarios":"Creating an RsaSecretEncryptor from a public key only (or a KeyStore entry exposing only the certificate/public key) and then calling decrypt(String); hybrid mode where only publicKey was provided.","commonSituations":"Server-side encryptor built with a partner's public key that should never decrypt; loading a keystore alias that only contains a certificate; unit test publicKeyCannotDecrypt asserting this behavior.","solutions":["Construct the RsaSecretEncryptor with a KeyPair (or private key / keystore alias containing the private key) so canDecrypt() returns true.","If the encryptor intentionally holds only a public key, do not call decrypt — use a separate encryptor configured with the private key.","Check canDecrypt() before calling decrypt and route to an encryptor that has the private key."],"exampleFix":"// before\nRsaSecretEncryptor enc = new RsaSecretEncryptor(publicKey);\nString plain = enc.decrypt(cipherText); // throws\n// after\nRsaSecretEncryptor dec = new RsaSecretEncryptor(keyPair); // has private key\nString plain = dec.decrypt(cipherText);","handlingStrategy":"validation","validationCode":"if (!encryptor.canDecrypt()) {\n    throw new UnsupportedOperationException(\"This encryptor holds only a public key; use a private-key-configured encryptor to decrypt\");\n}\nString plain = encryptor.decrypt(encryptedText);","typeGuard":"boolean canDecrypt(RsaSecretEncryptor enc) { return enc != null && enc.canDecrypt(); }","tryCatchPattern":"try {\n    return encryptor.decrypt(encryptedText);\n} catch (IllegalStateException ex) {\n    if (ex.getMessage().contains(\"not configured for decryption\")) {\n        return privateKeyEncryptor.decrypt(encryptedText);\n    }\n    throw ex;\n}","preventionTips":["Check canDecrypt() before any decrypt call.","Build decrypt-side encryptors from a KeyPair or PrivateKeyEntry keystore alias.","Keep encrypt-only (public key) encryptors separate from decrypt-capable ones by naming convention."],"tags":["rsa","decryption","illegal-state","public-key","cryptography"],"backgroundTag":"missing-private-key","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"}