Published on

What is PASETO?

Authors
  • avatar
    Name
    Jay
    Twitter

A Look at PASETO's Features

I recently overheard a developer mention they had implemented PASETO (Platform-Agnostic Security Tokens) in their system, which sparked my curiosity. After doing some research, I discovered that PASETO is a modern specification designed to improve upon the well-known JOSE (JavaScript Object Signing and Encryption) standards, which include JWTs.

The creator of PASETO argues that the flexibility of the JOSE specification can lead developers to accidentally introduce security flaws. A prime example he cites on this talk is CVE-2015-2964, where attackers could bypass signature verification by manipulating the alg (algorithm) header in a JWT.

PASETO distinguishes itself from JOSE with a few key design choices that enhance security and clarity.

1. Clear and Unambiguous Purpose

PASETO eliminates confusion by offering only two distinct modes of operation, or "purposes":

  • local: For when you need confidentiality. The token is encrypted symmetrically with a shared secret key.
  • public: For when you need authenticity. The token is signed asymmetrically with a private key and can be verified by anyone with the corresponding public key.

2. Versioning for Easy Upgrades

PASETO uses a straightforward versioning system (v1, v2, v3, v4) that makes it simple to adopt stronger security standards over time. Each version has a static, hardcoded set of cryptographic algorithms that are considered best-in-class for their time.

For instance, the official specification explicitly states which algorithm must be used for each version, leaving no room for ambiguity.

  • v1: Sign m2 using RSA with the private key sk.
  • v2: Sign m2 using Ed25519 sk. We'll call this sig.
  • v3: Sign m2 using ECDSA over P-384 and SHA-384 with the private key sk.
  • v4: Sign m2 using Ed25519 sk. We'll call this sig.

Is PASETO Practical for a Node.js Project?

Now that I have a better understanding of PASETO, the next logical question is: would adopting it actually benefit my current system? Since I work primarily in the Node.js ecosystem, I decided to evaluate the available libraries from that specific perspective.

The official PASETO website lists two packages for Node.js.

My investigation into the first option, panva/paseto, quickly hit a roadblock. The GitHub repository is archived, meaning it is no longer actively maintained. The project's readme states:

This project is now archived. It may get revived when v5 and v6 protocol versions get released and their underlying crypto becomes readily available in Web Cryptography API implementations across JavaScript runtimes.

The PASETO specification is simple and very clear. However, it raises an important question: is it the best choice to rely on a package that has been archived and hasn't had a new release since April 28, 2023?

So, I moved on to the second option, paseto-ts. This project starts to meet V4 specification. However, the project appears less mature when compared to panva/paseto. A quick look at its NPM statistics was revealing: it has just over 1,000 weekly downloads. For context, the archived panva/paseto package still has over 24,000 weekly downloads (jsonwebtoken package has over 21 million weekly downloads.)

In conclusion, the state of its Node.js ecosystem left me hesitant. The community support and library maturity don't seem to be on par with JOSE packages, which is a critical factor when choosing a security component for a production system.

What about applying PASETO algorithm?

One of PASETO's main benefits is that it mandates the use of up-to-date, secure algorithms for encryption and signing. For example, the latest version, v4, uses Ed25519 for signing.

This led me to wonder: could I get the best of both worlds by using this modern algorithm within my existing JWT setup? šŸ¤”

In my projects, I often use the NestJS framework with the official @nestjs/jwt module. This module, however, relies on the popular jsonwebtoken package internally. A look at the jsonwebtoken documentation shows it does not support Ed25519. It only provides ECDSA variants:

  • ECDSA using P-256 curve and SHA-256 hash algorithm
  • ECDSA using P-384 curve and SHA-384 hash algorithm
  • ECDSA using P-521 curve and SHA-512 hash algorithm

Well, one of benefit of PASETO is set to up to date secure algorithm for encypt and sign. The latest version v4 use Ed25519. I asked myself what about using this algorithm in JWT library. If you leverage nestjs framework and utilize nest jwt module, it utilize jsonwebtoken package internally. jsonwebtoken package provide

  • ECDSA using P-256 curve and SHA-256 hash algorithm
  • ECDSA using P-384 curve and SHA-384 hash algorithm
  • ECDSA using P-521 curve and SHA-512 hash algorithm

A comparison between Ed25519 and ECDSA reveals that Ed25519 has some advantages.

  • Better Performance šŸš€: It offers faster signing and, most importantly, much faster signature verification.
  • Safer Implementation: It ensures a unique nonce is generated deterministically from the private key and message hash. ECDSA, in contrast, requires a high-quality source of randomness for its nonces; a mistake in this process can lead to a catastrophic leak of the private key.

Fortunately, another popular package for JOSE, pnva/jose, allows you to use ed25519!

Conclusion

It was fascinating to learn about a new specification like PASETO and the problems it aims to solve. From the perspective of a developer who implements cryptographic standards, PASETO's simple and clear specification offers significant benefits.

However, as someone who just uses packages implemented by others, my priorities are different. I care more about whether a project is well-maintained and supported by a healthy community. From this standpoint, the PASETO ecosystem in Node.js is not yet as strong as the one for established JOSE libraries.

Furthermore, PASETO's public mode does not align with my use case. I mainly generate JWTs symmetrically for bearer tokens, and my system doesn't require other services to verify these tokens with a public key. PASETO's public mode only supports asymmetric signing.

For these reasons—the current maturity of the Node.js ecosystem and my specific technical requirements—I've decided to stick with my current JWT implementation for now.