PASETO v4.local Basics

Learn how PASETO v4.local tokens encrypt payloads with XChaCha20 + BLAKE2b, why they're authenticated, and when to choose them over v4.public.

Version

Detailed Explanation

v4.local is the symmetric, encrypted variant of PASETO v4. Unlike v4.public, the payload is not just signed — it's encrypted, so a recipient without the symmetric key sees only opaque ciphertext bytes. This makes v4.local ideal when the same service both issues and consumes its own tokens (e.g. server-side session cookies) and you don't want claims to be readable by intermediate parties.

Cryptography:

v4.local uses XChaCha20 for encryption and BLAKE2b keyed-hash for authentication. The 32-byte tag at the end of the message is a BLAKE2b-MAC over the ciphertext, the version+purpose header, the random nonce, and the optional footer (via PAE). XChaCha20's 192-bit nonce means random nonces are safe at scale — there's no realistic risk of nonce collision even across billions of tokens.

Wire format:

v4.local.<base64url(nonce || ciphertext || tag)>[.<base64url(footer)>]

The middle segment decodes to: 32-byte random nonce, then variable-length encrypted payload, then 32-byte authentication tag. A decoder without the key can show you the version, purpose, footer, and approximate ciphertext length, but cannot reveal the JSON claims.

Why use local instead of public:

Three main reasons: (1) performance — symmetric primitives are 10-100x faster than Ed25519 sign/verify; (2) confidentiality — the payload is not readable, which matters when you're storing session data or PII inside the token; (3) simpler key management when there's only one trust domain. The trade-off is that anyone with the key can both issue and verify, so leaked keys are catastrophic.

Common mistakes:

Don't confuse v4.local encryption with general-purpose encryption — PASETO encrypts a token's payload, not arbitrary blobs. For arbitrary data, use a high-level AEAD library directly. And never use the same key for both v4.local and other purposes; PASETO keys should be dedicated.

Use Case

A web app stores user session data inside a v4.local cookie, encrypted with a server-side key — the browser holds the cookie but cannot read the claims, and only the server can verify and decrypt.

Try It — PASETO Decoder

Open full tool