PASETO Version 2 is deprecated. Implementations SHOULD migrate to Version 4.
Given a message m
, key k
, and optional footer f
.
- Before encrypting, first assert that the key being used is intended for use
with
v2.local
tokens, and has a length of 256 bits (32 bytes). See Algorithm Lucidity for more information. - Set header
h
tov2.local.
Note: This includes the trailing period. - Generate 24 random bytes from the OS's CSPRNG,
b
. - Calculate BLAKE2b of the message
m
withb
as the key, with an output length of 24. This will be our nonce,n
.- This step is to ensure that an RNG failure does not result in a nonce-misuse condition that breaks the security of our stream cipher.
- Pack
h
,n
, andf
together (in that order) using PAE. We'll call thispreAuth
. - Encrypt the message using XChaCha20-Poly1305, using an AEAD interface such as
the one provided in libsodium.
c = crypto_aead_xchacha20poly1305_encrypt( message = m aad = preAuth nonce = n key = k );
- If
f
is:- Empty: return h || base64url(n || c)
- Non-empty: return h || base64url(n || c) ||
.
|| base64url(f) - ...where || means "concatenate"
- Note:
base64url()
means Base64url from RFC 4648 without=
padding.
Given a message m
, key k
, and optional footer f
.
- Before decrypting, first assert that the key being used is intended for use
with
v2.local
tokens, and has a length of 256 bits (32 bytes). See Algorithm Lucidity for more information. - If
f
is not empty, implementations MAY verify that the value appended to the token matches some expected stringf
, provided they do so using a constant-time string compare function. - Verify that the message begins with
v2.local.
, otherwise throw an exception. This constant will be referred to ash
.
Note: This includes the trailing period. - Decode the payload (
m
sansh
,f
, and the optional trailing period betweenm
andf
) from base64url to raw binary. Set:n
to the leftmost 24 bytesc
to the middle remainder of the payload, excludingn
.
- Pack
h
,n
, andf
together (in that order) using PAE. We'll call thispreAuth
- Decrypt
c
usingXChaCha20-Poly1305
, store the result inp
.p = crypto_aead_xchacha20poly1305_decrypt( ciphertext = c aad = preAuth nonce = n key = k );
- If decryption failed, throw an exception. Otherwise, return
p
.
Given a message m
, Ed25519 secret key sk
, and
optional footer f
(which defaults to empty string):
- Before signing, first assert that the key being used is intended for use
with
v2.public
tokens, and is the secret key of the intended keypair. See Algorithm Lucidity for more information. - Set
h
tov2.public.
Note: This includes the trailing period. - Pack
h
,m
, andf
together using PAE (pre-authentication encoding). We'll call thism2
. - Sign
m2
using Ed25519sk
. We'll call thissig
.sig = crypto_sign_detached( message = m2, private_key = sk );
- If
f
is:- Empty: return "
h
|| base64url(m
||sig
)" - Non-empty: return "
h
|| base64url(m
||sig
) ||.
|| base64url(f
)" - ...where || means "concatenate"
- Note:
base64url()
means Base64url from RFC 4648 without=
padding.
- Empty: return "
Given a signed message sm
, public key pk
, and optional footer f
(which defaults to empty string):
- Before verifying, first assert that the key being used is intended for use
with
v2.public
tokens, and is the public key of the intended keypair. See Algorithm Lucidity for more information. - If
f
is not empty, implementations MAY verify that the value appended to the token matches some expected stringf
, provided they do so using a constant-time string compare function. - Verify that the message begins with
v2.public.
, otherwise throw an exception. This constant will be referred to ash
.
Note: This includes the trailing period. - Decode the payload (
sm
sansh
,f
, and the optional trailing period betweenm
andf
) from base64url to raw binary. Set:s
to the rightmost 64 bytesm
to the leftmost remainder of the payload, excludings
- Pack
h
,m
, andf
together using PAE. We'll call thism2
. - Use Ed25519 to verify that the signature is valid for the message:
valid = crypto_sign_verify_detached( signature = s, message = m2, public_key = pk );
- If the signature is valid, return
m
. Otherwise, throw an exception.