PASETO 解码器与验证工具
粘贴 PASETO 令牌,查看其中携带的内容:版本和用途、声明、页脚。添加颁发者的公钥,即可验证 public 令牌的签名。
100% 本地处理——令牌和密钥都在你的浏览器中解码和验证,不会发送到任何服务器
令牌
示例:官方 PASETO 测试向量(paseto-standard/test-vectors),以及随之发布的公钥。
PASETO in one paragraph
PASETO — Platform-Agnostic Security Tokens, specified at paseto-standard/paseto-spec — carries the same kind of claims as a JWT, with one design decision changed: the token does not say which algorithm protects it. A JWT's header names its alg, and a verifier that trusts the header can be talked into none or into checking an RSA signature as an HMAC (RFC 8725 §2.1). A PASETO token names a version and a purpose, and each pair fixes exactly one algorithm. There is nothing to negotiate.
Version, purpose, payload, footer
A token is three or four parts separated by dots: v4.public.<payload> or v4.public.<payload>.<footer>.
| Token | Protection | Algorithm |
|---|---|---|
v4.public | signed | Ed25519 |
v4.local | encrypted | XChaCha20 with a BLAKE2b MAC |
v3.public | signed | ECDSA on P-384 with SHA-384 |
v3.local | encrypted | AES-256-CTR with HMAC-SHA-384 |
Version 4 uses modern primitives; version 3 the NIST ones, for environments that require them. Versions 1 and 2 are retired: the decoder recognises them and tells you so instead of trying.
For a public token the payload is the message — usually a JSON object of claims — followed by the signature: 64 bytes for v4, 96 for v3. The claims are readable by anyone, which is why the decoder shows them at once, marked as unverified until the signature checks. For a local token the payload is a nonce, the ciphertext and an authentication tag; the decoder shows their sizes. Decrypting needs the shared key and is not offered here.
The optional footer is authenticated but not encrypted. It typically carries a key identifier, for example {"kid":"…"}, which the verifier reads to choose a key before checking the signature. An implicit assertion (versions 3 and 4) is authenticated too but never appears in the token: issuer and verifier both supply it — a tenant or a user ID, say — and the signature only checks when they agree. That is why the decoder asks for it.
How the signature is checked
PASETO never signs the base64 text of a token. It signs a pre-authentication encoding (PAE): every piece — the header v4.public., the message, the footer, the implicit assertion — prefixed with its length as a 64-bit little-endian integer, so that no two different combinations of pieces can produce the same bytes. Version 3 also puts the signer's compressed public key in front, binding the signature to the key. The decoder rebuilds this encoding and verifies with the audited @noble/curves: Ed25519 for v4, ECDSA P-384 with SHA-384 for v3.
A failed check has three usual causes: the token was changed, the footer or implicit assertion differs from what the issuer used, or the key is not the issuer's. The key must fit the version — an Ed25519 key for v4, a P-384 key for v3 — and the decoder refuses a key of the wrong kind rather than reporting a misleading "invalid". It reads keys as PEM, as a JWK, or as raw bytes in hex: 32 bytes for Ed25519, a compressed point for P-384. Need a key for testing? The key generator makes Ed25519 and P-384 key pairs, and the JWK converter changes their encoding.
Claims and time
PASETO's registered claims mirror JWT's — iss, sub, aud, exp, nbf, iat, jti — with one difference that trips up people moving between the two: times are ISO 8601 strings such as 2026-12-31T23:59:59+00:00, not seconds since 1970. After a successful verification the decoder checks exp, nbf and iat against the current time and flags values that are not ISO 8601 dates. To compare with a JWT built from the same claims, sign one in the JWT signer and open it in the JWT debugger.
What stays in your browser
Decoding and verification run on the page; nothing you paste is sent anywhere. A public token, a public key and an implicit assertion are public data, so a share link carries all three — except a key pasted as bare 32 bytes, which cannot be told apart from a private Ed25519 seed and is therefore left out; share the PEM form instead.