idnits 2.17.1 draft-rundgren-json-canonicalization-scheme-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 : ---------------------------------------------------------------------------- ** The abstract seems to contain references ([RFC8259], [ES6]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (May 18, 2018) is 2169 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) == Missing Reference: 'RFC4648' is mentioned on line 398, but not defined == Missing Reference: 'RFC7515' is mentioned on line 402, but not defined == Missing Reference: 'XMLDSIG' is mentioned on line 413, but not defined == Missing Reference: 'NODEJS' is mentioned on line 391, but not defined == Missing Reference: 'OPENKEY' is mentioned on line 395, but not defined == Missing Reference: 'RFC7638' is mentioned on line 406, but not defined == Missing Reference: 'KEYBASE' is mentioned on line 388, but not defined -- Looks like a reference, but probably isn't: '1' on line 418 == Missing Reference: 'V8' is mentioned on line 410, but not defined == Missing Reference: 'OPENAPI' is mentioned on line 635, but not defined -- Looks like a reference, but probably isn't: '2' on line 694 -- Looks like a reference, but probably isn't: '3' on line 696 -- Looks like a reference, but probably isn't: '4' on line 698 -- Looks like a reference, but probably isn't: '5' on line 700 -- Looks like a reference, but probably isn't: '6' on line 705 -- Possible downref: Non-RFC (?) normative reference: ref. 'ES6' -- Possible downref: Non-RFC (?) normative reference: ref. 'IEEE754' -- Possible downref: Non-RFC (?) normative reference: ref. 'UNICODE' Summary: 1 error (**), 0 flaws (~~), 10 warnings (==), 10 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group A. Rundgren 3 Internet-Draft Independent 4 Intended status: Standards Track May 18, 2018 5 Expires: November 19, 2018 7 JSON Canonicalization Scheme (JCS) 8 draft-rundgren-json-canonicalization-scheme-00 10 Abstract 12 Cryptographic operations like hashing and signing depend on that the 13 target data does not change during serialization, transport, or 14 parsing. By applying the rules defined by JCS (JSON Canonicalization 15 Scheme), data provided in the JSON [RFC8259] format can be exchanged 16 "as is", while still being subject to secure cryptographic 17 operations. JCS achieves this by combining the strict serialization 18 of JSON primitives defined in ECMAScript [ES6] with a platform 19 independent sorting scheme. 21 The intended audiences of this document are JSON tool vendors, as 22 well as designers of JSON based cryptographic solutions. 24 Status of This Memo 26 This Internet-Draft is submitted in full conformance with the 27 provisions of BCP 78 and BCP 79. 29 Internet-Drafts are working documents of the Internet Engineering 30 Task Force (IETF). Note that other groups may also distribute 31 working documents as Internet-Drafts. The list of current Internet- 32 Drafts is at https://datatracker.ietf.org/drafts/current/. 34 Internet-Drafts are draft documents valid for a maximum of six months 35 and may be updated, replaced, or obsoleted by other documents at any 36 time. It is inappropriate to use Internet-Drafts as reference 37 material or to cite them other than as "work in progress." 39 This Internet-Draft will expire on November 19, 2018. 41 Copyright Notice 43 Copyright (c) 2018 IETF Trust and the persons identified as the 44 document authors. All rights reserved. 46 This document is subject to BCP 78 and the IETF Trust's Legal 47 Provisions Relating to IETF Documents 48 (https://trustee.ietf.org/license-info) in effect on the date of 49 publication of this document. Please review these documents 50 carefully, as they describe your rights and restrictions with respect 51 to this document. Code Components extracted from this document must 52 include Simplified BSD License text as described in Section 4.e of 53 the Trust Legal Provisions and are provided without warranty as 54 described in the Simplified BSD License. 56 Table of Contents 58 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 59 2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 3 60 3. Detailed Operation . . . . . . . . . . . . . . . . . . . . . 3 61 3.1. Creation of JSON Data . . . . . . . . . . . . . . . . . . 3 62 3.2. Canonicalization of JSON Data . . . . . . . . . . . . . . 4 63 3.2.1. Whitespace Handling . . . . . . . . . . . . . . . . . 4 64 3.2.2. Serialization of Primitive Data Types . . . . . . . . 4 65 3.2.2.1. Serialization of Literals . . . . . . . . . . . . 5 66 3.2.2.2. Serialization of Strings . . . . . . . . . . . . 5 67 3.2.2.3. Serialization of Numbers . . . . . . . . . . . . 6 68 3.2.3. Sorting of Object Properties . . . . . . . . . . . . 6 69 3.2.4. UTF-8 Generation . . . . . . . . . . . . . . . . . . 7 70 4. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8 71 5. Security Considerations . . . . . . . . . . . . . . . . . . . 8 72 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 8 73 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 8 74 7.1. Normative References . . . . . . . . . . . . . . . . . . 8 75 7.2. Informal References . . . . . . . . . . . . . . . . . . . 9 76 7.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 9 77 Appendix A. ES6 Sample Canonicalizer . . . . . . . . . . . . . . 10 78 Appendix B. Number Serialization Samples . . . . . . . . . . . . 11 79 Appendix C. Canonicalized JSON as "Wire Format" . . . . . . . . 13 80 Appendix D. Dealing with Big Numbers . . . . . . . . . . . . . . 13 81 Appendix E. Implementation Guidelines . . . . . . . . . . . . . 14 82 Appendix F. Other JSON Canonicalization Efforts . . . . . . . . 15 83 Appendix G. Development Portal . . . . . . . . . . . . . . . . . 16 84 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 16 86 1. Introduction 88 Cryptographic operations like hashing and signing depend on that the 89 target data does not change during serialization, transport, or 90 parsing. A straightforward way of accomplishing this is converting 91 the data into a format which has a simple and fixed representation 92 like Base64Url [RFC4648] which for example have been used in JWS 93 [RFC7515]. Another solution is creating a canonicalized version of 94 the target data with XML Signature [XMLDSIG] as a prime example. 96 Since the objective was keeping the data "as is", the 97 canonicalization method was selected. For avoiding "reinventing the 98 wheel", JCS relies on serialization of JSON primitives compatible 99 with ECMAScript (aka JavaScript) beginning with version 6 [ES6], from 100 now on simply referred to as "ES6". 102 Seasoned XML developers recalling difficulties getting signatures to 103 validate (usually due to different interpretations of the quite 104 intricate XML canonicalization rules as well as of the equally 105 extensive Web Services security standards), may rightfully wonder why 106 this particular effort would succeed. The reasons are twofold: 108 o JSON is a considerably simpler format than XML, as well as lacking 109 support for the powerful (but complex) namespace concept. 111 o ES6 compatible JSON serialization is already supported by most Web 112 browsers, Node.js [NODEJS], as well as by third party libraries 113 like Open Keystore [OPENKEY], giving the proposed canonicalization 114 scheme a head start. Also see Appendix E. 116 The JCS specification describes how JSON serializing rules compliant 117 with ES6 combined with an elementary sorting scheme, can be used for 118 supporting "Crypto Safe" JSON. 120 JCS is compatible with some existing systems relying on JSON 121 canonicalization such as JWK Thumbprint [RFC7638] and Keybase 122 [KEYBASE]. 124 2. Terminology 126 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 127 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 128 "OPTIONAL" in this document are to be interpreted as described in BCP 129 14 [RFC2119] [RFC8174] when, and only when, they appear in all 130 capitals, as shown here. 132 3. Detailed Operation 134 This section describes the different issues related to JSON 135 canonicalization, and how they are addressed by JCS. 137 3.1. Creation of JSON Data 139 In order to canonicalize JSON data, an internal representation of the 140 JSON data is needed. This can be achieved by: 142 o Parsing externally supplied JSON data. 144 o Programmatic creation of JSON data. 146 Irrespective of method used, the JSON data MUST be compatible both 147 with ES6 and I-JSON [RFC7493], which implies the following: 149 o There MUST NOT be any duplicate property names within an "Object". 151 o Data of the type "String" MUST be expressible as Unicode [UNICODE] 152 strings. Also see Section 3.2.2.2. 154 o Data of the type "Number" MUST be expressible as IEEE-754 155 [IEEE754] double precision values. Also see Section 3.2.2.3. 157 3.2. Canonicalization of JSON Data 159 The following sub sections describe the steps required for creating a 160 canonicalized version of internal JSON data elaborated on in the 161 previous section. 163 Appendix A shows sample code for an ES6 based canonicalizer, matching 164 the JCS specification. 166 3.2.1. Whitespace Handling 168 Possible whitespace between JSON elements MUST be ignored (not 169 emitted). 171 3.2.2. Serialization of Primitive Data Types 173 Assume that you parse a JSON object like the following: 175 { 176 "numbers": [333333333.33333329, 1E30, 4.50, 177 2e-3, 0.000000000000000000000000001], 178 "string": "\u20ac$\u000F\u000aA'\u0042\u0022\u005c\\\"\/", 179 "literals": [null, true, false] 180 } 182 If you subsequently serialize the object created by the operation 183 above using an serializer compliant with ES6's "JSON.stringify()", 184 the result would (with a line wrap added for display purposes only), 185 be rather divergent with respect to representation of data: 187 {"numbers":[333333333.3333333,1e+30,4.5,0.002,1e-27],"string": 188 "\u20ac$\u000f\nA'B\"\\\\\"/","literals":[null,true,false]} 190 Note: \u20ac denotes the Euro character, which not 191 being ASCII, is currently not displayable in RFCs. 193 The reason for the difference between the parsed data and its 194 serialized counterpart, is due to a wide tolerance on input data (as 195 defined by JSON [RFC8259]), while output data (as defined by ES6), 196 has a fixed representation. As can be seen by the example, numbers 197 are subject to rounding as well. 199 The following sub sections describe serialization of primitive JSON 200 data types according to JCS. This part is identical to that of ES6. 202 3.2.2.1. Serialization of Literals 204 The JSON literals "null", "true", and "false" present no challenge 205 since they already have a fixed definition in JSON [RFC8259]. 207 3.2.2.2. Serialization of Strings 209 For JSON data of the type "String" (which includes "Object" property 210 names as well), each character MUST be serialized as described in 211 Section 24.3.2.2 of ES6. 213 If the Unicode value falls within the traditional ASCII control 214 character range (U+0000 through U+001F), it MUST be serialized using 215 lowercase hexadecimal Unicode notation (\uhhhh) unless it is in the 216 set of predefined JSON control characters U+0008, U+0009, U+000A, 217 U+000C or U+000D which MUST be serialized as \b, \t, \n, \f and \r 218 respectively. 220 If the Unicode value is outside of the ASCII control character range, 221 it MUST be serialized "as is" unless it is equivalent to U+005C (\) 222 or U+0022 (") which MUST be serialized as \\ and \" respectively. 224 Finally, the serialized string value MUST be enclosed in double 225 quotes ("). 227 Note that many JSON systems permit the use of invalid Unicode data 228 like "lone surrogates" (e.g. U+DEAD), which also is dealt with in a 229 platform specific way. Since this leads to interoperability issues 230 including broken signatures, such usages MUST be avoided. 232 Note that although the Unicode standard offers a possibility 233 combining certain characters into one, referred to as "Unicode 234 Normalization" (https://www.unicode.org/reports/tr15/ [1]), such 235 functionality MUST be delegated to the application layer which 236 already is the case for most other uses of JSON. 238 3.2.2.3. Serialization of Numbers 240 JSON data of the type "Number" MUST be serialized according to 241 Section 7.1.12.1 of ES6; for maximum interoperability preferably 242 including the "Note 2" enhancement as well. The latter is 243 implemented by for example Google's V8 [V8]. 245 Due to the relative complexity of this part, it is not included in 246 this specification. 248 Note that ES6 builds on the IEEE-754 [IEEE754] double precision 249 standard for storing "Number" data. Appendix B holds a set of 250 IEEE-754 sample values and their corresponding JSON serialization. 252 Occasionally applications need higher precision or longer integers 253 than offered by the current implementation of JSON "Number" in ES6. 254 Appendix D outlines how this can be achieved in a portable and 255 extensible way. 257 3.2.3. Sorting of Object Properties 259 Although the previous step indeed normalized the representation of 260 primitive JSON data types, the result would not qualify as 261 "canonicalized" since "Object" properties are not in lexicographic 262 (alphabetical) order. 264 Applied to the sample in Section 3.2.2, a properly canonicalized 265 version should (with a line wrap added for display purposes only), 266 read as: 268 {"literals":[null,true,false],"numbers":[333333333.3333333, 269 1e+30,4.5,0.002,1e-27],"string":"\u20ac$\u000f\nA'B\"\\\\\"/"} 271 Note: \u20ac denotes the Euro character, which not 272 being ASCII, is currently not displayable in RFCs. 274 The rules for lexicographic sorting of JSON properties according to 275 JCS are as follows: 277 o "Object" properties are sorted in a recursive manner which means 278 that a found JSON child "Object" type MUST be subject to sorting 279 as well. 281 o JSON "Array" data MUST also be checked for the presence of 282 sortable JSON "Object" elements, but array element order MUST NOT 283 be changed. 285 When a JSON "Object" is about to have its properties sorted, the 286 following measures MUST be performed: 288 o Property strings to be sorted depend on that strings are 289 represented as arrays of 16-bit unsigned integers where each 290 integer holds a single UCS2/UTF-16 [UNICODE] code unit. The 291 sorting is based on pure value comparisons, independent of locale 292 settings. 294 o Property strings either have different values at some index that 295 is a valid index for both strings, or their lengths are different, 296 or both. If they have different values at one or more index 297 positions, let k be the smallest such index; then the string whose 298 value at position k has the smaller value, as determined by using 299 the < operator, lexicographically precedes the other string. If 300 there is no index position at which they differ, then the shorter 301 string lexicographically precedes the longer string. 303 The rationale for basing the sort algorithm on UCS2/UTF-16 code units 304 is that it maps directly to the string type in ECMAScript, Java and 305 .NET. Systems using another representation of string data will need 306 to convert JSON property strings into arrays of UCS2/UTF-16 code 307 units before sorting. 309 Note: for the purpose obtaining a deterministic property order, 310 sorting on UTF-8 or UTF-32 encoded data would also work, but the 311 result would differ (and thus be incompatible with this 312 specification). 314 3.2.4. UTF-8 Generation 316 Finally, in order to create a platform independent representation, 317 the resulting JSON string data MUST be encoded in UTF-8. 319 Applied to the sample in Section 3.2.3 this should yield the 320 following bytes here shown in hexadecimal notation: 322 7b 22 6c 69 74 65 72 61 6c 73 22 3a 5b 6e 75 6c 6c 2c 74 72 323 75 65 2c 66 61 6c 73 65 5d 2c 22 6e 75 6d 62 65 72 73 22 3a 324 5b 33 33 33 33 33 33 33 33 33 2e 33 33 33 33 33 33 33 2c 31 325 65 2b 33 30 2c 34 2e 35 2c 30 2e 30 30 32 2c 31 65 2d 32 37 326 5d 2c 22 73 74 72 69 6e 67 22 3a 22 e2 82 ac 24 5c 75 30 30 327 30 66 5c 6e 41 27 42 5c 22 5c 5c 5c 5c 5c 22 2f 22 7d 329 This data is intended to be usable as input to cryptographic 330 functions. 332 For other uses see Appendix C. 334 4. IANA Considerations 336 This document has no IANA actions. 338 5. Security Considerations 340 JSON parsers MUST check that input data conforms to the JSON 341 [RFC8259] specification. 343 6. Acknowledgements 345 Building on ES6 "Number" normalization was originally proposed by 346 James Manger. This ultimately led to the adoption of the entire ES6 347 serialization scheme for JSON primitives. 349 Other people who have contributed with valuable input to this 350 specification include Mike Jones, Mike Miller, Mike Samuel, Michal 351 Wadas, Richard Gibson and Scott Ananian. 353 7. References 355 7.1. Normative References 357 [ES6] Ecma International, "ECMAScript 2015 Language 358 Specification", . 361 [IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic", 362 August 2008, . 364 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 365 Requirement Levels", BCP 14, RFC 2119, 366 DOI 10.17487/RFC2119, March 1997, 367 . 369 [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, 370 DOI 10.17487/RFC7493, March 2015, 371 . 373 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 374 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 375 May 2017, . 377 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 378 Interchange Format", STD 90, RFC 8259, 379 DOI 10.17487/RFC8259, December 2017, 380 . 382 [UNICODE] The Unicode Consortium, "The Unicode Standard, Version 383 10.0.0", 384 . 386 7.2. Informal References 388 [KEYBASE] "Keybase", 389 . 391 [NODEJS] "Node.js", . 393 [OPENAPI] "The OpenAPI Initiative", . 395 [OPENKEY] "Open Keystore", 396 . 398 [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 399 Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, 400 . 402 [RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web 403 Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May 404 2015, . 406 [RFC7638] Jones, M. and N. Sakimura, "JSON Web Key (JWK) 407 Thumbprint", RFC 7638, DOI 10.17487/RFC7638, September 408 2015, . 410 [V8] Google LLC, "Chrome V8 Open Source JavaScript Engine", 411 . 413 [XMLDSIG] W3C, "XML Signature Syntax and Processing Version 1.1", 414 . 416 7.3. URIs 418 [1] https://www.unicode.org/reports/tr15/ 420 [2] https://tools.ietf.org/html/draft-staykov-hu-json-canonical- 421 form-00 423 [3] https://gibson042.github.io/canonicaljson-spec/ 425 [4] https://www.npmjs.com/package/canonicalize 427 [5] http://wiki.laptop.org/go/Canonical_JSON 429 [6] https://github.com/cyberphone/json-canonicalization 431 Appendix A. ES6 Sample Canonicalizer 433 Below is a functionally complete example of a JCS compliant 434 canonicalizer for usage with ES6 based systems. 436 Note: The primary purpose of this code is highlighting the 437 canonicalization algorithm. Using the full power of ES6 would reduce 438 the code size considerably but would also be more difficult to follow 439 by non-experts. 441 var canonicalize = function(object) { 443 var buffer = ''; 444 serialize(object); 445 return buffer; 447 function serialize(object) { 448 if (object === null || typeof object !== 'object') { 449 ///////////////////////////////////////////////// 450 // Primitive data type - Use ES6/JSON // 451 ///////////////////////////////////////////////// 452 buffer += JSON.stringify(object); 454 } else if (Array.isArray(object)) { 455 ///////////////////////////////////////////////// 456 // Array - Maintain element order // 457 ///////////////////////////////////////////////// 458 buffer += '['; 459 let next = false; 460 object.forEach((element) => { 461 if (next) { 462 buffer += ','; 463 } 464 next = true; 465 ///////////////////////////////////////// 466 // Array element - Recursive expansion // 467 ///////////////////////////////////////// 468 serialize(element); 469 }); 470 buffer += ']'; 472 } else { 473 ///////////////////////////////////////////////// 474 // Object - Sort properties before serializing // 475 ///////////////////////////////////////////////// 476 buffer += '{'; 477 let next = false; 478 Object.keys(object).sort().forEach((property) => { 479 if (next) { 480 buffer += ','; 481 } 482 next = true; 483 /////////////////////////////////////////////// 484 // Property names are strings - Use ES6/JSON // 485 /////////////////////////////////////////////// 486 buffer += JSON.stringify(property); 487 buffer += ':'; 488 ////////////////////////////////////////// 489 // Property value - Recursive expansion // 490 ////////////////////////////////////////// 491 serialize(object[property]); 492 }); 493 buffer += '}'; 494 } 495 } 496 }; 498 Appendix B. Number Serialization Samples 500 The following table holds a set of ES6 "Number" serialization 501 samples, including some edge cases. The column "ES6 Internal" refers 502 to the internal ES6 representation of the "Number" data type which is 503 based on the IEEE-754 [IEEE754] standard using 64-bit (double 504 precision) values, here expressed in hexadecimal. 506 |===================================================================| 507 | ES6 Internal | JSON Representation | Comment | 508 |===================================================================| 509 | 0000000000000000 | 0 | Zero | 510 |-------------------------------------------------------------------| 511 | 8000000000000000 | 0 | Minus zero | 512 |-------------------------------------------------------------------| 513 | 0000000000000001 | 5e-324 | Smallest pos number | 514 |-------------------------------------------------------------------| 515 | 8000000000000001 | -5e-324 | Smallest neg number | 516 |-------------------------------------------------------------------| 517 | 7fefffffffffffff | 1.7976931348623157e+308 | Largest pos number | 518 |-------------------------------------------------------------------| 519 | ffefffffffffffff | -1.7976931348623157e+308 | Largest neg number | 520 |-------------------------------------------------------------------| 521 | 4340000000000000 | 9007199254740992 | Largest pos integer | 522 |-------------------------------------------------------------------| 523 | c340000000000000 | -9007199254740992 | Largest neg integer | 524 |-------------------------------------------------------------------| 525 | 7fffffffffffffff | | Error (NaN) | 526 |-------------------------------------------------------------------| 527 | 7ff0000000000000 | | Error (Infinity) | 528 |-------------------------------------------------------------------| 529 | 44b52d02c7e14af5 | 9.999999999999997e+22 | | 530 |-------------------------------------------------------------------| 531 | 44b52d02c7e14af6 | 1e+23 | | 532 |-------------------------------------------------------------------| 533 | 44b52d02c7e14af7 | 1.0000000000000001e+23 | | 534 |-------------------------------------------------------------------| 535 | 444b1ae4d6e2ef4e | 999999999999999700000 | | 536 |-------------------------------------------------------------------| 537 | 444b1ae4d6e2ef4f | 999999999999999900000 | | 538 |-------------------------------------------------------------------| 539 | 444b1ae4d6e2ef50 | 1e+21 | | 540 |-------------------------------------------------------------------| 541 | 444b1ae4d6e2ef51 | 1.0000000000000001e+21 | | 542 |-------------------------------------------------------------------| 543 | 41b3de4355555553 | 333333333.3333332 | | 544 |-------------------------------------------------------------------| 545 | 41b3de4355555554 | 333333333.33333325 | | 546 |-------------------------------------------------------------------| 547 | 41b3de4355555555 | 333333333.3333333 | | 548 |-------------------------------------------------------------------| 549 | 41b3de4355555556 | 333333333.3333334 | | 550 |-------------------------------------------------------------------| 551 | 41b3de4355555557 | 333333333.33333343 | | 552 |-------------------------------------------------------------------| 553 Note: for maximum compliance with ECMAScript's JSON object, values 554 that are to be interpreted as true integers, SHOULD be in the range 555 -9007199254740991 to 9007199254740991. 557 Appendix C. Canonicalized JSON as "Wire Format" 559 Since the result from the canonicalization process (see 560 Section 3.2.4), is fully valid JSON, it can also be used as 561 "Wire Format". However, this is just an option since cryptographic 562 schemes based on JCS, in most cases would not depend on that 563 externally supplied JSON data already is canonicalized. 565 In fact, the ES6 standard way of serializing objects using 566 "JSON.stringify()" produces a more "logical" format, where properties 567 are kept in the order they were created or received. The example 568 below shows an address record which could benefit from ES6 standard 569 serialization: 571 { 572 "name": "John Doe", 573 "address": "2000 Sunset Boulevard", 574 "city": "Los Angeles", 575 "zip": "90001", 576 "state": "CA" 577 } 579 Using canonicalization the properties above would be output in the 580 order "address", "city", "name", "state" and "zip", which adds 581 fuzziness to the data from a human (developer or technical support), 582 perspective. 584 That is, for many applications, canonicalization would only be used 585 internally for creating a "hashable" representation of the data 586 needed for cryptographic operations. 588 Note that if message size is not a concern, you may even send 589 "Pretty Printed" JSON data on the wire (since whitespace always is 590 ignored by the canonicalization process). 592 Appendix D. Dealing with Big Numbers 594 There are two major issues associated with the JSON "Number" type, 595 here illustrated by the following sample object: 597 { 598 "giantNumber": 1.4e+9999, 599 "payMeThis": 26000.33, 600 "int64Max": 9223372036854775807 601 } 603 Although the sample above conforms to JSON (according to [RFC8259]), 604 there are some practical hurdles to consider: 606 o Standard JSON parsers rarely process "giantNumber" in a meaningful 607 way. 64-bit integers like "int64Max" normally pass through 608 parsers, but in systems like ES6, at the expense of lost 609 precision. 611 o Another issue is that parsers typically would use different 612 schemes for handling "giantNumber" and "int64Max". In addition, 613 monetary data like "payMeThis" would presumably not rely on a 614 floating point system due to rounding issues with respect to 615 decimal arithmetic. 617 The (to the author NB), only known way handling this kind of 618 "overloading" of the "Number" type (at least in an extensible 619 manner), is through mapping mechanisms, instructing parsers what 620 to do with different properties based on their name. However, 621 this greatly limits the value of using the "Number" type outside 622 of its original somewhat constrained, JavaScript context. 624 For usage with JCS (and in fact for any usage of JSON by multiple 625 parties potentially using independently developed software), numbers 626 that do not have a natural place in the current JSON ecosystem MUST 627 be wrapped using the JSON "String" type. This is close to a de-facto 628 standard for open systems. 630 Aided by a mapping system; be it programmatic like 632 var obj = JSON.parse('{"giantNumber": "1.4e+9999"}'); 633 var biggie = new BigNumber(obj.giantNumber); 635 or declarative schemes like OpenAPI [OPENAPI], there are no real 636 limits, not even when using ES6. 638 Appendix E. Implementation Guidelines 640 The optimal solution is integrating support for JCS directly in JSON 641 parsers and serializers. However, this is not always realistic. 642 Fortunately JCS support can be performed through externally supplied 643 canonicalizer software, enabling signature creation schemes like the 644 following: 646 1. Create the data to be signed. 648 2. Serialize the data using existing JSON tools. 650 3. Let the external canonicalizer process the serialized data and 651 return canonicalized result data. 653 4. Sign the canonicalized data. 655 5. Add the resulting signature value to the original JSON data 656 through a designated signature property. 658 6. Serialize the completed (now signed) JSON object using existing 659 JSON tools. 661 A compatible signature verification scheme would then be as follows: 663 1. Parse the signed JSON data using existing JSON tools. 665 2. Read and save the signature value from the designated signature 666 property. 668 3. Remove the signature property from the parsed JSON object. 670 4. Serialize the remaining JSON data using existing JSON tools. 672 5. Let the external canonicalizer process the serialized data and 673 return canonicalized result data. 675 6. Verify that the canonicalized data matches the saved signature 676 value using the algorithm and key used for creating the 677 signature. 679 A canonicalizer like above is effectively only a "filter", 680 potentially usable with a multitude of quite different cryptographic 681 schemes. 683 Using an integrated canonicalizer, you would eliminate the 684 serialization and parsing step before the canonicalization, for both 685 processes. That is, canonicalization would typically be an 686 additional "mode" for a JSON serializer. 688 Appendix F. Other JSON Canonicalization Efforts 690 There are (and have been) other efforts creating "Canonical JSON". 691 Below is a list of URLs to some of them: 693 o https://tools.ietf.org/html/draft-staykov-hu-json-canonical- 694 form-00 [2] 696 o https://gibson042.github.io/canonicaljson-spec/ [3] 698 o https://www.npmjs.com/package/canonicalize [4] 700 o http://wiki.laptop.org/go/Canonical_JSON [5] 702 Appendix G. Development Portal 704 The JSC specification is currently developed at 705 https://github.com/cyberphone/json-canonicalization [6]. 707 The portal also provides software for testing. 709 Author's Address 711 Anders Rundgren 712 Independent 713 Montpellier 714 France 716 Email: anders.rundgren.net@gmail.com 717 URI: https://www.linkedin.com/in/andersrundgren/