idnits 2.17.1 draft-rundgren-json-canonicalization-scheme-01.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 (June 25, 2018) is 2130 days in the past. Is this intentional? Checking references for intended status: Informational ---------------------------------------------------------------------------- == Missing Reference: 'RFC4648' is mentioned on line 401, but not defined == Missing Reference: 'RFC7515' is mentioned on line 405, but not defined == Missing Reference: 'XMLDSIG' is mentioned on line 416, but not defined == Missing Reference: 'NODEJS' is mentioned on line 394, but not defined == Missing Reference: 'OPENKEY' is mentioned on line 398, but not defined == Missing Reference: 'RFC7638' is mentioned on line 409, but not defined == Missing Reference: 'KEYBASE' is mentioned on line 391, but not defined -- Looks like a reference, but probably isn't: '1' on line 421 == Missing Reference: 'V8' is mentioned on line 413, but not defined == Missing Reference: 'OPENAPI' is mentioned on line 638, but not defined -- Looks like a reference, but probably isn't: '2' on line 697 -- Looks like a reference, but probably isn't: '3' on line 699 -- Looks like a reference, but probably isn't: '4' on line 701 -- Looks like a reference, but probably isn't: '5' on line 703 -- Looks like a reference, but probably isn't: '6' on line 708 Summary: 1 error (**), 0 flaws (~~), 10 warnings (==), 7 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: Informational June 25, 2018 5 Expires: December 27, 2018 7 JSON Canonicalization Scheme (JCS) 8 draft-rundgren-json-canonicalization-scheme-01 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 December 27, 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 adhered to: 288 o The sorting process is applied to the internal representation of 289 property strings. That is, their state before serialization. 291 o Property strings to be sorted depend on that strings are 292 internally represented as arrays of 16-bit unsigned integers where 293 each integer holds a single UCS2/UTF-16 [UNICODE] code unit. The 294 sorting is based on pure value comparisons, independent of locale 295 settings. 297 o Property strings either have different values at some index that 298 is a valid index for both strings, or their lengths are different, 299 or both. If they have different values at one or more index 300 positions, let k be the smallest such index; then the string whose 301 value at position k has the smaller value, as determined by using 302 the < operator, lexicographically precedes the other string. If 303 there is no index position at which they differ, then the shorter 304 string lexicographically precedes the longer string. 306 The rationale for basing the sort algorithm on UCS2/UTF-16 code units 307 is that it maps directly to the string type in ECMAScript, Java and 308 .NET. Systems using another representation of string data will need 309 to convert JSON property strings into arrays of UCS2/UTF-16 code 310 units before sorting. 312 Note: for the purpose obtaining a deterministic property order, 313 sorting on UTF-8 or UTF-32 encoded data would also work, but the 314 result would differ (and thus be incompatible with this 315 specification). 317 3.2.4. UTF-8 Generation 319 Finally, in order to create a platform independent representation, 320 the resulting JSON string data MUST be encoded in UTF-8. 322 Applied to the sample in Section 3.2.3 this should yield the 323 following bytes here shown in hexadecimal notation: 325 7b 22 6c 69 74 65 72 61 6c 73 22 3a 5b 6e 75 6c 6c 2c 74 72 326 75 65 2c 66 61 6c 73 65 5d 2c 22 6e 75 6d 62 65 72 73 22 3a 327 5b 33 33 33 33 33 33 33 33 33 2e 33 33 33 33 33 33 33 2c 31 328 65 2b 33 30 2c 34 2e 35 2c 30 2e 30 30 32 2c 31 65 2d 32 37 329 5d 2c 22 73 74 72 69 6e 67 22 3a 22 e2 82 ac 24 5c 75 30 30 330 30 66 5c 6e 41 27 42 5c 22 5c 5c 5c 5c 5c 22 2f 22 7d 332 This data is intended to be usable as input to cryptographic 333 functions. 335 For other uses see Appendix C. 337 4. IANA Considerations 339 This document has no IANA actions. 341 5. Security Considerations 343 JSON parsers MUST check that input data conforms to the JSON 344 [RFC8259] specification. 346 6. Acknowledgements 348 Building on ES6 "Number" normalization was originally proposed by 349 James Manger. This ultimately led to the adoption of the entire ES6 350 serialization scheme for JSON primitives. 352 Other people who have contributed with valuable input to this 353 specification include Mike Jones, Mike Miller, Mike Samuel, Michal 354 Wadas, Richard Gibson and Scott Ananian. 356 7. References 358 7.1. Normative References 360 [ES6] Ecma International, "ECMAScript 2015 Language 361 Specification", . 364 [IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic", 365 August 2008, . 367 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 368 Requirement Levels", BCP 14, RFC 2119, 369 DOI 10.17487/RFC2119, March 1997, 370 . 372 [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, 373 DOI 10.17487/RFC7493, March 2015, 374 . 376 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 377 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 378 May 2017, . 380 [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 381 Interchange Format", STD 90, RFC 8259, 382 DOI 10.17487/RFC8259, December 2017, 383 . 385 [UNICODE] The Unicode Consortium, "The Unicode Standard, Version 386 10.0.0", 387 . 389 7.2. Informal References 391 [KEYBASE] "Keybase", 392 . 394 [NODEJS] "Node.js", . 396 [OPENAPI] "The OpenAPI Initiative", . 398 [OPENKEY] "Open Keystore", 399 . 401 [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data 402 Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, 403 . 405 [RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web 406 Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May 407 2015, . 409 [RFC7638] Jones, M. and N. Sakimura, "JSON Web Key (JWK) 410 Thumbprint", RFC 7638, DOI 10.17487/RFC7638, September 411 2015, . 413 [V8] Google LLC, "Chrome V8 Open Source JavaScript Engine", 414 . 416 [XMLDSIG] W3C, "XML Signature Syntax and Processing Version 1.1", 417 . 419 7.3. URIs 421 [1] https://www.unicode.org/reports/tr15/ 423 [2] https://tools.ietf.org/html/draft-staykov-hu-json-canonical- 424 form-00 426 [3] https://gibson042.github.io/canonicaljson-spec/ 428 [4] https://www.npmjs.com/package/canonicalize 430 [5] http://wiki.laptop.org/go/Canonical_JSON 432 [6] https://github.com/cyberphone/json-canonicalization 434 Appendix A. ES6 Sample Canonicalizer 436 Below is a functionally complete example of a JCS compliant 437 canonicalizer for usage with ES6 based systems. 439 Note: The primary purpose of this code is highlighting the 440 canonicalization algorithm. Using the full power of ES6 would reduce 441 the code size considerably but would also be more difficult to follow 442 by non-experts. 444 var canonicalize = function(object) { 446 var buffer = ''; 447 serialize(object); 448 return buffer; 450 function serialize(object) { 451 if (object === null || typeof object !== 'object') { 452 ///////////////////////////////////////////////// 453 // Primitive data type - Use ES6/JSON // 454 ///////////////////////////////////////////////// 455 buffer += JSON.stringify(object); 457 } else if (Array.isArray(object)) { 458 ///////////////////////////////////////////////// 459 // Array - Maintain element order // 460 ///////////////////////////////////////////////// 461 buffer += '['; 462 let next = false; 463 object.forEach((element) => { 464 if (next) { 465 buffer += ','; 466 } 467 next = true; 468 ///////////////////////////////////////// 469 // Array element - Recursive expansion // 470 ///////////////////////////////////////// 471 serialize(element); 472 }); 473 buffer += ']'; 475 } else { 476 ///////////////////////////////////////////////// 477 // Object - Sort properties before serializing // 478 ///////////////////////////////////////////////// 479 buffer += '{'; 480 let next = false; 481 Object.keys(object).sort().forEach((property) => { 482 if (next) { 483 buffer += ','; 484 } 485 next = true; 486 /////////////////////////////////////////////// 487 // Property names are strings - Use ES6/JSON // 488 /////////////////////////////////////////////// 489 buffer += JSON.stringify(property); 490 buffer += ':'; 491 ////////////////////////////////////////// 492 // Property value - Recursive expansion // 493 ////////////////////////////////////////// 494 serialize(object[property]); 495 }); 496 buffer += '}'; 497 } 498 } 499 }; 501 Appendix B. Number Serialization Samples 503 The following table holds a set of ES6 "Number" serialization 504 samples, including some edge cases. The column "ES6 Internal" refers 505 to the internal ES6 representation of the "Number" data type which is 506 based on the IEEE-754 [IEEE754] standard using 64-bit (double 507 precision) values, here expressed in hexadecimal. 509 |===================================================================| 510 | ES6 Internal | JSON Representation | Comment | 511 |===================================================================| 512 | 0000000000000000 | 0 | Zero | 513 |-------------------------------------------------------------------| 514 | 8000000000000000 | 0 | Minus zero | 515 |-------------------------------------------------------------------| 516 | 0000000000000001 | 5e-324 | Smallest pos number | 517 |-------------------------------------------------------------------| 518 | 8000000000000001 | -5e-324 | Smallest neg number | 519 |-------------------------------------------------------------------| 520 | 7fefffffffffffff | 1.7976931348623157e+308 | Largest pos number | 521 |-------------------------------------------------------------------| 522 | ffefffffffffffff | -1.7976931348623157e+308 | Largest neg number | 523 |-------------------------------------------------------------------| 524 | 4340000000000000 | 9007199254740992 | Largest pos integer | 525 |-------------------------------------------------------------------| 526 | c340000000000000 | -9007199254740992 | Largest neg integer | 527 |-------------------------------------------------------------------| 528 | 7fffffffffffffff | | Error (NaN) | 529 |-------------------------------------------------------------------| 530 | 7ff0000000000000 | | Error (Infinity) | 531 |-------------------------------------------------------------------| 532 | 44b52d02c7e14af5 | 9.999999999999997e+22 | | 533 |-------------------------------------------------------------------| 534 | 44b52d02c7e14af6 | 1e+23 | | 535 |-------------------------------------------------------------------| 536 | 44b52d02c7e14af7 | 1.0000000000000001e+23 | | 537 |-------------------------------------------------------------------| 538 | 444b1ae4d6e2ef4e | 999999999999999700000 | | 539 |-------------------------------------------------------------------| 540 | 444b1ae4d6e2ef4f | 999999999999999900000 | | 541 |-------------------------------------------------------------------| 542 | 444b1ae4d6e2ef50 | 1e+21 | | 543 |-------------------------------------------------------------------| 544 | 444b1ae4d6e2ef51 | 1.0000000000000001e+21 | | 545 |-------------------------------------------------------------------| 546 | 41b3de4355555553 | 333333333.3333332 | | 547 |-------------------------------------------------------------------| 548 | 41b3de4355555554 | 333333333.33333325 | | 549 |-------------------------------------------------------------------| 550 | 41b3de4355555555 | 333333333.3333333 | | 551 |-------------------------------------------------------------------| 552 | 41b3de4355555556 | 333333333.3333334 | | 553 |-------------------------------------------------------------------| 554 | 41b3de4355555557 | 333333333.33333343 | | 555 |-------------------------------------------------------------------| 556 Note: for maximum compliance with ECMAScript's JSON object, values 557 that are to be interpreted as true integers, SHOULD be in the range 558 -9007199254740991 to 9007199254740991. 560 Appendix C. Canonicalized JSON as "Wire Format" 562 Since the result from the canonicalization process (see 563 Section 3.2.4), is fully valid JSON, it can also be used as 564 "Wire Format". However, this is just an option since cryptographic 565 schemes based on JCS, in most cases would not depend on that 566 externally supplied JSON data already is canonicalized. 568 In fact, the ES6 standard way of serializing objects using 569 "JSON.stringify()" produces a more "logical" format, where properties 570 are kept in the order they were created or received. The example 571 below shows an address record which could benefit from ES6 standard 572 serialization: 574 { 575 "name": "John Doe", 576 "address": "2000 Sunset Boulevard", 577 "city": "Los Angeles", 578 "zip": "90001", 579 "state": "CA" 580 } 582 Using canonicalization the properties above would be output in the 583 order "address", "city", "name", "state" and "zip", which adds 584 fuzziness to the data from a human (developer or technical support), 585 perspective. 587 That is, for many applications, canonicalization would only be used 588 internally for creating a "hashable" representation of the data 589 needed for cryptographic operations. 591 Note that if message size is not a concern, you may even send 592 "Pretty Printed" JSON data on the wire (since whitespace always is 593 ignored by the canonicalization process). 595 Appendix D. Dealing with Big Numbers 597 There are two major issues associated with the JSON "Number" type, 598 here illustrated by the following sample object: 600 { 601 "giantNumber": 1.4e+9999, 602 "payMeThis": 26000.33, 603 "int64Max": 9223372036854775807 604 } 606 Although the sample above conforms to JSON (according to [RFC8259]), 607 there are some practical hurdles to consider: 609 o Standard JSON parsers rarely process "giantNumber" in a meaningful 610 way. 64-bit integers like "int64Max" normally pass through 611 parsers, but in systems like ES6, at the expense of lost 612 precision. 614 o Another issue is that parsers typically would use different 615 schemes for handling "giantNumber" and "int64Max". In addition, 616 monetary data like "payMeThis" would presumably not rely on a 617 floating point system due to rounding issues with respect to 618 decimal arithmetic. 620 The (to the author NB), only known way handling this kind of 621 "overloading" of the "Number" type (at least in an extensible 622 manner), is through mapping mechanisms, instructing parsers what 623 to do with different properties based on their name. However, 624 this greatly limits the value of using the "Number" type outside 625 of its original somewhat constrained, JavaScript context. 627 For usage with JCS (and in fact for any usage of JSON by multiple 628 parties potentially using independently developed software), numbers 629 that do not have a natural place in the current JSON ecosystem MUST 630 be wrapped using the JSON "String" type. This is close to a de-facto 631 standard for open systems. 633 Aided by a mapping system; be it programmatic like 635 var obj = JSON.parse('{"giantNumber": "1.4e+9999"}'); 636 var biggie = new BigNumber(obj.giantNumber); 638 or declarative schemes like OpenAPI [OPENAPI], there are no real 639 limits, not even when using ES6. 641 Appendix E. Implementation Guidelines 643 The optimal solution is integrating support for JCS directly in JSON 644 parsers and serializers. However, this is not always realistic. 645 Fortunately JCS support can be performed through externally supplied 646 canonicalizer software, enabling signature creation schemes like the 647 following: 649 1. Create the data to be signed. 651 2. Serialize the data using existing JSON tools. 653 3. Let the external canonicalizer process the serialized data and 654 return canonicalized result data. 656 4. Sign the canonicalized data. 658 5. Add the resulting signature value to the original JSON data 659 through a designated signature property. 661 6. Serialize the completed (now signed) JSON object using existing 662 JSON tools. 664 A compatible signature verification scheme would then be as follows: 666 1. Parse the signed JSON data using existing JSON tools. 668 2. Read and save the signature value from the designated signature 669 property. 671 3. Remove the signature property from the parsed JSON object. 673 4. Serialize the remaining JSON data using existing JSON tools. 675 5. Let the external canonicalizer process the serialized data and 676 return canonicalized result data. 678 6. Verify that the canonicalized data matches the saved signature 679 value using the algorithm and key used for creating the 680 signature. 682 A canonicalizer like above is effectively only a "filter", 683 potentially usable with a multitude of quite different cryptographic 684 schemes. 686 Using an integrated canonicalizer, you would eliminate the 687 serialization and parsing step before the canonicalization, for both 688 processes. That is, canonicalization would typically be an 689 additional "mode" for a JSON serializer. 691 Appendix F. Other JSON Canonicalization Efforts 693 There are (and have been) other efforts creating "Canonical JSON". 694 Below is a list of URLs to some of them: 696 o https://tools.ietf.org/html/draft-staykov-hu-json-canonical- 697 form-00 [2] 699 o https://gibson042.github.io/canonicaljson-spec/ [3] 701 o https://www.npmjs.com/package/canonicalize [4] 703 o http://wiki.laptop.org/go/Canonical_JSON [5] 705 Appendix G. Development Portal 707 The JSC specification is currently developed at 708 https://github.com/cyberphone/json-canonicalization [6]. 710 The portal also provides software for testing. 712 Author's Address 714 Anders Rundgren 715 Independent 716 Montpellier 717 France 719 Email: anders.rundgren.net@gmail.com 720 URI: https://www.linkedin.com/in/andersrundgren/