view jwt_review.txt @ 13:38c8261aebfc

renamed, more ascii art
author Henry S. Thompson <ht@inf.ed.ac.uk>
date Thu, 01 May 2025 16:50:41 +0100
parents twt_review.txt@9cb53ac26388
children f2a7c10fbdd7
line wrap: on
line source

*Summary*

*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.
     
     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
     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)

  "[\"_26bc4LT-ac6q2KI6cBW5es\", \"family_name\", \"M\u00c3\u00b6bius\"]" (2)

     but that's really ugly and would be more likely to confuse than clarify.

     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öbius"]'   # 4d c3 b6 62 69 75 73

     '["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M\\u00f6bius"]'

     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.

     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
     times in later sections, I would _strongly recommend_ that you

      a) Add the following to section 1.2, immediately after the
         definition of *base64url*:

         *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
         sequence which when decoded and parsed will reconstruct an
         object indistinguishable from the original.

      b) Replace that problematic bullet, and the next, with

         * JSON-encode the array, producing a UTF-8 encoded byte sequence.

         * base64url-encode the resulting byte sequence. The resulting
           string is the Disclosure.

      c) Be careful never to use "string" when "(UTF-8) byte sequence"
         is meant, starting in 4.2.2 with

           The Disclosure string is created by JSON-encoding this array
           and base64url-encoding the resulting byte sequence as
           described in Section 4.2.1

      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'

      e) Include RFC 8529 in 13.1

 Appendix B.

     The above problem resurfaces here, with confusion between three
     possible interpretations, in the terms of RFC 8529, of what is
     displayed:

        * a JSON object, that is, structured data composed of
          instances of the six primitive types which JSON can
          represent.  It is _not_ to be understood as string, byte
          sequence or file contents;
   
       * a possible JSON text for some JSON object.

       * a UTF-8 encoding of some JSON text, aka a "JSON encoding".

     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.

     The next figure purports to present two alternative "JSON
     encodings", the second of which is problematic.

     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
     representation of a six-character object member string value.

     However in the second figure, second alternative, the o-umlaut
     corresponds to a _two_-byte UTF-8 sub-part of the JSON encoding of
     that value as a seven-byte UTF-8 byte sequence, either in some
     internal representation or an external stream or file.

     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
     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

     Replace the first figure with these two:

     _________________________________________________________
     |*JT*                                                    |
     |                                                        |
     |  ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "Möbius"]  |
     |                                               ^        |
     |                                               |        |
     |                                             X+00F6     |
     |                                                        |
     |________________________________________________________|

     _______________________________________________________________
     |*J-ET*                                                         |
     |                                                               |
     |  ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M%xc3%xb6bius"]  |
     |                                                               |
     |_______________________________________________________________|

  and the first bullet of the three alternatives which follow with

     * A different way to encode the unicode o-umlaut:

     ______________________________________________________________
     |*JT*                                                         |
     |                                                             |
     |  ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M\x00f6bius"]  |
     |                                                             |
     |_____________________________________________________________|

     ______________________________________________________________
     |*J-ET*                                                       |
     |                                                             |
     |  ["_26bc4LT-ac6q2KI6cBW5es", "family_name", "M\x00f6bius"]  |
     |                                                             |
     |_____________________________________________________________|

      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
  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
  character is what is meant.

  The Appendix B example then looks like this, along with some small
  changes to the text:

     Usually, JSON-based formats transport claim values as simple
     properties of a JSON object such as this:

     _________________________________________
     |*JT*                                    |
     |                                        |
     |  ...                                   |
     |    "family_name": "Möbius",            |
     |    "address": {                        |
     |      "street_address": "Schulstr. 12", |
     |      "locality": "Schulpforta"         |
     |     }                                  |
     |  ...                                   |
     |________________________________________|



*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]

        "However, the digest is calculated over the respective
         base64url-encoded value itself, which effectively signs"

         ->

        "Because the digest is calculated over the respective
         base64url-encoded value itself, this effectively signs"

 4.3.1.  I'd recommend
        "The bytes of the digest MUST" -> "The bytes of the sd_hash value MUST"

 6. I have decoded a few of the Disclosures and they're fine, but you
    might want to ask a friendly 3rd party to double-check all the
    Disclosures and digests, at least here and in Appendix A.

 9. "Security considerations in this section help achieve the
     following properties:"

    This confused me for a while.  I think what you mean to say here
    is something like

      This spec aims to provide two security guarantees:

      *Selective Disclosure*: ...

      *Integrity*: ...

    The following sub-sections show how the various aspects of the
    design presented here combine to achieve this.