PASETO in Rust — paseto-rs Quickstart
Quickstart for using paseto-rs to issue and verify PASETO v4.public tokens in Rust, including key generation and footer handling.
Detailed Explanation
Rust has excellent PASETO support via the rusty_paseto crate (sometimes called paseto-rs). It supports v1-v4, both local and public, plus PASERK.
Cargo.toml:
[dependencies]
rusty_paseto = { version = "0.7", features = ["v4_public", "v4_local"] }
serde_json = "1"
Generating a v4.public key pair:
use rusty_paseto::core::{Key, V4, Public};
let private = Key::<64>::try_new_random()?; // Ed25519 secret
let public = Key::<32>::try_from(&private[32..])?; // last 32 bytes are the public part
In practice, use the high-level PasetoBuilder API which handles key types for you.
Issuing a v4.public token:
use rusty_paseto::prelude::*;
let token = PasetoBuilder::<V4, Public>::default()
.set_claim(IssuerClaim::from("https://auth.example.com"))
.set_claim(SubjectClaim::from("user-12345"))
.set_claim(AudienceClaim::from("https://api.example.com"))
.set_claim(ExpirationClaim::try_from("2026-01-01T00:00:00Z")?)
.build(&private_key)?;
The result is a string like v4.public.eyJpc3MiOi....
Verifying a v4.public token:
use rusty_paseto::prelude::*;
let parsed = PasetoParser::<V4, Public>::default()
.check_claim(IssuerClaim::from("https://auth.example.com"))
.check_claim(AudienceClaim::from("https://api.example.com"))
.parse(&token, &public_key)?;
let payload: serde_json::Value = serde_json::from_value(parsed)?;
The parser refuses to return claims if the signature is invalid or any check_claim fails — so you can't accidentally trust an unverified payload.
Footers:
Add a footer at build time with .set_footer(Footer::from("{"kid":"key-1"}")) and read it from a parsed token via the parser API. Footers are validated as part of the signature.
Why Rust for PASETO:
Rust's strong type system maps well onto PASETO's version+purpose model — PasetoBuilder<V4, Public> and PasetoBuilder<V4, Local> are different types, so you literally can't accidentally swap them. The library leans into this to prevent misuse at compile time.
Use Case
A Rust microservice issues v4.public tokens with rusty_paseto, attaching a kid footer; downstream services verify with the matching public key configured at startup.