|  Download Paseto Version 2EncryptGiven a message m, keyk, and optional footerf. 
Set header `h` to `v2.local.`
Generate 24 random bytes from the OS's CSPRNG.
Calculate BLAKE2b of the message `m` with the output of step 2 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`, and `f` together (in that order) using 
PAE.
We'll call this `preAuth`.
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 || b64(n || c)
* Non-empty: return h || b64(n || c) || `.` || base64url(f)
* ...where || means "concatenate"
 DecryptGiven a message m, keyk, and optional footerf. 
If `f` is not empty, implementations MAY verify that the value appended
to the token matches some expected string `f`, 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 as `h`.
Decode the payload (`m` sans `h`, `f`, and the optional trailing period
between `m` and `f`) from base64url to raw binary. Set:
* `n` to the leftmost 24 bytes
* `c` to the middle remainder of the payload, excluding `n`.
Pack `h`, `n`, and `f` together (in that order) using
PAE. 
We'll call this `preAuth`
Decrypt `c` using `XChaCha20-Poly1305`, store the result in `p`.
p = crypto_aead_xchacha20poly1305_decrypt(
   ciphertext = c
   aad = preAuth
   nonce = n
   key = k
);
If decryption failed, throw an exception. Otherwise, return `p`. 
 SignGiven a message m, Ed25519 secret keysk, and
optional footerf(which defaults to empty string): 
Set `h` to `v2.public.`
Pack `h`, `m`, and `f` together using
PAE
(pre-authentication encoding). We'll call this `m2`.
Sign `m2` using Ed25519 `sk`. We'll call this `sig`.
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.
 VerifyGiven a signed message sm, public keypk, and optional footerf(which defaults to empty string): 
If `f` is not empty, implementations MAY verify that the value appended
to the token matches some expected string `f`, 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 as `h`.
Decode the payload (`sm` sans `h`, `f`, and the optional trailing period
between `m` and `f`) from base64url to raw binary. Set:
* `s` to the rightmost 64 bytes
* `m` to the leftmost remainder of the payload, excluding `s`  
Pack `h`, `m`, and `f` together using
PAE.
We'll call this `m2`.
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.
 |