{"record":{"id":"490595374d72c7c1","repo":"spring-projects/spring-security","slug":"cannot-decrypt","errorCode":null,"errorMessage":"Cannot decrypt","messagePattern":"Cannot decrypt","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java","lineNumber":163,"sourceCode":"\t\ttry {\n\t\t\tfinal Cipher cipher = Cipher.getInstance(alg.getJceName());\n\t\t\tint maxLength = getByteLength(key);\n\t\t\tint pos = 0;\n\t\t\twhile (pos < text.length) {\n\t\t\t\tint limit = Math.min(text.length - pos, maxLength);\n\t\t\t\tcipher.init(Cipher.DECRYPT_MODE, key);\n\t\t\t\tcipher.update(text, pos, limit);\n\t\t\t\tpos += limit;\n\t\t\t\tbyte[] buffer = cipher.doFinal();\n\t\t\t\toutput.write(buffer, 0, buffer.length);\n\t\t\t}\n\t\t\treturn output.toByteArray();\n\t\t}\n\t\tcatch (RuntimeException ex) {\n\t\t\tthrow ex;\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthrow new IllegalStateException(\"Cannot decrypt\", ex);\n\t\t}\n\t}\n\n\t// copied from sun.security.rsa.RSACore.getByteLength(java.math.BigInteger)\n\tpublic static int getByteLength(@Nullable RSAKey key) {\n\t\tif (key == null) {\n\t\t\tthrow new IllegalArgumentException(\"key cannot be null\");\n\t\t}\n\t\tint n = key.getModulus().bitLength();\n\t\treturn (n + 7) >> 3;\n\t}\n\n}\n","sourceCodeStart":145,"sourceCodeEnd":177,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/encrypt/RsaRawEncryptor.java#L145-L177","documentation":"RsaRawEncryptor.decrypt(byte[]) wraps any checked Exception from the underlying RSA Cipher.doFinal into an IllegalStateException with message \"Cannot decrypt\", preserving the original as the cause. The library throws it when decryption of the raw ciphertext fails — typically a malformed/corrupt ciphertext block, a ciphertext longer than the modulus, or a key/algorithm mismatch between encrypt and decrypt.","triggerScenarios":"Calling RsaRawEncryptor.decrypt(byte[]) with bytes not produced by encrypt(); ciphertext truncated or Base64-mangled; decrypting with a different RSA key or cipher algorithm (e.g. OAEP vs PKCS1) than used to encrypt; BadPaddingException from Cipher.doFinal.","commonSituations":"Passing a Base64 String's bytes directly instead of decoding first; encrypt/decrypt using keys of different sizes; data corrupted in transit or storage; switching between RsaRawEncryptor and RsaSecretEncryptor (different wire formats).","solutions":["Ensure the byte array passed to decrypt is exactly the output of encrypt() with a matching key and algorithm — if you encoded with Base64, decode before decrypting.","Verify the same RSAKeyPair/algorithm is used for both encryptor instances.","Inspect the cause (ex.getCause()) — BadPaddingException/IllegalBlockSizeException indicate wrong key, wrong algorithm, or corrupted ciphertext.","Regenerate test vectors by round-tripping through the same encryptor instance."],"exampleFix":"// before\nbyte[] plain = encryptor.decrypt(encryptedBase64String.getBytes());\n// after\nbyte[] cipherBytes = Base64.getDecoder().decode(encryptedBase64String);\nbyte[] plain = encryptor.decrypt(cipherBytes);","handlingStrategy":"try-catch","validationCode":"// before decrypting\nif (cipherBytes == null || cipherBytes.length == 0) throw new IllegalArgumentException(\"empty ciphertext\");\nif (cipherBytes.length != ((keyPair.getPublic().getModulus().bitLength() + 7) >> 3)) {\n    throw new IllegalArgumentException(\"ciphertext length does not match RSA modulus\");\n}","typeGuard":"boolean isDecodable(RsaRawEncryptor enc, byte[] cipher, RSAKey key) {\n    return cipher != null && cipher.length == RsaRawEncryptor.getByteLength(key);\n}","tryCatchPattern":"try {\n    byte[] plain = encryptor.decrypt(cipherBytes);\n} catch (IllegalStateException ex) {\n    logger.error(\"RSA decryption failed: \" + ex.getCause(), ex);\n    throw new SecurityException(\"Unable to decrypt payload\", ex);\n}","preventionTips":["Always round-trip through the same encryptor instance/key/algorithm in tests.","Base64-decode strings before passing to decrypt(byte[]).","Log ex.getCause(), not just the IllegalStateException.","Validate ciphertext length equals the RSA modulus byte size before decrypting."],"tags":["rsa","cryptography","decryption","illegal-state"],"backgroundTag":"decryption-failed","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"}