idnits 2.17.1 draft-paragon-paseto-rfc-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- == There are 2 instances of lines with non-RFC2606-compliant FQDNs in the document. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == Line 869 has weird spacing: '...ccccccc ccccc...' == Line 870 has weird spacing: '...kkkkkkk kkkkk...' == Line 871 has weird spacing: '...kkkkkkk kkkkk...' == Line 872 has weird spacing: '...bbbbbbb nnnnn...' == Line 876 has weird spacing: '...ccccccc ccccc...' == (3 more instances...) -- The document date (April 19, 2018) is 2193 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Informational ---------------------------------------------------------------------------- -- Looks like a reference, but probably isn't: '1' on line 1094 -- Looks like a reference, but probably isn't: '2' on line 1096 -- Looks like a reference, but probably isn't: '3' on line 1099 -- Looks like a reference, but probably isn't: '4' on line 1101 -- Looks like a reference, but probably isn't: '5' on line 1103 -- Looks like a reference, but probably isn't: '6' on line 1105 -- Looks like a reference, but probably isn't: '7' on line 1107 -- Looks like a reference, but probably isn't: '8' on line 1109 ** Obsolete normative reference: RFC 7539 (Obsoleted by RFC 8439) Summary: 1 error (**), 0 flaws (~~), 8 warnings (==), 10 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 (No Working Group) S. Arciszewski 3 Internet-Draft Paragon Initiative Enterprises 4 Intended status: Informational S. Haussmann 5 Expires: October 21, 2018 Rensselaer Polytechnic Institute 6 April 19, 2018 8 PASETO: Platform-Agnostic SEcurity TOkens 9 draft-paragon-paseto-rfc-00 11 Abstract 13 Platform-Agnostic SEcurity TOkens (PASETOs) provide a 14 cryptographically secure, compact, and URL-safe representation of 15 claims that may be transferred between two parties. The claims are 16 encoded in JavaScript Object Notation (JSON), version-tagged, and 17 either encrypted using shared-key cryptography or signed using 18 public-key cryptography. 20 Status of This Memo 22 This Internet-Draft is submitted in full conformance with the 23 provisions of BCP 78 and BCP 79. 25 Internet-Drafts are working documents of the Internet Engineering 26 Task Force (IETF). Note that other groups may also distribute 27 working documents as Internet-Drafts. The list of current Internet- 28 Drafts is at http://datatracker.ietf.org/drafts/current/. 30 Internet-Drafts are draft documents valid for a maximum of six months 31 and may be updated, replaced, or obsoleted by other documents at any 32 time. It is inappropriate to use Internet-Drafts as reference 33 material or to cite them other than as "work in progress." 35 This Internet-Draft will expire on October 21, 2018. 37 Copyright Notice 39 Copyright (c) 2018 IETF Trust and the persons identified as the 40 document authors. All rights reserved. 42 This document is subject to BCP 78 and the IETF Trust's Legal 43 Provisions Relating to IETF Documents 44 (http://trustee.ietf.org/license-info) in effect on the date of 45 publication of this document. Please review these documents 46 carefully, as they describe your rights and restrictions with respect 47 to this document. Code Components extracted from this document must 48 include Simplified BSD License text as described in Section 4.e of 49 the Trust Legal Provisions and are provided without warranty as 50 described in the Simplified BSD License. 52 Table of Contents 54 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 55 1.1. Difference Between PASETO and JOSE . . . . . . . . . . . 3 56 1.2. Notation and Conventions . . . . . . . . . . . . . . . . 3 57 2. PASETO Message Format . . . . . . . . . . . . . . . . . . . . 3 58 2.1. Base64 Encoding . . . . . . . . . . . . . . . . . . . . . 4 59 2.2. Authentication Padding . . . . . . . . . . . . . . . . . 4 60 2.2.1. PAE Definition . . . . . . . . . . . . . . . . . . . 5 61 3. Protocol Versions . . . . . . . . . . . . . . . . . . . . . . 6 62 3.1. PASETO Protocol Guidelines . . . . . . . . . . . . . . . 6 63 4. PASETO Protocol Version v1 . . . . . . . . . . . . . . . . . 7 64 4.1. v1.local . . . . . . . . . . . . . . . . . . . . . . . . 7 65 4.2. v1.public . . . . . . . . . . . . . . . . . . . . . . . . 8 66 4.3. Version v1 Algorithms . . . . . . . . . . . . . . . . . . 8 67 4.3.1. v1.GetNonce . . . . . . . . . . . . . . . . . . . . . 8 68 4.3.2. v1.Encrypt . . . . . . . . . . . . . . . . . . . . . 8 69 4.3.3. v1.Decrypt . . . . . . . . . . . . . . . . . . . . . 9 70 4.3.4. v1.Sign . . . . . . . . . . . . . . . . . . . . . . . 11 71 4.3.5. v1.Verify . . . . . . . . . . . . . . . . . . . . . . 12 72 5. PASETO Protocol Version v2 . . . . . . . . . . . . . . . . . 13 73 5.1. v2.local . . . . . . . . . . . . . . . . . . . . . . . . 13 74 5.2. v2.public . . . . . . . . . . . . . . . . . . . . . . . . 13 75 5.3. Version v2 Algorithms . . . . . . . . . . . . . . . . . . 13 76 5.3.1. v2.Encrypt . . . . . . . . . . . . . . . . . . . . . 13 77 5.3.2. v2.Decrypt . . . . . . . . . . . . . . . . . . . . . 14 78 5.3.3. v2.Sign . . . . . . . . . . . . . . . . . . . . . . . 15 79 5.3.4. v2.Verify . . . . . . . . . . . . . . . . . . . . . . 16 80 6. Payload Processing . . . . . . . . . . . . . . . . . . . . . 16 81 6.1. Registered Claims . . . . . . . . . . . . . . . . . . . . 17 82 6.1.1. Key-ID Support . . . . . . . . . . . . . . . . . . . 17 83 7. AEAD_XChaCha20_Poly1305 . . . . . . . . . . . . . . . . . . . 18 84 7.1. Motivation for XChaCha20-Poly1305 . . . . . . . . . . . . 19 85 7.2. HChaCha20 . . . . . . . . . . . . . . . . . . . . . . . . 19 86 7.2.1. Test Vector for the HChaCha20 Block Function . . . . 20 87 8. Intended Use-Cases for PASETO . . . . . . . . . . . . . . . . 20 88 9. Security Considerations . . . . . . . . . . . . . . . . . . . 21 89 10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 22 90 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 22 91 11.1. Normative References . . . . . . . . . . . . . . . . . . 22 92 11.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 24 93 Appendix A. PASETO Test Vectors . . . . . . . . . . . . . . . . 24 94 A.1. PASETO v1 Test Vectors . . . . . . . . . . . . . . . . . 25 95 A.1.1. v1.local (Shared-Key Encryption) Test Vectors . . . . 25 96 A.1.2. v1.public (Public-Key Authentication) Test Vectors . 27 98 A.2. PASETO v2 Test Vectors . . . . . . . . . . . . . . . . . 29 99 A.2.1. v2.local (Shared-Key Encryption) Test Vectors . . . . 29 100 A.2.2. v2.public (Public-Key Authentication) Test Vectors . 31 101 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 31 103 1. Introduction 105 A Platform-Agnostic SEcurity TOken (PASETO) is a cryptographically 106 secure, compact, and URL-safe representation of claims intended for 107 space-constrained environments such as HTTP Cookies, HTTP 108 Authorization headers, and URI query parameters. A PASETO encodes 109 claims to be transmitted in a JSON [RFC8259] object, and is either 110 encrypted symmetrically or signed using public-key cryptography. 112 1.1. Difference Between PASETO and JOSE 114 The key difference between PASETO and the JOSE family of standards 115 (JWS [RFC7516], JWE [RFC7517], JWK [RFC7518], JWA [RFC7518], and JWT 116 [RFC7519]) is that JOSE allows implementors and users to mix and 117 match their own choice of cryptographic algorithms (specified by the 118 "alg" header in JWT), while PASETO has clearly defined protocol 119 versions to prevent unsafe configurations from being selected. 121 PASETO is defined in two pieces: 123 1. The PASETO Message Format, defined in Section 2 125 2. The PASETO Protocol Version, defined in Section 3 127 1.2. Notation and Conventions 129 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 130 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 131 document are to be interpreted as described in RFC 2119 [RFC2119]. 133 2. PASETO Message Format 135 PASETOs consist of three or four segments, separated by a period (the 136 ASCII character whose number, represented in hexadecimal, is 2E). 138 Without the Optional Footer: 140 version.purpose.payload 142 With the Optional Footer: 144 version.purpose.payload.footer 146 If no footer is provided, implementations SHOULD NOT append a 147 trailing period to each payload. 149 The *version* is a string that represents the current version of the 150 protocol. Currently, two versions are specified, which each possess 151 their own ciphersuites. Accepted values: *v1*, *v2*. 153 The *purpose* is a short string describing the purpose of the token. 154 Accepted values: *local*, *public*. 156 o *local*: shared-key authenticated encryption 158 o *public*: public-key digital signatures; *not encrypted* 160 The *payload* is a string that contains the token's data. In a 161 "local" token, this data is encrypted with a symmetric cipher. In a 162 "public" token, this data is _unencrypted_. 164 Any optional data can be appended to the *footer*. This data is 165 authenticated through inclusion in the calculation of the 166 authentication tag along with the header and payload. The *footer* 167 MUST NOT be encrypted. 169 2.1. Base64 Encoding 171 The payload and footer in a PASETO MUST be encoded using base64url as 172 defined in [RFC4648], without "=" padding. 174 In this document. "b64()" refers to this unpadded variant of 175 base64url. 177 2.2. Authentication Padding 179 Multi-part messages (e.g. header, content, footer) are encoded in a 180 specific manner before being passed to the appropriate cryptographic 181 function. 183 In "local" mode, this encoding is applied to the additional 184 associated data (AAD). In "public" mode, which is not encrypted, 185 this encoding is applied to the components of the token, with respect 186 to the protocol version being followed. 188 We will refer to this process as *PAE* in this document (short for 189 Pre-Authentication Encoding). 191 2.2.1. PAE Definition 193 "PAE()" accepts an array of strings. 195 "LE64()" encodes a 64-bit unsigned integer into a little-endian 196 binary string. The most significant bit MUST be set to 0 for 197 interoperability with programming languages that do not have unsigned 198 integer support. 200 The first 8 bytes of the output will be the number of pieces. 201 Currently, this will be 3 or 4. This is calculated by applying 202 "LE64()" to the size of the array. 204 Next, for each piece provided, the length of the piece is encoded via 205 "LE64()" and prefixed to each piece before concatenation. 207 function LE64(n) { 208 var str = ''; 209 for (var i = 0; i < 8; ++i) { 210 if (i === 7) { 211 n &= 127; 212 } 213 str += String.fromCharCode(n & 255); 214 n = n >>> 8; 215 } 216 return str; 217 } 218 function PAE(pieces) { 219 if (!Array.isArray(pieces)) { 220 throw TypeError('Expected an array.'); 221 } 222 var count = pieces.length; 223 var output = LE64(count); 224 for (var i = 0; i < count; i++) { 225 output += LE64(pieces[i].length); 226 output += pieces[i]; 227 } 228 return output; 229 } 231 JavaScript implementation of Pre-Authentication Encoding (PAE) 233 As a consequence: 235 o "PAE([])" will always return "\x00\x00\x00\x00\x00\x00\x00\x00" 237 o "PAE([''])" will always return 238 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 240 o "PAE(['test'])" will always return "\x01\x00\x00\x00\x00\x00\x00\x 241 00\x04\x00\x00\x00\x00\x00\x00\x00test" 243 o "PAE('test')" will throw a "TypeError" 245 As a result, partially controlled plaintext cannot be used to create 246 a collision. Either the number of pieces will differ, or the length 247 of one of the fields (which is prefixed to user-controlled input) 248 will differ, or both. 250 Due to the length being expressed as an unsigned 64-bit integer, it 251 is infeasible to encode enough data to create an integer overflow. 253 This is not used to encode data prior to decryption, and no decoding 254 function is provided or specified. This merely exists to prevent 255 canonicalization attacks. 257 3. Protocol Versions 259 This document defines two protocol versions, *v1* and *v2*. 261 Each protocol version strictly defines the cryptographic primitives 262 used. Changes to the primitives requires new protocol versions. 263 Future RFCs MAY introduce new PASETO protocol versions by continuing 264 the convention (e.g. *v3*, *v4*, ...). 266 Both *v1* and *v2* provide authentication of the entire PASETO 267 message, including the *version*, *purpose*, *payload*, and *footer*. 269 The initial recommendation is to use *v2*, allowing for upgrades to 270 possible future versions *v3*, *v4*, etc. when they are defined in 271 the future. 273 3.1. PASETO Protocol Guidelines 275 When defining future protocol versions, the following rules SHOULD or 276 MUST be followed: 278 1. Everything in a token MUST be authenticated. Attackers should 279 never be allowed the opportunity to alter messages freely. 281 * If encryption is specified, unauthenticated modes (e.g. AES- 282 CBC without a MAC) are forbidden. 284 * The nonce or initialization vector must be covered by the 285 authentication tag, not just the ciphertext. 287 2. Some degree of nonce-misuse resistance SHOULD be provided: 289 * Supporting larger nonces (longer than 128-bit) is sufficient 290 for satisfying this requirement, provided the nonce is 291 generated by a cryptographically secure random number 292 generator, such as */dev/urandom* on Linux. 294 * Key-splitting and including an additional HKDF salt as part of 295 the nonce is sufficient for this requirement. 297 * Hashing the plaintext payload with the random nonce is an 298 acceptable strategy for mitigating random number generator 299 failures, but a secure random number generator SHOULD be used 300 even with this safeguard in place. 302 3. Non-deterministic, stateful, and otherwise dangerous signature 303 schemes (e.g. ECDSA without deterministic signatures as in 304 [RFC6979], XMSS) are forbidden from all PASETO protocols. 306 4. Public-key cryptography MUST be IND-CCA2 secure to be considered 307 for inclusion. 309 * This means that RSA with PKCS1v1.5 padding and unpadded RSA 310 MUST NOT ever be used in a PASETO protocol. 312 4. PASETO Protocol Version v1 314 Version *v1* is a compatibility mode composed of cryptographic 315 primitives likely available on legacy systems. *v1* SHOULD NOT be 316 used when all systems are able to use *v2*. *v1* MAY be used when 317 compatibility requirements include systems unable to use 318 cryptographic primitives from *v2*. 320 *v1* messages MUST use a *purpose* value of either *local* or 321 *public*. 323 4.1. v1.local 325 *v1.local* messages SHALL be encrypted and authenticated with *AES- 326 256-CTR* (AES-CTR from [RFC3686] with a 256-bit key) and *HMAC-SHA- 327 384* ([RFC4231]), using an *Encrypt-then-MAC* construction. 329 Encryption and authentication keys are split from the original key 330 and half the nonce, facilitated by HKDF [RFC5869] using SHA384. 332 Refer to the operations defined in *v1.Encrypt* and *v1.Decrypt* for 333 a formal definition. 335 4.2. v1.public 337 *v1.public* messages SHALL be signed using RSASSA-PSS as defined in 338 [RFC8017], with 2048-bit private keys. These messages provide 339 authentication but do not prevent the contents from being read, 340 including by those without either the *public key* or the *private 341 key*. Refer to the operations defined in *v1.Sign* and *v1.Verify* 342 for a formal definition. 344 4.3. Version v1 Algorithms 346 4.3.1. v1.GetNonce 348 Given a message ("m") and a nonce ("n"): 350 1. Calculate HMAC-SHA384 of the message "m" with "n" as the key. 352 2. Return the leftmost 32 bytes of step 1. 354 4.3.2. v1.Encrypt 356 Given a message "m", key "k", and optional footer "f" (which defaults 357 to empty string): 359 1. Set header "h" to "v1.local." 361 2. Generate 32 random bytes from the OS's CSPRNG. 363 3. Calculate "GetNonce()" of "m" and the output of step 2 to get the 364 nonce, "n". 366 * This step is to ensure that an RNG failure does not result in 367 a nonce-misuse condition that breaks the security of our 368 stream cipher. 370 4. Split the key ("k") into an Encryption key ("Ek") and an 371 Authentication key ("Ak"), using the leftmost 16 bytes of "n" as 372 the HKDF salt. (See below for pseudocode.) 374 * For encryption keys, the *info* parameter for HKDF MUST be set 375 to *paseto-encryption-key*. 377 * For authentication keys, the *info* parameter for HKDF MUST be 378 set to *paseto-auth-key-for-aead*. 380 * The output length MUST be 32 for both keys. 382 5. Encrypt the message using "AES-256-CTR", using "Ek" as the key 383 and the rightmost 16 bytes of "n" as the nonce. We'll call this 384 "c". (See below for pseudocode.) 386 6. Pack "h", "n", "c", and "f" together (in that order) using PAE 387 (see Section 2.2). We'll call this "preAuth". 389 7. Calculate HMAC-SHA-384 of the output of "preAuth", using "Ak" as 390 the authentication key. We'll call this "t". 392 8. If "f" is: 394 * Empty: return h || b64(n || c || t) 396 * Non-empty: return h || b64(n || c || t) || "." || b64(f) 398 * ...where || means "concatenate" 400 Example code: 402 Ek = hkdf_sha384( 403 len = 32 404 ikm = k, 405 info = "paseto-encryption-key", 406 salt = n[0:16] 407 ); 408 Ak = hkdf_sha384( 409 len = 32 410 ikm = k, 411 info = "paseto-auth-key-for-aead", 412 salt = n[0:16] 413 ); 415 Step 4: Key splitting with HKDF-SHA384 as per . 417 c = aes256ctr_encrypt( 418 plaintext = m, 419 nonce = n[16:] 420 key = Ek 421 ); 423 Step 5: PASETO v1 encryption (calculating c) 425 4.3.3. v1.Decrypt 427 Given a message "m", key "k", and optional footer "f" (which defaults 428 to empty string): 430 1. If "f" is not empty, implementations MAY verify that the value 431 appended to the token matches some expected string "f", provided 432 they do so using a constant-time string compare function. 434 2. Verify that the message begins with "v1.local.", otherwise throw 435 an exception. This constant will be referred to as "h". 437 3. Decode the payload ("m" sans "h", "f", and the optional trailing 438 period between "m" and "f") from b64 to raw binary. Set: 440 * "n" to the leftmost 32 bytes 442 * "t" to the rightmost 48 bytes 444 * "c" to the middle remainder of the payload, excluding "n" and 445 "t" 447 4. Split the key ("k") into an Encryption key ("Ek") and an 448 Authentication key ("Ak"), using the leftmost 16 bytes of "n" as 449 the HKDF salt. (See below for pseudocode.) 451 * For encryption keys, the *info* parameter for HKDF MUST be set 452 to *paseto-encryption-key*. 454 * For authentication keys, the *info* parameter for HKDF MUST be 455 set to *paseto-auth-key-for-aead*. 457 * The output length MUST be 32 for both keys. 459 5. Pack "h", "n", "c", and "f" together (in that order) using PAE 460 (see Section 2.2). We'll call this "preAuth". 462 6. Recalculate HMAC-SHA-384 of "preAuth" using "Ak" as the key. 463 We'll call this "t2". 465 7. Compare "t" with "t2" using a constant-time string compare 466 function. If they are not identical, throw an exception. 468 8. Decrypt "c" using "AES-256-CTR", using "Ek" as the key and the 469 rightmost 16 bytes of "n" as the nonce, and return this value. 471 Example code: 473 Ek = hkdf_sha384( 474 len = 32 475 ikm = k, 476 info = "paseto-encryption-key", 477 salt = n[0:16] 478 ); 479 Ak = hkdf_sha384( 480 len = 32 481 ikm = k, 482 info = "paseto-auth-key-for-aead", 483 salt = n[0:16] 484 ); 486 Step 4: Key splitting with HKDF-SHA384 as per . 488 return aes256ctr_decrypt( 489 cipherext = c, 490 nonce = n[16:] 491 key = Ek 492 ); 494 Step 8: PASETO v1 decryption 496 4.3.4. v1.Sign 498 Given a message "m", 2048-bit RSA secret key "sk", and optional 499 footer "f" (which defaults to empty string): 501 1. Set "h" to "v1.public." 503 2. Pack "h", "m", and "f" together (in that order) using PAE (see 504 Section 2.2). We'll call this "m2". 506 3. Sign "m2" using RSA with the private key "sk". We'll call this 507 "sig". The padding mode MUST be RSASSA-PSS [RFC8017]; PKCS1v1.5 508 is explicitly forbidden. The public exponent "e" MUST be 65537. 509 The mask generating function MUST be MGF1+SHA384. The hash 510 function MUST be SHA384. (See below for pseudocode.) 512 4. If "f" is: 514 * Empty: return h || b64(m || sig) 516 * Non-empty: return h || b64(m || sig) || "." || b64(f) 518 * ...where || means "concatenate" 519 sig = crypto_sign_rsa( 520 message = m2, 521 private_key = sk, 522 padding_mode = "pss", 523 public_exponent = 65537, 524 hash = "sha384" 525 mgf = "mgf1+sha384" 526 ); 528 Pseudocode: RSA signature algorithm used in PASETO v1 530 4.3.5. v1.Verify 532 Given a signed message "sm", RSA public key "pk", and optional footer 533 "f" (which defaults to empty string): 535 1. If "f" is not empty, implementations MAY verify that the value 536 appended to the token matches some expected string "f", provided 537 they do so using a constant-time string compare function. 539 2. Verify that the message begins with "v1.public.", otherwise throw 540 an exception. This constant will be referred to as "h". 542 3. Decode the payload ("sm" sans "h", "f", and the optional trailing 543 period between "m" and "f") from b64 to raw binary. Set: 545 * "s" to the rightmost 256 bytes 547 * "m" to the leftmost remainder of the payload, excluding "s" 549 4. Pack "h", "m", and "f" together (in that order) using PAE (see 550 Section 2.2). We'll call this "m2". 552 5. Use RSA to verify that the signature is valid for the message. 553 The padding mode MUST be RSASSA-PSS [RFC8017]; PKCS1v1.5 is 554 explicitly forbidden. The public exponent "e" MUST be 65537. 555 The mask generating function MUST be MGF1+SHA384. The hash 556 function MUST be SHA384. (See below for pseudocode.) 558 6. If the signature is valid, return "m". Otherwise, throw an 559 exception. 561 valid = crypto_sign_rsa_verify( 562 signature = s, 563 message = m2, 564 public_key = pk, 565 padding_mode = "pss", 566 public_exponent = 65537, 567 hash = "sha384" 568 mgf = "mgf1+sha384" 569 ); 571 Pseudocode: RSA signature validation for PASETO v1 573 5. PASETO Protocol Version v2 575 Version *v2* is the RECOMMENDED protocol version. *v2* SHOULD be used 576 in preference to *v1*. Applications using PASETO SHOULD only support 577 *v2* messages, but MAY support *v1* messages if the cryptographic 578 primitives used in *v2* are not available on all machines. 580 *v2* messages MUST use a *purpose* value of either *local* or 581 *public*. 583 5.1. v2.local 585 *v2.local* messages MUST be encrypted with XChaCha20-Poly1305, a 586 variant of ChaCha20-Poly1305 [RFC7539] defined in Section 7. Refer 587 to the operations defined in *v2.Encrypt* and *v2.Decrypt* for a 588 formal definition. 590 5.2. v2.public 592 *v2.public* messages MUST be signed using Ed25519 [RFC8032] public 593 key signatures. These messages provide authentication but do not 594 prevent the contents from being read, including by those without 595 either the *public key* or the *private key*. Refer to the operations 596 defined in *v2.Sign* and *v2.Verify* for a formal definition. 598 5.3. Version v2 Algorithms 600 5.3.1. v2.Encrypt 602 Given a message "m", key "k", and optional footer "f". 604 1. Set header "h" to "v2.local." 606 2. Generate 24 random bytes from the OS's CSPRNG. 608 3. Calculate BLAKE2b of the message "m" with the output of step 2 as 609 the key, with an output length of 24. This will be our nonce, 610 "n". 612 * This step is to ensure that an RNG failure does not result in 613 a nonce-misuse condition that breaks the security of our 614 stream cipher. 616 4. Pack "h", "n", and "f" together (in that order) using PAE (see 617 Section 2.2). We'll call this "preAuth". 619 5. Encrypt the message using XChaCha20-Poly1305, using an AEAD 620 interface such as the one provided in libsodium. (See below for 621 pseudocode.) 623 6. If "f" is: 625 * Empty: return h || b64(n || c) 627 * Non-empty: return h || b64(n || c) || "." || base64url(f) 629 * ...where || means "concatenate" 631 c = crypto_aead_xchacha20poly1305_encrypt( 632 message = m 633 aad = preAuth 634 nonce = n 635 key = k 636 ); 638 Step 5: PASETO v2 encryption (calculating c) 640 5.3.2. v2.Decrypt 642 Given a message "m", key "k", and optional footer "f". 644 1. If "f" is not empty, implementations MAY verify that the value 645 appended to the token matches some expected string "f", provided 646 they do so using a constant-time string compare function. 648 2. Verify that the message begins with "v2.local.", otherwise throw 649 an exception. This constant will be referred to as "h". 651 3. Decode the payload ("m" sans "h", "f", and the optional trailing 652 period between "m" and "f") from base64url to raw binary. Set: 654 * "n" to the leftmost 24 bytes 655 * "c" to the middle remainder of the payload, excluding "n". 657 4. Pack "h", "n", and "f" together (in that order) using PAE (see 658 Section 2.2). We'll call this "preAuth" 660 5. Decrypt "c" using "XChaCha20-Poly1305", store the result in "p". 661 (See below for pseudocode.) 663 6. If decryption failed, throw an exception. Otherwise, return "p". 665 p = crypto_aead_xchacha20poly1305_decrypt( 666 ciphertext = c 667 aad = preAuth 668 nonce = n 669 key = k 670 ); 672 Step 8: PASETO v2 decryption 674 5.3.3. v2.Sign 676 Given a message "m", Ed25519 secret key "sk", and optional footer "f" 677 (which defaults to empty string): 679 1. Set "h" to "v2.public." 681 2. Pack "h", "m", and "f" together (in that order) using PAE (see 682 Section 2.2). We'll call this "m2". 684 3. Sign "m2" using Ed25519 "sk". We'll call this "sig". (See below 685 for pseudocode.) 687 4. If "f" is: 689 * Empty: return h || b64(m || sig) 691 * Non-empty: return h || b64(m || sig) || "." || b64(f) 693 * ...where || means "concatenate" 695 sig = crypto_sign_detached( 696 message = m2, 697 private_key = sk 698 ); 700 Step 3: Generating an Ed25519 with libsodium 702 5.3.4. v2.Verify 704 Given a signed message "sm", public key "pk", and optional footer "f" 705 (which defaults to empty string): 707 1. If "f" is not empty, implementations MAY verify that the value 708 appended to the token matches some expected string "f", provided 709 they do so using a constant-time string compare function. 711 2. Verify that the message begins with "v2.public.", otherwise throw 712 an exception. This constant will be referred to as "h". 714 3. Decode the payload ("sm" sans "h", "f", and the optional trailing 715 period between "m" and "f") from base64url to raw binary. Set: 717 * "s" to the rightmost 64 bytes 719 * "m" to the leftmost remainder of the payload, excluding "s" 721 4. Pack "h", "m", and "f" together (in that order) using PAE (see 722 Section 2.2). We'll call this "m2". 724 5. Use Ed25519 to verify that the signature is valid for the 725 message: (See below for pseudocode.) 727 6. If the signature is valid, return "m". Otherwise, throw an 728 exception. 730 valid = crypto_sign_verify_detached( 731 signature = s, 732 message = m2, 733 public_key = pk 734 ); 736 Step 5: Validating the Ed25519 signature using libsodium. 738 6. Payload Processing 740 All PASETO payloads MUST be a JSON object [RFC8259]. 742 If non-UTF-8 character sets are desired for some fields, implementors 743 are encouraged to use Base64url [1] encoding to preserve the original 744 intended binary data, but still use UTF-8 for the actual payloads. 746 6.1. Registered Claims 748 The following keys are reserved for use within PASETO. Users SHOULD 749 NOT write arbitrary/invalid data to any keys in a top-level PASETO in 750 the list below: 752 +-----+------------+--------+-------------------------------------+ 753 | Key | Name | Type | Example | 754 +-----+------------+--------+-------------------------------------+ 755 | iss | Issuer | string | {"iss":"paragonie.com"} | 756 | sub | Subject | string | {"sub":"test"} | 757 | aud | Audience | string | {"aud":"pie-hosted.com"} | 758 | exp | Expiration | DtTime | {"exp":"2039-01-01T00:00:00+00:00"} | 759 | nbf | Not Before | DtTime | {"nbf":"2038-04-01T00:00:00+00:00"} | 760 | iat | Issued At | DtTime | {"iat":"2038-03-17T00:00:00+00:00"} | 761 | jti | Token ID | string | {"jti":"87IFSGFgPNtQNNuw0AtuLttP"} | 762 | kid | Key-ID | string | {"kid":"stored-in-the-footer"} | 763 +-----+------------+--------+-------------------------------------+ 765 In the table above, DtTime means an ISO 8601 compliant DateTime 766 string. See [#keyid-support] for special rules about "kid" claims. 768 Any other claims can be freely used. These keys are only reserved in 769 the top-level JSON object. 771 The keys in the above table are case-sensitive. 773 Implementors (i.e. library designers) SHOULD provide some means to 774 discourage setting invalid/arbitrary data to these reserved claims. 776 For example: Storing any string that isn't a valid ISO 8601 DateTime 777 in the "exp" claim should result in an exception or error state 778 (depending on the programming language in question). 780 6.1.1. Key-ID Support 782 Some systems need to support key rotation, but since the payloads of 783 a _local_ token are always encrypted, it is impractical to store the 784 key id in the payload. 786 Instead, users should store Key-ID claims (_kid_) in the unencrypted 787 footer. 789 For example, a footer of {"kid":"gandalf0"} can be read without 790 needing to first decrypt the token (which would in turn allow the 791 user to know which key to use to decrypt the token). 793 Implementations SHOULD provide a means to extract the footer from a 794 PASETO before authentication and decryption. This is possible for 795 _local_ tokens because the contents of the footer are _not_ 796 encrypted. However, the authenticity of the footer is only assured 797 after the authentication tag is verified. 799 While a key identifier can generally be safely used for selecting the 800 cryptographic key used to decrypt and/or verify payloads before 801 verification, provided that the _kid_ is a public number that is 802 associated with a particular key which is not supplied by attackers, 803 any other fields stored in the footer MUST be distrusted until the 804 payload has been verified. 806 IMPORTANT: Key identifiers MUST be independent of the actual keys 807 used by PASETO. 809 A fingerprint of the key is allowed as long as it is impractical for 810 an attacker to recover the key from said fingerprint. 812 For example, the user MUST NOT store the public key in the footer for 813 a *public* token and have the recipient use the provided public key. 814 Doing so would allow an attacker to replace the public key with one 815 of their own choosing, which will cause the recipient to accept any 816 signature for any message as valid, therefore defeating the security 817 goals of public-key cryptography. 819 Instead, it's recommended that implementors and users use a unique 820 identifier for each key (independent of the cryptographic key's 821 contents) that is used in a database or other key-value store to 822 select the appropriate cryptographic key. These search operations 823 MUST fail closed if no valid key is found for the given key 824 identifier. 826 7. AEAD_XChaCha20_Poly1305 828 XChaCha20-Poly1305 is a variant of the ChaCha20-Poly1305 AEAD 829 construction as defined in [RFC7539] that uses a 192-bit nonce 830 instead of a 64-bit nonce. 832 The algorithm for XChaCha20-Poly1305 is as follows: 834 1. Calculate a subkey from the first 16 bytes of the nonce and the 835 key, using HChaCha20 (Section 7.2). 837 2. Use the subkey and remaining 8 bytes of the nonce (prefixed with 838 4 NUL bytes) with AEAD_CHACHA20_POLY1305 from [RFC7539] as 839 normal. 841 XChaCha20-Poly1305 implementations already exist in libsodium [2], 842 Monocypher [3], xsecretbox [4], and a standalone Go [5] library. 844 7.1. Motivation for XChaCha20-Poly1305 846 As long as ChaCha20-Poly1305 is a secure AEAD cipher and ChaCha is a 847 secure pseudorandom function (PRF), XChaCha20-Poly1305 is secure. 849 The nonce used by the original ChaCha20-Poly1305 is too short to 850 safely use with random strings for long-lived keys. 852 With XChaCha20-Poly1305, users can safely generate a random 192-bit 853 nonce for each message and not worry about nonce-reuse 854 vulnerabilities. 856 7.2. HChaCha20 858 *HChaCha20* is an intermediary step towards XChaCha20 based on the 859 construction and security proof used to create XSalsa20 [6], an 860 extended-nonce Salsa20 variant used in NaCl [7]. 862 HChaCha20 is initialized the same way as the ChaCha cipher, except 863 that HChaCha20 uses a 128-bit nonce and has no counter. 865 Consider the two figures below, where each non-whitespace character 866 represents one nibble of information about the ChaCha states (all 867 numbers little-endian): 869 cccccccc cccccccc cccccccc cccccccc 870 kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk 871 kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk 872 bbbbbbbb nnnnnnnn nnnnnnnn nnnnnnnn 874 ChaCha20 State: c=constant k=key b=blockcount n=nonce 876 cccccccc cccccccc cccccccc cccccccc 877 kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk 878 kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk 879 nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn 881 HChaCha20 State: c=constant k=key n=nonce 883 After initialization, proceed through the ChaCha rounds as usual. 885 Once the 20 ChaCha rounds have been completed, the first 128 bits and 886 last 128 bits of the keystream (both little-endian) are concatenated, 887 and this 256-bit subkey is returned. 889 7.2.1. Test Vector for the HChaCha20 Block Function 891 o Key = 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13: 892 14:15:16:17:18:19:1a:1b:1c:1d:1e:1f. The key is a sequence of 893 octets with no particular structure before we copy it into the 894 HChaCha state. 896 o Nonce = (00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27) 898 After setting up the HChaCha state, it looks like this: 900 61707865 3320646e 79622d32 6b206574 901 03020100 07060504 0b0a0908 0f0e0d0c 902 13121110 17161514 1b1a1918 1f1e1d1c 903 09000000 4a000000 00000000 27594131 905 ChaCha state with the key setup. 907 After running 20 rounds (10 column rounds interleaved with 10 908 "diagonal rounds"), the HChaCha state looks like this: 910 82413b42 27b27bfe d30e4250 8a877d73 911 4864a70a f3cd5479 37cd6a84 ad583c7b 912 8355e377 127ce783 2d6a07e0 e5d06cbc 913 a0f9e4d5 8a74a853 c12ec413 26d3ecdc 915 HChaCha state after 20 rounds 917 HChaCha20 will then return only the first and last rows, resulting in 918 the following 256-bit key: 920 82413b4 227b27bfe d30e4250 8a877d73 921 a0f9e4d 58a74a853 c12ec413 26d3ecdc 923 Resultant HChaCha20 subkey 925 8. Intended Use-Cases for PASETO 927 Like JWTs, PASETOs are intended to be single-use tokens, as there is 928 no built-in mechanism to prevent replay attacks within the token 929 lifetime. 931 o *local* tokens are intended for tamper-resistant encrypted cookies 932 or HTTP request parameters. A resonable example would be long- 933 term authentication cookies which re-establish a new session 934 cookie if a user checked the "remember me on this computer" box 935 when authenticating. To accomplish this, the server would look 936 use the "jti" claim in a database lookup to find the appropriate 937 user to associate this session with. After each new browsing 938 session, the "jti" would be rotated in the database and a fresh 939 cookie would be stored in tbe browser. 941 o *public* tokens are intended for one-time authentication claims 942 from a third party. For example, *public* PASETO would be 943 suitable for a protocol like OpenID Connect. 945 9. Security Considerations 947 PASETO was designed in part to address known deficits of the JOSE 948 standards that lead to insecure implementations. 950 PASETO uses versioned protocols, rather than runtime ciphersuite 951 negotiation, to prevent insecure algorithms from being selected. 952 Mix-and-match is not a robust strategy for usable security 953 engineering, especially when implementations have insecure default 954 settings. 956 If a severe security vulnerability is ever discovered in one of the 957 specified versions, a new version of the protocol that is not 958 affected should be decided by a team of cryptography engineers 959 familiar with the vulnerability in question. This prevents users 960 from having to rewrite and/or reconfigure their implementations to 961 side-step the vulnerability. 963 PASETO implementors should only support the two most recent protocol 964 versions (currently *v1* and *v2*) at any given time. 966 PASETO users should beware that, although footers are authenticated, 967 they are never encrypted. Therefore, sensitive information MUST NOT 968 be stored in a footer. 970 Furthermore, PASETO users should beware that, if footers are employed 971 to implement Key Identification (*kid*), the values stored in the 972 footer MUST be unrelated to the actual cryptographic key used in 973 verifying the token as discussed in Section 6.1.1. 975 PASETO has no built-in mechanism to resist replay attacks within the 976 token's lifetime. Users SHOULD NOT attempt to use PASETO to obviate 977 the need for server-side data storage when designing web 978 applications. 980 PASETO's cryptography features requires the availability of a secure 981 random number generator, such as the getrandom(2) syscall on newer 982 Linux distributions, /dev/urandom on most Unix-like systems, and 983 CryptGenRandom on Windows computers. 985 The use of userspace pseudo-random number generators, even if seeded 986 by the operating system's cryptographically secure pseudo-random 987 number generator, is discouraged. 989 10. IANA Considerations 991 The IANA should reserve a new "PASETO Headers" registry for the 992 purpose of this document and superseding RFCs. 994 This document defines a suite of string prefixes for PASETO tokens, 995 called "PASETO Headers" (see Section 2), which consists of two parts: 997 o *version*, with values *v1*, *v2* defined above 999 o *purpose*, with the values of *local* or *public* 1001 These two values are concatenated with a single character separator, 1002 the ASCII period character *.*. 1004 Initial values for the "PASETO Headers" registry are given below; 1005 future assignments are to be made through Expert Review [RFC8126], 1006 such as the CFRG [8]. 1008 +-----------+-----------------------+-------------+ 1009 | Value | PASETO Header Meaning | Definition | 1010 +-----------+-----------------------+-------------+ 1011 | v1.local | Version 1, local | Section 4.1 | 1012 | v1.public | Version 1, public | Section 4.2 | 1013 | v2.local | Version 2, local | Section 5.1 | 1014 | v2.public | Version 2, public | Section 5.2 | 1015 +-----------+-----------------------+-------------+ 1017 PASETO Headers and their respective meanings 1019 11. References 1021 11.1. Normative References 1023 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1024 Requirement Levels", BCP 14, RFC 2119, 1025 DOI 10.17487/RFC2119, March 1997, . 1028 [RFC3686] Housley, R., "Using Advanced Encryption Standard (AES) 1029 Counter Mode With IPsec Encapsulating Security Payload 1030 (ESP)", RFC 3686, DOI 10.17487/RFC3686, January 2004, 1031 . 1033 [RFC4231] Nystrom, M., "Identifiers and Test Vectors for HMAC-SHA- 1034 224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512", 1035 RFC 4231, DOI 10.17487/RFC4231, December 2005, 1036 . 1038 [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 1039 Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, 1040 . 1042 [RFC5869] Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand 1043 Key Derivation Function (HKDF)", RFC 5869, 1044 DOI 10.17487/RFC5869, May 2010, . 1047 [RFC6979] Pornin, T., "Deterministic Usage of the Digital Signature 1048 Algorithm (DSA) and Elliptic Curve Digital Signature 1049 Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979, August 1050 2013, . 1052 [RFC7516] Jones, M. and J. Hildebrand, "JSON Web Encryption (JWE)", 1053 RFC 7516, DOI 10.17487/RFC7516, May 2015, 1054 . 1056 [RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517, 1057 DOI 10.17487/RFC7517, May 2015, . 1060 [RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, 1061 DOI 10.17487/RFC7518, May 2015, . 1064 [RFC7519] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token 1065 (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015, 1066 . 1068 [RFC7539] Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF 1069 Protocols", RFC 7539, DOI 10.17487/RFC7539, May 2015, 1070 . 1072 [RFC8017] Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, 1073 "PKCS #1: RSA Cryptography Specifications Version 2.2", 1074 RFC 8017, DOI 10.17487/RFC8017, November 2016, 1075 . 1077 [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital 1078 Signature Algorithm (EdDSA)", RFC 8032, 1079 DOI 10.17487/RFC8032, January 2017, . 1082 [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for 1083 Writing an IANA Considerations Section in RFCs", BCP 26, 1084 RFC 8126, DOI 10.17487/RFC8126, June 2017, 1085 . 1087 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 1088 Interchange Format", STD 90, RFC 8259, 1089 DOI 10.17487/RFC8259, December 2017, . 1092 11.2. URIs 1094 [1] https://tools.ietf.org/html/rfc4648#page-7 1096 [2] https://download.libsodium.org/doc/secret-key_cryptography/ 1097 xchacha20-poly1305_construction.html 1099 [3] https://github.com/LoupVaillant/Monocypher 1101 [4] https://github.com/jedisct1/xsecretbox 1103 [5] https://github.com/aead/chacha20 1105 [6] https://cr.yp.to/snuffle/xsalsa-20110204.pdf 1107 [7] https://nacl.cr.yp.to 1109 [8] https://irtf.org/cfrg 1111 Appendix A. PASETO Test Vectors 1113 Note: When a nonce is given below, it refers to the value before 1114 being hashed with the message. Typically this value is provided by a 1115 secure random number generator. 1117 Note: Signing may result in a different token each time, but the 1118 given token and public key pair should validate successfully. The 1119 private key that corresponds to this public key is as follows: 1121 -----BEGIN RSA PRIVATE KEY----- 1122 MIIEowIBAAKCAQEAyaTgTt53ph3p5GHgwoGWwz5hRfWXSQA08NCOwe0FEgALWos9 1123 GCjNFCd723nCHxBtN1qd74MSh/uN88JPIbwxKheDp4kxo4YMN5trPaF0e9G6Bj1N 1124 02HnanxFLW+gmLbgYO/SZYfWF/M8yLBcu5Y1Ot0ZxDDDXS9wIQTtBE0ne3YbxgZJ 1125 AZTU5XqyQ1DxdzYyC5lF6yBaR5UQtCYTnXAApVRuUI2Sd6L1E2vl9bSBumZ5IpNx 1126 kRnAwIMjeTJB/0AIELh0mE5vwdihOCbdV6alUyhKC1+1w/FW6HWcp/JG1kKC8DPI 1127 idZ78Bbqv9YFzkAbNni5eSBOsXVBKG78Zsc8owIDAQABAoIBAF22jLDa34yKdns3 1128 qfd7to+C3D5hRzAcMn6Azvf9qc+VybEI6RnjTHxDZWK5EajSP4/sQ15e8ivUk0Jo 1129 WdJ53feL+hnQvwsab28gghSghrxM2kGwGA1XgO+SVawqJt8SjvE+Q+//01ZKK0Oy 1130 A0cDJjX3L9RoPUN/moMeAPFw0hqkFEhm72GSVCEY1eY+cOXmL3icxnsnlUD//SS9 1131 q33RxF2y5oiW1edqcRqhW/7L1yYMbxHFUcxWh8WUwjn1AAhoCOUzF8ZB+0X/PPh+ 1132 1nYoq6xwqL0ZKDwrQ8SDhW/rNDLeO9gic5rl7EetRQRbFvsZ40AdsX2wU+lWFUkB 1133 42AjuoECgYEA5z/CXqDFfZ8MXCPAOeui8y5HNDtu30aR+HOXsBDnRI8huXsGND04 1134 FfmXR7nkghr08fFVDmE4PeKUk810YJb+IAJo8wrOZ0682n6yEMO58omqKin+iIUV 1135 rPXLSLo5CChrqw2J4vgzolzPw3N5I8FJdLomb9FkrV84H+IviPIylyECgYEA3znw 1136 AG29QX6ATEfFpGVOcogorHCntd4niaWCq5ne5sFL+EwLeVc1zD9yj1axcDelICDZ 1137 xCZynU7kDnrQcFkT0bjH/gC8Jk3v7XT9l1UDDqC1b7rm/X5wFIZ/rmNa1rVZhL1o 1138 /tKx5tvM2syJ1q95v7NdygFIEIW+qbIKbc6Wz0MCgYBsUZdQD+qx/xAhELX364I2 1139 epTryHMUrs+tGygQVrqdiJX5dcDgM1TUJkdQV6jLsKjPs4Vt6OgZRMrnuLMsk02R 1140 3M8gGQ25ok4f4nyyEZxGGWnVujn55KzUiYWhGWmhgp18UCkoYa59/Q9ss+gocV9h 1141 B9j9Q43vD80QUjiF4z0DQQKBgC7XQX1VibkMim93QAnXGDcAS0ij+w02qKVBjcHk 1142 b9mMBhz8GAxGOIu7ZJafYmxhwMyVGB0I1FQeEczYCJUKnBYN6Clsjg6bnBT/z5bJ 1143 x/Jx1qCzX3Uh6vLjpjc5sf4L39Tyye1u2NXQmZPwB5x9BdcsFConSq/s4K1LJtUT 1144 3KFxAoGBANGcQ8nObi3m4wROyKrkCWcWxFFMnpwxv0pW727Hn9wuaOs4UbesCnwm 1145 pcMTfzGUDuzYXCtAq2pJl64HG6wsdkWmjBTJEpm6b9ibOBN3qFV2zQ0HyyKlMWxI 1146 uVSj9gOo61hF7UH9XB6R4HRdlpBOuIbgAWZ46dkj9/HM9ovdP0Iy 1147 -----END RSA PRIVATE KEY----- 1149 A.1. PASETO v1 Test Vectors 1151 A.1.1. v1.local (Shared-Key Encryption) Test Vectors 1153 A.1.1.1. Test Vector v1-E-1 1155 Key: 70717273 74757677 78797a7b 7c7d7e7f 1156 80818283 84858687 88898a8b 8c8d8e8f 1157 Nonce: 00000000 00000000 00000000 00000000 1158 00000000 00000000 00000000 00000000 1159 Payload: {"data":"this is a signed message", 1160 "exp":"2019-01-01T00:00:00+00:00"} 1161 Footer: 1162 Token: v1.local.WzhIh1MpbqVNXNt7-HbWvL-JwAym3Tomad9Pc2nl7wK87vGraUV 1163 vn2bs8BBNo7jbukCNrkVID0jCK2vr5bP18G78j1bOTbBcP9HZzqnraEdspcj 1164 d_PvrxDEhj9cS2MG5fmxtvuoHRp3M24HvxTtql9z26KTfPWxJN5bAJaAM6go 1165 s8fnfjJO8oKiqQMaiBP_Cqncmqw8 1167 A.1.1.2. Test Vector v1-E-2 1169 Same as v1-E-1, but with a slightly different message. 1171 Key: 70717273 74757677 78797a7b 7c7d7e7f 1172 80818283 84858687 88898a8b 8c8d8e8f 1173 Nonce: 00000000 00000000 00000000 00000000 1174 00000000 00000000 00000000 00000000 1175 Payload: {"data":"this is a secret message", 1176 "exp":"2019-01-01T00:00:00+00:00"} 1177 Footer: 1178 Token: v1.local.w_NOpjgte4bX-2i1JAiTQzHoGUVOgc2yqKqsnYGmaPaCu_KWUkR 1179 GlCRnOvZZxeH4HTykY7AE_jkzSXAYBkQ1QnwvKS16uTXNfnmp8IRknY76I2m 1180 3S5qsM8klxWQQKFDuQHl8xXV0MwAoeFh9X6vbwIqrLlof3s4PMjRDwKsxYzk 1181 Mr1RvfDI8emoPoW83q4Q60_xpHaw 1183 A.1.1.3. Test Vector v1-E-3 1185 Key: 70717273 74757677 78797a7b 7c7d7e7f 1186 80818283 84858687 88898a8b 8c8d8e8f 1187 Nonce: 26f75533 54482a1d 91d47846 27854b8d 1188 a6b8042a 7966523c 2b404e8d bbe7f7f2 1189 Payload: {"data":"this is a signed message", 1190 "exp":"2019-01-01T00:00:00+00:00"} 1191 Footer: 1192 Token: v1.local.4VyfcVcFAOAbB8yEM1j1Ob7Iez5VZJy5kHNsQxmlrAwKUbOtq9c 1193 v39T2fC0MDWafX0nQJ4grFZzTdroMvU772RW-X1oTtoFBjsl_3YYHWnwgqzs 1194 0aFc3ejjORmKP4KUM339W3syBYyjKIOeWnsFQB6Yef-1ov9rvqt7TmwONUHe 1195 JUYk4IK_JEdUeo_uFRqAIgHsiGCg 1197 A.1.1.4. Test Vector v1-E-4 1199 Same as v1-E-3, but with a slightly different message. 1201 Key: 70717273 74757677 78797a7b 7c7d7e7f 1202 80818283 84858687 88898a8b 8c8d8e8f 1203 Nonce: 26f75533 54482a1d 91d47846 27854b8d 1204 a6b8042a 7966523c 2b404e8d bbe7f7f2 1205 Payload: {"data":"this is a secret message", 1206 "exp":"2019-01-01T00:00:00+00:00"} 1207 Footer: 1208 Token: v1.local.IddlRQmpk6ojcD10z1EYdLexXvYiadtY0MrYQaRnq3dnqKIWcbb 1209 pOcgXdMIkm3_3gksirTj81bvWrWkQwcUHilt-tQo7LZK8I6HCK1V78B9YeEq 1210 GNeeWXOyWWHoJQIe0d5nTdvejdt2Srz_5Q0QG4oiz1gB_wmv4U5pifedaZbH 1211 XUTWXchFEi0etJ4u6tqgxZSklcec 1213 A.1.1.5. Test Vector v1-E-5 1215 Key: 70717273 74757677 78797a7b 7c7d7e7f 1216 80818283 84858687 88898a8b 8c8d8e8f 1217 Nonce: 26f75533 54482a1d 91d47846 27854b8d 1218 a6b8042a 7966523c 2b404e8d bbe7f7f2 1219 Payload: {"data":"this is a signed message", 1220 "exp":"2019-01-01T00:00:00+00:00"} 1221 Footer: {"kid":"UbkK8Y6iv4GZhFp6Tx3IWLWLfNXSEvJcdT3zdR65YZxo"} 1222 Token: v1.local.4VyfcVcFAOAbB8yEM1j1Ob7Iez5VZJy5kHNsQxmlrAwKUbOtq9c 1223 v39T2fC0MDWafX0nQJ4grFZzTdroMvU772RW-X1oTtoFBjsl_3YYHWnwgqzs 1224 0aFc3ejjOR mKP4KUM339W3szA28OabR192eRqiyspQ6xPM35NMR-04-FhRJ 1225 ZEWiF0W5oWjPVtGPjeVjm2DI4YtJg.eyJraWQiOiJVYmtLOFk2aXY0R1poRn 1226 A2VHgzSVdMV0xmTlhTRXZKY2RUM3pkUjY1WVp4byJ9 1228 A.1.1.6. Test Vector v1-E-6 1230 Same as v1-E-5, but with a slightly different message. 1232 Key: 70717273 74757677 78797a7b 7c7d7e7f 1233 80818283 84858687 88898a8b 8c8d8e8f 1234 Nonce: 26f75533 54482a1d 91d47846 27854b8d 1235 a6b8042a 7966523c 2b404e8d bbe7f7f2 1236 Payload: {"data":"this is a secret message", 1237 "exp":"2019-01-01T00:00:00+00:00"} 1238 Footer: {"kid":"UbkK8Y6iv4GZhFp6Tx3IWLWLfNXSEvJcdT3zdR65YZxo"} 1239 Token: v1.local.IddlRQmpk6ojcD10z1EYdLexXvYiadtY0MrYQaRnq3dnqKIWcbb 1240 pOcgXdMIkm3_3gksirTj81bvWrWkQwcUHilt-tQo7LZK8I6HCK1V78B9YeEq 1241 GNeeWXOyWWHoJQIe0d5nTdvcT2vnER6NrJ7xIowvFba6J4qMlFhBnYSxHEq9 1242 v9NlzcKsz1zscdjcAiXnEuCHyRSc.eyJraWQiOiJVYmtLOFk2aXY0R1poRnA 1243 2VHgzSVdMV0xmTlhTRXZKY2RUM3pkUjY1WVp4byJ9 1245 A.1.2. v1.public (Public-Key Authentication) Test Vectors 1247 A.1.2.1. Test Vector v1-S-1 1248 Token: v1.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiw 1249 iZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9cIZKahKeGM5k 1250 iAS_4D70Qbz9FIThZpxetJ6n6E6kXP_119SvQcnfCSfY_gG3D0Q2v7FEt 1251 m2Cmj04lE6YdgiZ0RwA41WuOjXq7zSnmmHK9xOSH6_2yVgt207h1_LphJ 1252 zVztmZzq05xxhZsV3nFPm2cCu8oPceWy-DBKjALuMZt_Xj6hWFFie96Sf 1253 Q6i85lOsTX8Kc6SQaG-3CgThrJJ6W9DC-YfQ3lZ4TJUoY3QNYdtEgAvp1 1254 QuWWK6xmIb8BwvkBPej5t88QUb7NcvZ15VyNw3qemQGn2ITSdpdDgwMtp 1255 flZOeYdtuxQr1DSGO2aQyZl7s0WYn1IjdQFx6VjSQ4yfw 1256 Public Key: -----BEGIN PUBLIC KEY----- 1257 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyaTgTt53ph3p 1258 5GHgwoGWwz5hRfWXSQA08NCOwe0FEgALWos9GCjNFCd723nCHxBtN1qd 1259 74MSh/uN88JPIbwxKheDp4kxo4YMN5trPaF0e9G6Bj1N02HnanxFLW+g 1260 mLbgYO/SZYfWF/M8yLBcu5Y1Ot0ZxDDDXS9wIQTtBE0ne3YbxgZJAZTU 1261 5XqyQ1DxdzYyC5lF6yBaR5UQtCYTnXAApVRuUI2Sd6L1E2vl9bSBumZ5 1262 IpNxkRnAwIMjeTJB/0AIELh0mE5vwdihOCbdV6alUyhKC1+1w/FW6HWc 1263 p/JG1kKC8DPIidZ78Bbqv9YFzkAbNni5eSBOsXVBKG78Zsc8owIDAQAB 1264 -----END PUBLIC KEY----- 1265 Payload: {"data":"this is a secret message", 1266 "exp":"2019-01-01T00:00:00+00:00"} 1267 Footer: 1269 A.1.2.2. Test Vector v1-S-2 1271 Token: v1.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiw 1272 iZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9sBTIb0J_4mis 1273 AuYc4-6P5iR1rQighzktpXhJ8gtrrp2MqSSDkbb8q5WZh3FhUYuW_rg2X 1274 8aflDlTWKAqJkM3otjYwtmfwfOhRyykxRL2AfmIika_A-_MaLp9F0iw4S 1275 1JetQQDV8GUHjosd87TZ20lT2JQLhxKjBNJSwWue8ucGhTgJcpOhXcthq 1276 az7a2yudGyd0layzeWziBhdQpoBR6ryTdtIQX54hP59k3XCIxuYbB9qJM 1277 pixiPAEKBcjHT74sA-uukug9VgKO7heWHwJL4Rl9ad21xyNwaxAnwAJ7C 1278 0fN5oGv8Rl0dF11b3tRmsmbDoIokIM0Dba29x_T3YzOyg.eyJraWQiOiJ 1279 kWWtJU3lseFFlZWNFY0hFTGZ6Rjg4VVpyd2JMb2xOaUNkcHpVSEd3OVVx 1280 biJ9 1281 Public Key: -----BEGIN PUBLIC KEY----- 1282 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyaTgTt53ph3p 1283 5GHgwoGWwz5hRfWXSQA08NCOwe0FEgALWos9GCjNFCd723nCHxBtN1qd 1284 74MSh/uN88JPIbwxKheDp4kxo4YMN5trPaF0e9G6Bj1N02HnanxFLW+g 1285 mLbgYO/SZYfWF/M8yLBcu5Y1Ot0ZxDDDXS9wIQTtBE0ne3YbxgZJAZTU 1286 5XqyQ1DxdzYyC5lF6yBaR5UQtCYTnXAApVRuUI2Sd6L1E2vl9bSBumZ5 1287 IpNxkRnAwIMjeTJB/0AIELh0mE5vwdihOCbdV6alUyhKC1+1w/FW6HWc 1288 p/JG1kKC8DPIidZ78Bbqv9YFzkAbNni5eSBOsXVBKG78Zsc8owIDAQAB 1289 -----END PUBLIC KEY----- 1290 Payload: {"data":"this is a secret message", 1291 "exp":"2019-01-01T00:00:00+00:00"} 1292 Footer: {"kid":"dYkISylxQeecEcHELfzF88UZrwbLolNiCdpzUHGw9Uqn"} 1294 A.2. PASETO v2 Test Vectors 1296 A.2.1. v2.local (Shared-Key Encryption) Test Vectors 1298 A.2.1.1. Test Vector v2-E-1 1300 Key: 70717273 74757677 78797a7b 7c7d7e7f 1301 80818283 84858687 88898a8b 8c8d8e8f 1302 Nonce: 00000000 00000000 00000000 00000000 1303 00000000 00000000 1304 Payload: {"data":"this is a signed message", 1305 "exp":"2019-01-01T00:00:00+00:00"} 1306 Footer: 1307 Token: v2.local.97TTOvgwIxNGvV80XKiGZg_kD3tsXM_-qB4dZGHOeN1cTkgQ4Pn 1308 W8888l802W8d9AvEGnoNBY3BnqHORy8a5cC8aKpbA0En8XELw2yDk2f1sVOD 1309 yfnDbi6rEGMY3pSfCbLWMM2oHJxvlEl2XbQ 1311 A.2.1.2. Test Vector v2-E-2 1313 Same as v2-E-1, but with a slightly different message. 1315 Key: 70717273 74757677 78797a7b 7c7d7e7f 1316 80818283 84858687 88898a8b 8c8d8e8f 1317 Nonce: 00000000 00000000 00000000 00000000 1318 00000000 00000000 1319 Payload: {"data":"this is a secret message", 1320 "exp":"2019-01-01T00:00:00+00:00"} 1321 Footer: 1322 Token: v2.local.CH50H-HM5tzdK4kOmQ8KbIvrzJfjYUGuu5Vy9ARSFHy9owVDMYg 1323 3-8rwtJZQjN9ABHb2njzFkvpr5cOYuRyt7CRXnHt42L5yZ7siD-4l-FoNsC7 1324 J2OlvLlIwlG06mzQVunrFNb7Z3_CHM0PK5w 1326 A.2.1.3. Test Vector v2-E-3 1328 Key: 70717273 74757677 78797a7b 7c7d7e7f 1329 80818283 84858687 88898a8b 8c8d8e8f 1330 Nonce: 45742c97 6d684ff8 4ebdc0de 59809a97 1331 cda2f64c 84fda19b 1332 Payload: {"data":"this is a signed message", 1333 "exp":"2019-01-01T00:00:00+00:00"} 1334 Footer: 1335 Token: v2.local.5K4SCXNhItIhyNuVIZcwrdtaDKiyF81-eWHScuE0idiVqCo72bb 1336 jo07W05mqQkhLZdVbxEa5I_u5sgVk1QLkcWEcOSlLHwNpCkvmGGlbCdNExn6 1337 Qclw3qTKIIl5-O5xRBN076fSDPo5xUCPpBA 1339 A.2.1.4. Test Vector v2-E-4 1341 Same as v2-E-3, but with a slightly different message. 1343 Key: 70717273 74757677 78797a7b 7c7d7e7f 1344 80818283 84858687 88898a8b 8c8d8e8f 1345 Nonce: 45742c97 6d684ff8 4ebdc0de 59809a97 1346 cda2f64c 84fda19b 1347 Payload: {"data":"this is a secret message", 1348 "exp":"2019-01-01T00:00:00+00:00"} 1349 Footer: 1350 Token: v2.local.pvFdDeNtXxknVPsbBCZF6MGedVhPm40SneExdClOxa9HNR8wFv7 1351 cu1cB0B4WxDdT6oUc2toyLR6jA6sc-EUM5ll1EkeY47yYk6q8m1RCpqTIzUr 1352 Iu3B6h232h62DPbIxtjGvNRAwsLK7LcV8oQ 1354 A.2.1.5. Test Vector v2-E-5 1356 Key: 70717273 74757677 78797a7b 7c7d7e7f 1357 80818283 84858687 88898a8b 8c8d8e8f 1358 Nonce: 45742c97 6d684ff8 4ebdc0de 59809a97 1359 cda2f64c 84fda19b 1360 Payload: {"data":"this is a signed message", 1361 "exp":"2019-01-01T00:00:00+00:00"} 1362 Footer: {"kid":"UbkK8Y6iv4GZhFp6Tx3IWLWLfNXSEvJcdT3zdR65YZxo"} 1363 Token: v2.local.5K4SCXNhItIhyNuVIZcwrdtaDKiyF81-eWHScuE0idiVqCo72bb 1364 jo07W05mqQkhLZdVbxEa5I_u5sgVk1QLkcWEcOSlLHwNpCkvmGGlbCdNExn6 1365 Qclw3qTKIIl5-zSLIrxZqOLwcFLYbVK1SrQ.eyJraWQiOiJ6VmhNaVBCUDlm 1366 UmYyc25FY1Q3Z0ZUaW9lQTlDT2NOeTlEZmdMMVc2MGhhTiJ9 1368 A.2.1.6. Test Vector v2-E-6 1370 Same as v2-E-5, but with a slightly different message. 1372 Key: 70717273 74757677 78797a7b 7c7d7e7f 1373 80818283 84858687 88898a8b 8c8d8e8f 1374 Nonce: 45742c97 6d684ff8 4ebdc0de 59809a97 1375 cda2f64c 84fda19b 1376 Payload: {"data":"this is a secret message", 1377 "exp":"2019-01-01T00:00:00+00:00"} 1378 Footer: {"kid":"UbkK8Y6iv4GZhFp6Tx3IWLWLfNXSEvJcdT3zdR65YZxo"} 1379 Token: v2.local.pvFdDeNtXxknVPsbBCZF6MGedVhPm40SneExdClOxa9HNR8wFv7 1380 cu1cB0B4WxDdT6oUc2toyLR6jA6sc-EUM5ll1EkeY47yYk6q8m1RCpqTIzUr 1381 Iu3B6h232h62DnMXKdHn_Smp6L_NfaEnZ-A.eyJraWQiOiJ6VmhNaVBCUDlm 1382 UmYyc25FY1Q3Z0ZUaW9lQTlDT2NOeTlEZmdMMVc2MGhhTiJ9 1384 A.2.2. v2.public (Public-Key Authentication) Test Vectors 1386 A.2.2.1. Test Vector v2-S-1 1388 Token: v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIi 1389 wiZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9HQr8URrGnt 1390 Tu7Dz9J2IF23d1M7-9lH9xiqdGyJNvzp4angPW5Esc7C5huy_M8I8_Dj 1391 JK2ZXC2SUYuOFM-Q_5Cw 1392 Private Key: b4cbfb43 df4ce210 727d953e 4a713307 1393 fa19bb7d 9f850414 38d9e11b 942a3774 1394 1eb9dbbb bc047c03 fd70604e 0071f098 1395 7e16b28b 757225c1 1f00415d 0e20b1a2 1396 Public Key: 1eb9dbbb bc047c03 fd70604e 0071f098 1397 7e16b28b 757225c1 1f00415d 0e20b1a2 1398 Payload: {"data":"this is a signed message", 1399 "exp":"2019-01-01T00:00:00+00:00"} 1400 Footer: 1402 A.2.2.2. Test Vector v2-S-2 1404 Token: v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIi 1405 wiZXhwIjoiMjAxOS0wMS0wMVQwMDowMDowMCswMDowMCJ9flsZsx_gYC 1406 R0N_Ec2QxJFFpvQAs7h9HtKwbVK2n1MJ3Rz-hwe8KUqjnd8FAnIJZ601 1407 tp7lGkguU63oGbomhoBw.eyJraWQiOiJ6VmhNaVBCUDlmUmYyc25FY1Q 1408 3Z0ZUaW9lQTlDT2NOeTlEZmdMMVc2MGhhTiJ9 1409 Private Key: b4cbfb43 df4ce210 727d953e 4a713307 1410 fa19bb7d 9f850414 38d9e11b 942a3774 1411 1eb9dbbb bc047c03 fd70604e 0071f098 1412 7e16b28b 757225c1 1f00415d 0e20b1a2 1413 Public Key: 1eb9dbbb bc047c03 fd70604e 0071f098 1414 7e16b28b 757225c1 1f00415d 0e20b1a2 1415 Payload: {"data":"this is a signed message", 1416 "exp":"2019-01-01T00:00:00+00:00"} 1417 Footer: {"kid":"dYkISylxQeecEcHELfzF88UZrwbLolNiCdpzUHGw9Uqn"} 1419 Authors' Addresses 1421 Scott Arciszewski 1422 Paragon Initiative Enterprises 1423 United States 1425 Email: security@paragonie.com 1426 Steven Haussmann 1427 Rensselaer Polytechnic Institute 1428 United States 1430 Email: hausss@rpi.edu