Mercurial > hg > ietf
changeset 16:f2a7c10fbdd7
as submitted
| author | Henry S. Thompson <ht@inf.ed.ac.uk> |
|---|---|
| date | Fri, 02 May 2025 11:03:22 +0100 |
| parents | 4f6b93a40ca1 |
| children | 4ca654e435db |
| files | jwt_review.txt |
| diffstat | 1 files changed, 115 insertions(+), 57 deletions(-) [+] |
line wrap: on
line diff
--- a/jwt_review.txt Thu May 01 17:03:03 2025 +0100 +++ b/jwt_review.txt Fri May 02 11:03:22 2025 +0100 @@ -1,54 +1,54 @@ +Document: draft-ietf-oauth-selective-disclosure-jwt-18 +Title: Selective Disclosure for JWTs (SD-JWT) +Reviewer: Henry S. Thompson +Review Date: 2025-05-02 + *Summary* +The substance of this is, as far as I can tell as a non-specialist, is +in good shape. There are a few nits and editorial points at the end +of this review, but as will be evident by its length, there is one +essentially presentational issue, classified as Minor because a +specialist in this area will shrug and say "yes, but I see what +they're getting at". I hope none-the-less the authors will find it +useful and address the points I raise, because I do think as things +stand there's a genuine risk of misunderstanding exactly what's +required of an implementation. + *Minor points* -[this actually borders on the 'substantive', see the discussion under -Appendix B.] 4.2.1 This bullet "JSON-encode the array, producing [a] UTF-8 string" - looks simple, but ended up confusing me for over an hour. + looks simple, but ended up taking me several days to sort out. For the rest of things to work, you must mean "Serialize the array - to the corresponding utf-8-encoded byte sequence", but that's not + to the corresponding UTF-8 byte sequence", but that's not exactly trivial in the JSON-native context you've adopted in this document. - That is, at first I thought you should just include one extra - step in the Disclosure construction, example, namely what the - UTF-8 (byte) string looks like as (what RFC8259 calls) "UTF-8 - encoded JSON text", immediately after the array creation - display: - - ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "Möbius"] (1) + In the end I think you should include one extra step in the + Disclosure construction, example, namely what the that byte + sequence looks like as (what [RFC8259] calls) "UTF-8 encoded JSON + text", immediately after the array creation display: - "[\"_26bc4LT-ac6q2KI6cBW5es\", \"family_name\", \"M\u00c3\u00b6bius\"]" (2) - - but that's really ugly and would be more likely to confuse than clarify. + ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "Möbius"] [1] - Note that in only the first 64bitURL Disclosure - samples that you offer decodes to my guess (2)! And indeed - what they _do_ decode to, that is + ["26bc4LT-ac6q2KI6cBW5es", "family_name", "M%xc3%xb6bius"] [2] - '["_26bc4LT-ac6q2KI6cBW5es", "family_name", "Möbius"]' # 4d c3 b6 62 69 75 73 - - '["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M\\u00f6bius"]' + It would also be good at this point to clarify notation and + terminology, following [RFC8259]. That is, to emphasise the + distinction that [1] is a "JSON text" per the RFC, whose final + value is a six-character Unicode string, while [2] is a UTF-8 + byte sequence, the result of what you call "JSON-encoding". - respectively, are non-trivially distinct, as in both Python and - node.js these, as strings, correspond to two _different_ - byte-sequences (the second is 4 bytes longer than the first and, - if both are decoded as utf-8, to 5 more characters). It's true - that they are both valid JSON texts, per RFC8259, but you have to - apply a JSON parser to them to get to indistinguishable JSON objects. + It's true that they are both valid JSON texts, per RFC8259, but + you have to apply a JSON parser to them to get to + indistinguishable JSON objects. - Apologies for this lengthy attempt to show where I think you've - gotten in to trouble by specifying _algorithms_ in informal - english, while more-or-less assuming, I'm guessing, some library - functions in whatever language you're used to using. - - To address this problem, since you use "JSON-encode" a number of + To be more specific, since you use "JSON-encode" a number of times in later sections, I would _strongly recommend_ that you a) Add the following to section 1.2, immediately after the @@ -56,13 +56,13 @@ *JSON-encode* denotes the conversion of a JSON object to "JSON text" and encoding that text in UTF-8, as defined in - RFC 8529. That is, mapping a JSON object to a UTF-8 byte + [RFC8259]. That is, mapping a JSON object to a UTF-8 byte sequence which when decoded and parsed will reconstruct an object indistinguishable from the original. - b) Replace that problematic bullet, and the next, with + b) Replace the first two bullets in the algorithm description, with - * JSON-encode the array, producing a UTF-8 encoded byte sequence. + * JSON-encode the array, producing a UTF-8 byte sequence. * base64url-encode the resulting byte sequence. The resulting string is the Disclosure. @@ -76,15 +76,15 @@ d) In the second media type registration in 12.2 "represented as a JSON Object" -> - 'represented as UTF-8 encoded "JSON text" as defined in RFC 8529' + 'represented as UTF-8 encoded "JSON text" as defined in [RFC8259]' - e) Include RFC 8529 in 13.1 + e) Include [RFC8259] in 13.1 - Appendix B. + Appendices A and B. The above problem resurfaces here, with confusion between three - possible interpretations, in the terms of RFC 8529, of what is - displayed: + possible interpretations, in the terms of [RFC8259], of what is + displayed at various points: * a JSON object, that is, structured data composed of instances of the six primitive types which JSON can @@ -95,10 +95,14 @@ * a UTF-8 encoding of some JSON text, aka a "JSON encoding". + I'll use the first example figure in Appendix B to go through + this in detail, expanding on the discussion above about 4.2.1. + The first figure is labelled as a JSON object, which is OK. - But it is indistinguishable from one of the possible - JSON texts corresponding to that object. + But it is indistinguishable from one of the possible JSON texts + corresponding to that object, and that should be explicitly + acknowledged. The next figure purports to present two alternative "JSON encodings", the second of which is problematic. @@ -106,8 +110,8 @@ Its first line appears indistinguishable from that shown for the JSON object in the preceding figure, but is in fact different. - In the first figure, construed as a "JSON text", the o-umlaut - glyph denotes a single Unicode character in a six-character + In the first figure, construed as "JSON text", the o-umlaut glyph + denotes a single Unicode character in a six-character representation of a six-character object member string value. However in the second figure, second alternative, the o-umlaut @@ -118,14 +122,14 @@ What to do? First, add something similar to https://www.ietf.org/archive/id/draft-bray-unichars-14.html#name-notation Then, whenever presenting JSON, always indicate whether what is - being shown is JSON text or JSON-encoded text (i.e. UTF-8 encoded - JSON text). In JSON text, always include a version using the + being shown is JSON text or JSON-encoded text (that is UTF-8 + byte sequences). In JSON text, always include a version using the U+xxxx notation whenever the underlying string contains non-ASCII characters. In JSON-encoded text, _always_ use the %xnn notation for non-ASCII characters. - Some examples of a possible way of indicating JSON text and - JSON-encoded text, from section 4.2.1 + Some examples of a possible way of indicating JSON text (*JT*) + and JSON-encoded text (*JUBS*), from section 4.2.1 Replace the first figure with these two: @@ -140,9 +144,9 @@ |________________________________________________________| _______________________________________________________________ - |*J-ET* | + |*JUBS* | | | - | ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M%xc3%xb6bius"] | + | ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M%xC3%xB6bius"] | | | |_______________________________________________________________| @@ -158,17 +162,19 @@ |_____________________________________________________________| ______________________________________________________________ - |*J-ET* | + |*JUBS* | | | | ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M\x00f6bius"] | | | |_____________________________________________________________| - WyJfMjZiYzRMVC1hYzZxMktJNmNCVzVlcyIsICJmYW1pbHlfbmFtZSIsICJNX + The corresponding declaration is then + + WyJfMjZiYzRMVC1hYzZxMktJNmNCVzVlcyIsICJmYW1pbHlfbmFtZSIsICJNX HUwMGY2Yml1cyJd And throughout the examples in Appendices A and B, label the initial - figure with *JT* and the 'Content' boxes with *J-ET*. You don't + figure with *JT* and the 'Content' boxes with *JUBS*. You don't need to gloss every Chinese/German string with their U+xxxx version, but saying something at the top of A that where non-ASCII characters appear in any of the initial examples that the actual Unicode @@ -184,22 +190,74 @@ |*JT* | | | | ... | - | "family_name": "Möbius", | - | "address": { | - | "street_address": "Schulstr. 12", | + | "family_name": "Möbius", | ö is the single character + | "address": { | LATIN SMALL LETTER O + | "street_address": "Schulstr. 12", | WITH DIAERESIS | "locality": "Schulpforta" | | } | | ... | |________________________________________| + [In first para, change "byte string" to "byte sequence" + twice, and three more times further down] + + JSON, however, does not prescribe a unique representation for + data, allowing for variations in the how it presented. The JSON + text above is only one possibility. Other possible + representations include + ________________________________________ + |*JT* and *JUEBS* | + | | + | ... | + | "family_name": "M\u00f6bius", | + | "address": { | + | "street_address": "Schulstr. 12", | + | "locality": "Schulpforta" | + | } | + | ... | + |_______________________________________| + + and + + __________________________________________________________________________ + |*JT* | + | | + | ... | + | "family_name": "Möbius", | + | "address": {"locality":"Schulpforta", "street_address":"Schulstr. 12"} | + | ... | + |_________________________________________________________________________| + + ö is the single character LATIN SMALL LETTER O WITH DIAERESIS + + __________________________________________________________________________ + |*JUBS* | + | | + | ... | + | "family_name": "M%xC3%xB6bius", | + | "address": {"locality":"Schulpforta", "street_address":"Schulstr. 12"} | + | ... | + |_________________________________________________________________________| + + + The two representations of the value in family_name are very + different on the byte-level, but when decoded from UTF-8 byte + sequences to JSON texts, those texts would be parsed into + indistinguishable JSON objects. The same goes for ... + + The variations in white space, ordering of object properties, and + representation of Unicode characters are all explicitly allowed + in [RFC8259]. There are further variations, e.g. for floating + point values ([RFC 8785]) and UNICODE combining characters + ([UNICODE]). *Nits* 4. "(for those who celebrate)" will be anywhere from obscure to confusing for many readers from many cultures -- best to remove it. - 4.2.1. "an UTF-8" -> "a UTF-8" [overtaken by 4.2.1 above] + 4.2.1. "an UTF-8" -> "a UTF-8" [overtaken above] "However, the digest is calculated over the respective base64url-encoded value itself, which effectively signs"
