{"record":{"id":"90e823104c1e7cd7","repo":"jwtk/jjwt","slug":"publickeys-may-not-be-used-to-decrypt-data-public-90e823","errorCode":null,"errorMessage":"PublicKeys may not be used to decrypt data. PublicKeys are used to encrypt, and PrivateKeys are used to decrypt.","messagePattern":"PublicKeys may not be used to decrypt data\\. PublicKeys are used to encrypt, and PrivateKeys are used to decrypt\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java","lineNumber":297,"sourceCode":"            throw new IllegalArgumentException(DefaultJwtParser.PRIV_KEY_VERIFY_MSG);\n        }\n        this.signatureVerificationKey = Assert.notNull(key, \"signature verification key cannot be null.\");\n        return this;\n    }\n\n    @Override\n    public JwtParserBuilder decryptWith(SecretKey key) {\n        return decryptWith((Key) key);\n    }\n\n    @Override\n    public JwtParserBuilder decryptWith(PrivateKey key) {\n        return decryptWith((Key) key);\n    }\n\n    private JwtParserBuilder decryptWith(final Key key) {\n        if (key instanceof PublicKey) {\n            throw new IllegalArgumentException(DefaultJwtParser.PUB_KEY_DECRYPT_MSG);\n        }\n        this.decryptionKey = Assert.notNull(key, \"decryption key cannot be null.\");\n        return this;\n    }\n\n    @Override\n    public NestedCollection<CompressionAlgorithm, JwtParserBuilder> zip() {\n        return new NestedIdentifiableCollection<CompressionAlgorithm, JwtParserBuilder>(this, this.zipAlgs) {\n            @Override\n            protected void changed() {\n                zipAlgs = new IdRegistry<>(StandardCompressionAlgorithms.NAME, getValues().values());\n            }\n        };\n    }\n\n    @Override\n    public NestedCollection<AeadAlgorithm, JwtParserBuilder> enc() {\n        return new NestedIdentifiableCollection<AeadAlgorithm, JwtParserBuilder>(this, this.encAlgs) {","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java#L279-L315","documentation":"Thrown as IllegalArgumentException from DefaultJwtParserBuilder.decryptWith(Key) when a PublicKey is supplied for JWE decryption. Public keys encrypt; only the corresponding PrivateKey may decrypt, so passing a PublicKey indicates inverted key usage in the JWE flow.","triggerScenarios":"Calling parserBuilder.decryptWith(publicKey) to parse an encrypted JWT (JWE); typically when the developer confuses the encryption side (public key) with the decryption side (private key).","commonSituations":"Client encrypts with the recipient's public key but the recipient misconfigures decryptWith with that same public key; symmetric/asymmetric algorithm confusion after switching from MAC to RSA-OAEP; reading documentation examples out of order.","solutions":["Pass the corresponding PrivateKey to decryptWith(...) on the receiving side.","Keep the public key only on the sender's side (encryptWith / builder).","Confirm the JWE algorithm family (RSA-OAEP, ECDH-ES, dir, etc.) and that your key type matches it.","If both parties need the same key, use a symmetric SecretKey (AES) with a 'dir' or key-wrap algorithm instead."],"exampleFix":"// before\nPublicKey pub = loadRecipientPublicKey();\nJwts.parser().decryptWith(pub).build().parseEncryptedClaims(jwe); // IllegalArgumentException\n// after\nPrivateKey priv = loadRecipientPrivateKey();\nJwts.parser().decryptWith(priv).build().parseEncryptedClaims(jwe);","handlingStrategy":"type-guard","validationCode":"if (key instanceof java.security.PublicKey) {\n    throw new IllegalArgumentException(\"Refusing to configure a PublicKey for decryption\");\n}","typeGuard":"boolean isDecryptionKey(java.security.Key k) {\n    return k instanceof java.security.PrivateKey || k instanceof javax.crypto.SecretKey;\n}","tryCatchPattern":"try {\n    builder.decryptWith(key);\n} catch (IllegalArgumentException e) {\n    // PublicKey supplied: use the matching PrivateKey (or SecretKey for 'dir')\n}","preventionTips":["Remember the JWE direction: sender encrypts with recipient's public key; recipient decrypts with private key","Keep public keys out of receiving/decryption configuration","Use SecretKey with 'dir'/key-wrap algorithms only when both sides legitimately share the secret","Label key material in config (encrypt-pub vs decrypt-priv) to prevent mix-ups"],"tags":["jwt","jwe","key-management","encryption"],"backgroundTag":"invalid-argument-value","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}