PASETO Token Anatomy — From String to Bytes

Detailed walkthrough of how a PASETO token is laid out on the wire, how each segment is encoded, and where the signature or auth tag lives inside the payload.

Structure

Detailed Explanation

Understanding the layout of a PASETO token byte-by-byte is the fastest way to debug issuance and verification bugs.

Top-level structure:

vN.purpose.<payload-segment>[.<footer-segment>]

There are 3 or 4 dot-separated parts. The first two — vN and purpose — are plain ASCII; everything else is Base64url with no padding.

Header segment:

The first two parts together form the header string that's bound into the cryptographic operation via pre-authentication encoding (PAE). Examples: v4.public, v4.local, v3.public, v2.local. There is no JSON header like JWT has — the header is the literal concatenation of the version and purpose strings.

Payload segment for public tokens:

After Base64url decoding, the payload segment for v*.public is the UTF-8 JSON message followed by the signature bytes. Signature lengths:

  • v1.public: 256 bytes (RSA-PSS-2048)
  • v2.public: 64 bytes (Ed25519)
  • v3.public: 96 bytes (ECDSA P-384, raw R||S)
  • v4.public: 64 bytes (Ed25519)

To extract the JSON, decode the segment and slice off the trailing N bytes.

Payload segment for local tokens:

For v*.local, the layout after Base64url decoding is: nonce, ciphertext, tag — concatenated. Lengths:

  • v1.local: 32-byte nonce, ciphertext, 48-byte HMAC-SHA384 tag
  • v2.local: 24-byte nonce, ciphertext, 16-byte Poly1305 tag
  • v3.local: 32-byte nonce, ciphertext, 48-byte HMAC-SHA384 tag
  • v4.local: 32-byte nonce, ciphertext, 32-byte BLAKE2b tag

The ciphertext is exactly the length of the plaintext JSON — no padding.

Footer segment:

If present, the footer is just Base64url-encoded raw bytes. PASETO doesn't impose any structure — your application defines it. By convention, JSON footers are common.

Pre-authentication encoding (PAE):

This is the magic glue that prevents bytes from being moved between segments. PAE concatenates the count of items, then for each item its little-endian length followed by its bytes. The signature/tag is computed over PAE(header, body, footer) (and implicit assertions in v3/v4). Tampering with any segment changes PAE and breaks verification.

Use Case

A developer building a custom PASETO library uses this anatomy to write a parser that correctly slices the trailing 64-byte signature off a v4.public payload before handing the JSON to the application.

Try It — PASETO Decoder

Open full tool