PASETO (Platform-Agnostic SEcurity TOkens) Specification

repository·master·Indexed 42 days ago

https://github.com/paseto-standard/paseto-spec

A security specification for stateless tokens designed to avoid common JWT vulnerabilities by using versioned protocols instead of algorithm agility. It defines two primary purposes: 'local' for shared-key authenticated encryption and 'public' for public-key digital signatures. The specification covers protocol versions v1 through v4, including NIST-compliant and Sodium-based cryptographic primitives, token structure, and Pre-Authentication Encoding (PAE).

Tokens
12.6K
Snippets
24
Records
60
Agent score
52%

What's inside PASETO

  1. What is Paseto and how does it differ from JWT?

    master

    Paseto (Platform-Agnostic SEcurity TOkens) is a specification for secure, stateless tokens. Unlike JSON Web Tokens (JWT), which use 'algorithm agility' (allowing developers to specify an alg header that can lead to insecure configurations like none or algorithm substitution attacks), Paseto uses 'versioned protocols'.

    Paseto restricts developers to secure, authenticated modes by requiring a version and a purpose rather than an arbitrary algorithm choice. This design makes it significantly harder to use Paseto insecurely.

    Caution: Paseto is suitable for tamper-proof cookies, but it does not prevent replay attacks by itself and should not be used for stateless session management without additional protections.

  2. Overview of PASETO implementation components

    master

    When implementing PASETO, the protocol is divided into two distinct parts that must be handled:

    1. The cryptography protocol: This is the layer that protects the payload. It is defined by specific protocol versions, and each version may impose unique requirements to ensure cryptographic security. Implementors must follow the established rules for current and future protocol versions.
    2. The payload: The actual data being protected by the cryptography protocol.

    Implementors should refer to the specific protocol version requirements to ensure the cryptographic layer is correctly applied to the payload.

  3. How v3.local and v4.local handle nonces and HKDF

    master

    In v3 and v4, the handling of randomness and key derivation has been standardized for better security analysis:

    • No Nonce-Hashing: Unlike earlier versions, v3.local and v4.local do not pre-hash the message and random value to derive a nonce. This avoids a failure mode where a weak RNG could allow offline plaintext attacks.
    • HKDF Salt Usage: The entire 32-byte random value is used in the HKDF step and appended to the info tag.
    • Key and Nonce Derivation: The HKDF output (384 bits for v3.local, 448 bits for v4.local) is used to derive both the key and the nonce. The first 32 bytes of the HKDF output are used as the key, and the remaining bytes are used as the nonce for the underlying cipher (AES-256-CTR or XChaCha20).
  4. Understand Paseto token structure and purposes

    master

    A Paseto token consists of a header, a payload, and a signature/authentication tag. The header defines the version and the purpose. There are two primary purposes:

    1. local: Used for shared-key authenticated encryption (symmetric-key, AEAD). The payload is encrypted.
    2. public: Used for public-key digital signatures (asymmetric-key). The payload is visible but signed.

    Tokens may also include an optional footer, which is always cleartext but base64url-encoded. The header and footer are included in the signature or authentication tag to ensure integrity.

    ### Paseto Example 1 (local)
    v2.local.QAxIpVe-ECVNI1z4xQbm_qQYomyT3h8FtV8bxkz8pBJWkT8f7HtlOpbroPDEZUKop_vaglyp76CzYy375cHmKCW8e1CCkV0Lflu4GTDyXMqQdpZMM1E6OaoQW27gaRSvWBrR3IgbFIa0AkuUFw.UGFyYWdvbiBJbml0aWF0aXZlIEVudGVycHJpc2Vz
    
    ### Paseto Example 2 (public)
    v2.public.eyJleHAiOiIyMDM5LTAxLTAxVDAwOjAwOjAwKzAwOjAwIiwiZGF0YSI6InRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSJ91gC7-jCWsN3mv4uJaZxZp0btLJgcyVwL-svJD7f4IHyGteKe3HTLjHYTGHI1MtCqJ-ESDLNoE7otkIzamFskCA
  5. Understand the differences between PASETO v3 and v4 modes

    master

    PASETO v3 and v4 introduce new cryptographic modes to address security properties like key-commitment and NIST compliance.

    • v4.local: Uses XChaCha20 for encryption and a keyed BLAKE2b hash (acting as HMAC) for the authentication tag. This provides better key- and message-commitment than v2.local.
    • v3.public: Designed for NIST-dependent applications. It uses ECDSA over the NIST P-384 curve with SHA-384. It is recommended to use RFC 6979 deterministic signatures.
    • v4.public: Uses Ed25519 (similar to v2.public) but is the preferred choice if you want to avoid NIST curves and potential NSA backdoor concerns.
    • v3.local / v4.public: These modes do not introduce specific cryptographic changes from their predecessors but benefit from broader improvements like implicit assertions and better HKDF salt usage.
  6. Use the optional footer for application-specific data

    master

    PASETO includes an optional, authenticated footer. Unlike the payload, the footer's contents are not restricted to JSON, though they may be JSON-encoded. The footer is intended for free-form, application-specific data.

    Security Warning: The footer's contents are not authenticated until the authentication tag has been verified. Any data extracted from the footer must be treated as untrusted until the payload verification is complete.

  7. Use implicit assertions in v3 and v4 tokens

    master

    PASETO v3 and v4 support implicit assertions. These are pieces of additional authenticated data (AAD) that are not stored within the token itself but are used to calculate the authentication tag (for local tokens) or the signature (for public tokens).

    Use this feature to bind a token to a specific context without leaking sensitive internal values in the token payload. For example, in a multi-tenant system, you can provide a user_account_id during both minting and validation to ensure a token is only valid within that specific user's context.

  8. Format PASETO payloads as JSON objects

    master

    All PASETO payloads must be a JSON-encoded object represented as a UTF-8 encoded string. The topmost JSON structure must be an object, map, or associative array. It cannot be a flat array, a list, or an empty string.

    Valid examples:

    • {"foo":"bar"}
    • {"foo":"bar","baz":12345,"678":["a","b","c"]}
    • {}

    Invalid examples:

    • [{"foo":"bar"}] (Array)
    • ["foo"] (Array)
    • {0: "test"} (Integer keys)
    • [] (Empty array)
    • "" (Empty string)
    • {"foo":"bar","foo":"baz"} (Duplicate keys)

    If you need to include non-UTF-8 character sets within fields, use Base64url encoding to preserve the binary data while keeping the overall payload UTF-8 compliant.

  9. Compress ECDSA Public Keys for P-384

    master

    Paseto v3 requires ECDSA public keys to use point compression. A compressed public key is 49 bytes long:

    1. The first byte is 0x02 if the Y coordinate's least significant bit is 0, or 0x03 if it is 1.
    2. The remaining 48 bytes are the X coordinate in big-endian byte order.
    lsb(y):
       return y[y.length - 1] & 1
    
    pubKeyCompress(x, y):
       header = [0x02 + lsb(y)]
       return header.concat(x)
  10. Understand Builders and Parsers in PASETO

    master

    PASETO implementations rely on two primary abstractions for handling tokens:

    • Builder: A function or class responsible for assembling an encrypted or signed PASETO token at runtime.
    • Parser: A function or class that verifies the cryptographic integrity of a token. It also allows users to assert that token claims conform to specific expectations via Parser Rules.
  11. Identify PASETO version families and compatibility rules

    master

    PASETO versions are organized into two parallel families. By default, libraries should only support the two most recent versions within a specific family to maintain security standards.

    • NIST Family: Includes Version 1 and Version 3. Use these if you require NIST-compliant algorithms (like AES or ECDSA).
    • Sodium Family: Includes Version 2 and Version 4. Use these if you prefer modern, high-performance primitives like XChaCha20 or Ed25519.

    Note on Future Versions: If a Version 5 (NIST) or Version 6 (Sodium) is introduced, Version 1 and Version 2 should be considered deprecated and no longer accepted by default.

  12. Implement Misuse Resistance by constraining Builders and Parsers

    master

    To prevent security vulnerabilities like protocol downgrade attacks, Builders and Parsers should be strictly constrained to a single (Version, Purpose) tuple.

    • Constraint: A single instance of a Builder or Parser SHOULD only accept one version of the PASETO protocol and one purpose (e.g., v4.local).
    • Handling Multiple Versions: If an application needs to support multiple versions or purposes, it should instantiate different Builder/Parser instances for each and map incoming tokens to the correct instance at runtime.
    • Version Routing: Libraries SHOULD NOT provide version routing out-of-the-box. If a library provides a version router (as a separate module), it MUST fail closed (e.g., throw an exception) if a user provides a version/purpose for which no key has been specified. A strict allow-list of permitted versions and purposes is recommended.
    • Key ID Support: If a library supports parsing the footer for Key IDs, it MUST ensure all keys in the keyring match the expected key and purpose of that specific Builder or Parser. This validation must be handled by the library, not the user.