About
jwecodec was created and is maintained by the YouTube channel The Seasoned Programmer, who also makes jwtcodec.com for signed JWTs. Questions or suggestions? Email info@the-seasoned-programmer.com.
Every tool on this site runs in your browser using the built-in Web Crypto API. Tokens, keys and passwords are never sent to a server.
What is a JWE?
JSON Web Encryption (RFC 7516) is the encrypted sibling of the signed JWT. A signed token proves who issued it, but anyone can read it. An encrypted token can only be read by its intended recipient. JWEs are used for encrypted ID tokens in OpenID Connect, for passing sensitive claims between services, and anywhere a token passes through hands that shouldn't see what's inside.
How it works
- The sender picks a random content encryption key (CEK) and a random IV.
- The plaintext is encrypted with the CEK using the
encalgorithm. The protected header is fed in as additional authenticated data, so changing it breaks decryption too. - The CEK is delivered to the recipient using the
algalgorithm: encrypted with their public key, wrapped with a shared key, or agreed with ECDH. - The five parts are Base64URL-encoded and joined with dots: header, encrypted key, IV, ciphertext and authentication tag.
Key management algorithms (alg)
- RSA-OAEP-256 (and -384, -512, plain RSA-OAEP with SHA-1): the CEK is encrypted with the recipient's RSA public key. The most widely supported choice.
- ECDH-ES: the sender makes a one-time (ephemeral) EC key pair, puts its public half in the header as
epk, and both sides derive the same key from it. With plain ECDH-ES that key is the CEK; withECDH-ES+A256KWit wraps a random CEK. Smaller keys than RSA, and works with P-256, P-384, P-521 and X25519. - A128KW / A256KW and A128GCMKW / A256GCMKW: both sides share an AES key, which wraps the CEK.
- dir: the shared key is the CEK, and the encrypted key part is empty.
- PBES2: a key is derived from a password with PBKDF2, using the salt
p2sand iteration countp2cfrom the header, and wraps the CEK. - RSA1_5 is deprecated because of padding-oracle attacks and isn't supported here.
Content encryption algorithms (enc)
- A128GCM / A192GCM / A256GCM: AES in Galois/Counter Mode, with a 12-byte IV and a 16-byte tag. Fast and the usual choice.
- A128CBC-HS256 / A192CBC-HS384 / A256CBC-HS512: AES-CBC for secrecy plus an HMAC for integrity. The CEK is twice as long: the first half is the HMAC key and the second half the AES key. The only content encryption every JOSE library must support.
Nested JWTs
Encryption alone doesn't prove who sent a token: anyone with the recipient's public key can encrypt one. To get both secrecy and proof of origin, sign a JWT first and then encrypt the whole signed token as the JWE plaintext, setting "cty": "JWT" in the header. The decoder recognises nested JWTs and shows their claims.
Best practices
- Allow-list algorithms when decrypting. Don't let the token's own
algandencpick anything the library knows. - Encryption isn't authentication. If it matters who created the token, use a nested (signed, then encrypted) JWT and verify the signature.
- Limit PBES2 iterations you'll accept: a huge
p2cin a malicious token makes the server burn CPU. - Prefer key wrapping to dir, so each token gets its own content key.
- Still check the claims:
exp,issandaudafter decrypting.