Skip to content
Platform-Agnostic Security Tokens
Branch: master
Clone or download
paragonie-scott Merge pull request #93 from djmarland/master
Allow DateTimeImmutable everywhere
Latest commit dac54fb Oct 17, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs fix: Test Vector v2-S-2 footer kid May 30, 2019
src Allow DateTimeImmutable everywhere Jan 3, 2019
tests Merge pull request #87 from mjpieters/fix-test-names Jul 31, 2018
.gitignore Rename file to be consistent with the RFC Editors' expectations. Apr 9, 2018
.travis.yml Allow Psalm 2, PHP 7.3 Jan 3, 2019
LICENSE Add license file. Jan 2, 2018 Support contracts are available Jan 3, 2019
psalm.xml Allow Psalm 2, PHP 7.3 Jan 3, 2019

PASETO: Platform-Agnostic Security Tokens

Build Status Latest Stable Version Latest Unstable Version License Downloads

Paseto is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.

What follows is a reference implementation. Requires PHP 7 or newer.

What is Paseto?

Paseto (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.

Key Differences between Paseto and JWT

Unlike JSON Web Tokens (JWT), which gives developers more than enough rope with which to hang themselves, Paseto only allows secure operations. JWT gives you "algorithm agility", Paseto gives you "versioned protocols". It's incredibly unlikely that you'll be able to use Paseto in an insecure way.

Caution: Neither JWT nor Paseto were designed for stateless session management. Paseto is suitable for tamper-proof cookies, but cannot prevent replay attacks by itself.


Paseto Example 1


This decodes to:

  • Version: v2
  • Purpose: local (shared-key authenticated encryption)
  • Payload (hex-encoded):
    • Nonce: 400c48a557be10254d235cf8c506e6fea418a26c93de1f05
    • Authentication tag: 6914af581ad1dc881b1486b4024b9417
  • Decrypted Payload:
      "data": "this is a signed message",
      "exp": "2039-01-01T00:00:00+00:00"
    • Key used in this example (hex-encoded):
  • Footer:
    Paragon Initiative Enterprises

Paseto Example 2


This decodes to:

  • Version: v2
  • Purpose: public (public-key digital signature)
  • Payload:
      "data": "this is a signed message",
      "exp": "2039-01-01T00:00:00+00:00"
  • Signature (hex-encoded):
  • Public key (hex-encoded):

To learn what each version means, please see this page in the documentation.


An example JWT (taken from might look like this:


This decodes to:


  "alg": "HS256",
  "typ": "JWT"


  "sub": "1234567890",
  "name": "John Doe",
  "admin": true




As you can see, with JWT, you get to specify an alg header. There are a lot of options to choose from (including none).

There have been ways to exploit JWT libraries by replacing RS256 with HS256 and using the known public key as the HMAC-SHA256 key, thereby allowing arbitrary token forgery.

With Paseto, your options are version and a purpose. There are two possible values for purpose:

  • local -- shared-key encryption (symmetric-key, AEAD)
  • public -- public-key digital signatures (asymmetric-key)

Paseto only allows you to use authenticated modes.

Regardless of the purpose selected, the header (and an optional footer, which is always cleartext but base64url-encoded) is included in the signature or authentication tag.

How to Use this Library

See the documentation.

The section dedicated to this PHP implementation may be more relevant.

Other Implementations

The curation of other implementations has been moved to See for the website source code.

Support Contracts

If your company uses this library in their products or services, you may be interested in purchasing a support contract from Paragon Initiative Enterprises.

You can’t perform that action at this time.