From e76af5a3ef5dbfd4ef4f2b8dae65f64901bda575 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Fri, 8 Mar 2024 11:08:55 +0100 Subject: [PATCH 1/8] Rework JSON Serialization section --- draft-ietf-oauth-selective-disclosure-jwt.md | 101 +++++++++++++++---- 1 file changed, 80 insertions(+), 21 deletions(-) diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index f850b56a..8a99a41b 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -765,35 +765,94 @@ Otherwise, the processed SD-JWT payload can be passed to the application to be u # JWS JSON Serialization {#json_serialization} -This section describes an optional alternate format for SD-JWT using the JWS JSON Serialization from [@!RFC7515]. +This section describes an alternative format for SD-JWT using the JWS JSON +Serialization from [@!RFC7515]. Supporting this format is OPTIONAL. -For both the General and Flattened JSON Serialization, the SD-JWT is represented as a JSON object according -to Section 7.2 of [@!RFC7515]. The Disclosures (both for issuance and presentation) SHOULD be included in the -serialized JWS using the member name `disclosures` at the top-level of the JSON object (the same level as the `payload` member). The -value of the `disclosures` member is an array of strings where each element is an individual Disclosure -as described in (#creating_disclosures). The Issuer includes a Disclosure for each selectively -disclosable claim of the SD-JWT payload, whereas the Holder includes only the Disclosures -selected for the given presentation. +## New Unprotected Header Parameters {#json_serialization_unprotected_headers} -Alternative methods for conveying the Disclosures MAY be used (such as including them in a `disclosures` -member of an outer JSON structure also containing the JSON Serialized SD-JWT) as dictated by a specific -application or transport protocol. However, the details of such approaches fall outside the scope of this -specification. +For both the General and Flattened JSON Serialization, the SD-JWT is represented +as a JSON object according to Section 7.2 of [@!RFC7515]. The following new +unprotected header parameters are defined: -Verification of the JWS JSON serialized SD-JWT follows the same rules defined in (#verification), -except that the SD-JWT does not need to be split into component parts and the Disclosures -can be found in the respective member of the JSON object (or elsewhere). + * `disclosures`: An array of strings where each element is an individual + Disclosure as described in (#creating_disclosures). + * `kb_jwt`: A Key Binding JWT as described in (#kb-jwt). -Using a payload similar to that from [Example 1](#example-1), the following is a non-normative example of -a JWS JSON serialized SD-JWT from an Issuer with all the respective Disclosures. +If a Key Binding JWT is present, the digest in the `sd_hash` claim MUST be taken over +a string built as described in (#integrity-protection-of-the-presentation), +where the Issuer-signed JWT is built by concatenating the protected header, the +payload, and the unprotected header of the JWS JSON serialized SD-JWT using a +`.` character as a separator, and using the Disclosures from the `disclosures` +member of the unprotected header. -<{{examples/json_serialization/sd_jwt_issuance.json}} +## Flattened JSON Serialization -Below is a non-normative example of a presentation of the JWS JSON serialized SD-JWT, where the Holder -has selected to disclose `given_name`, `family_name`, and `address`. +In case of the Flattened JSON Serialization, there is only one unprotected +header. -<{{examples/json_serialization/sd_jwt_presentation.json}} +The following is a non-normative example of a JWS JSON serialized SD-JWT with +Key Binding using the Flattened JSON Serialization: +```json +{ + "payload":"eyJfc2QiOiBbIjR...Aic2hhLTI1NiJ9", + "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", + "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw", + "header":{ + "disclosures":[ + "WyI2SWo3dE0tYTVpVlBH...W1lIiwgIkRvZSJd", + "WyJBSngtMDk1VlBycFR...ImFkZHJlc3MiLCB7InN0cmVldF9", + "WyJlbHVWNU9nM2dTT...VuX25hbWUiLCAiSm9obiJd" + ], + "kb_jwt":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogI...bGUrc2Qtand0In0" + } +} +``` + +## General JSON Serialization + +In case of the General JSON Serialization, there are multiple unprotected +headers (one per signature). If present, `disclosures` and `kb_jwt`, MUST be +included in the first unprotected header and MUST NOT be present in any +following unprotected headers. + +The following is a non-normative example of a JWS JSON serialized SD-JWT with +Key Binding using the General JSON Serialization: + +```json +{ + "payload":"eyJfc2QiOiBbIjR...Aic2hhLTI1NiJ9", + "signatures":[ + { + "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", + "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw", + "header":{ + "disclosures":[ + "WyI2SWo3dE0tYTVpVlBH...W1lIiwgIkRvZSJd", + "WyJBSngtMDk1VlBycFR...ImFkZHJlc3MiLCB7InN0cmVldF9", + "WyJlbHVWNU9nM2dTT...VuX25hbWUiLCAiSm9obiJd" + ], + "kb_jwt":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogI...bGUrc2Qtand0In0" + } + }, + { + "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", + "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw" + } + ] +} +``` + +## Verification of the JWS JSON Serialized SD-JWT + +Verification of the JWS JSON serialized SD-JWT follows the same rules defined in +(#verification), except for the following aspects: + + * The SD-JWT does not need to be split into component parts and the Disclosures + can be found in the respective member of the JSON object. + * To verify the digest in `sd_hash` in the Key Binding JWT, the Verifier MUST + assemble the string to be hashed as described in + (#json_serialization_unprotected_headers). # Security Considerations {#security_considerations} From bb5b08720f40976237692dd60c36f9e05eedae84 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Fri, 8 Mar 2024 15:57:20 +0100 Subject: [PATCH 2/8] Switch to new branch, update examples --- .github/workflows/ghpages.yml | 2 +- draft-ietf-oauth-selective-disclosure-jwt.md | 53 ++++--------------- examples/json_serialization/specification.yml | 21 -------- examples/settings.yml | 18 +++---- 4 files changed, 21 insertions(+), 73 deletions(-) delete mode 100644 examples/json_serialization/specification.yml diff --git a/.github/workflows/ghpages.yml b/.github/workflows/ghpages.yml index 5faa6cff..514bfa92 100644 --- a/.github/workflows/ghpages.yml +++ b/.github/workflows/ghpages.yml @@ -30,7 +30,7 @@ jobs: - name: "Install SD-JWT tooling" run: | python3 -m pip install --upgrade pip - python3 -m pip install git+https://github.com/openwallet-foundation-labs/sd-jwt-python.git + python3 -m pip install git+https://github.com/openwallet-foundation-labs/sd-jwt-python.git@danielfett/new-json-serialization # Build the local examples - name: "Build local examples" diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index 8a99a41b..3988b714 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -790,24 +790,14 @@ member of the unprotected header. In case of the Flattened JSON Serialization, there is only one unprotected header. -The following is a non-normative example of a JWS JSON serialized SD-JWT with -Key Binding using the Flattened JSON Serialization: +The following is a non-normative example of a JWS JSON serialized SD-JWT as +issued using the Flattened JSON Serialization: -```json -{ - "payload":"eyJfc2QiOiBbIjR...Aic2hhLTI1NiJ9", - "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", - "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw", - "header":{ - "disclosures":[ - "WyI2SWo3dE0tYTVpVlBH...W1lIiwgIkRvZSJd", - "WyJBSngtMDk1VlBycFR...ImFkZHJlc3MiLCB7InN0cmVldF9", - "WyJlbHVWNU9nM2dTT...VuX25hbWUiLCAiSm9obiJd" - ], - "kb_jwt":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogI...bGUrc2Qtand0In0" - } -} -``` +<{{examples/json_serialization_flattened/sd_jwt_issuance.json}} + +The following is a presentation including a Key Binding JWT and two Disclosures: + +<{{examples/json_serialization_flattened/sd_jwt_presentation.json}} ## General JSON Serialization @@ -816,32 +806,11 @@ headers (one per signature). If present, `disclosures` and `kb_jwt`, MUST be included in the first unprotected header and MUST NOT be present in any following unprotected headers. -The following is a non-normative example of a JWS JSON serialized SD-JWT with -Key Binding using the General JSON Serialization: +The following is a non-normative example of a presentation of a JWS JSON +serialized SD-JWT including a Key Binding JWT using the General JSON +Serialization: -```json -{ - "payload":"eyJfc2QiOiBbIjR...Aic2hhLTI1NiJ9", - "signatures":[ - { - "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", - "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw", - "header":{ - "disclosures":[ - "WyI2SWo3dE0tYTVpVlBH...W1lIiwgIkRvZSJd", - "WyJBSngtMDk1VlBycFR...ImFkZHJlc3MiLCB7InN0cmVldF9", - "WyJlbHVWNU9nM2dTT...VuX25hbWUiLCAiSm9obiJd" - ], - "kb_jwt":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogI...bGUrc2Qtand0In0" - } - }, - { - "protected":"eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImV4YW1wbGUrc2Qtand0In0", - "signature":"oL5lornrs6CFBMu...4HQby6OaaLqAw" - } - ] -} -``` +<{{examples/json_serialization_general/sd_jwt_presentation.json}} ## Verification of the JWS JSON Serialized SD-JWT diff --git a/examples/json_serialization/specification.yml b/examples/json_serialization/specification.yml deleted file mode 100644 index 4820d5e3..00000000 --- a/examples/json_serialization/specification.yml +++ /dev/null @@ -1,21 +0,0 @@ -user_claims: - !sd sub: john_doe_42 - !sd given_name: John - !sd family_name: Doe - !sd email: johndoe@example.com - !sd phone_number: +1-202-555-0101 - !sd address: - street_address: 123 Main St - locality: Anytown - region: Anystate - country: US - !sd birthdate: "1940-01-01" - -holder_disclosed_claims: - given_name: true - family_name: true - address: true - -key_binding: False - -serialization_format: "json" \ No newline at end of file diff --git a/examples/settings.yml b/examples/settings.yml index 5272f14b..b83f41c5 100644 --- a/examples/settings.yml +++ b/examples/settings.yml @@ -7,12 +7,12 @@ key_settings: kty: EC - issuer_key: - kty: EC - d: Ur2bNKuBPOrAaxsRnbSH6hIhmNTxSGXshDSUD1a1y7g - crv: P-256 - x: b28d4MwZMjw8-00CG4xfnn9SLMVMM19SlqZpVb_uNtQ - y: Xv5zWwuoaTgdS6hV43yI6gBwTnjukmFQQnJ_kCxzqk8 + issuer_keys: + - kty: EC + d: Ur2bNKuBPOrAaxsRnbSH6hIhmNTxSGXshDSUD1a1y7g + crv: P-256 + x: b28d4MwZMjw8-00CG4xfnn9SLMVMM19SlqZpVb_uNtQ + y: Xv5zWwuoaTgdS6hV43yI6gBwTnjukmFQQnJ_kCxzqk8 holder_key: kty: EC @@ -23,9 +23,9 @@ key_settings: key_binding_nonce: "1234567890" -expiry_seconds: 86400000 # 1000 days +expiry_seconds: 86400000 # 1000 days random_seed: 0 -iat: 1683000000 # Tue May 02 2023 04:00:00 GMT+0000 -exp: 1883000000 # Sat Sep 01 2029 23:33:20 GMT+0000 \ No newline at end of file +iat: 1683000000 # Tue May 02 2023 04:00:00 GMT+0000 +exp: 1883000000 # Sat Sep 01 2029 23:33:20 GMT+0000 From aeb2ad84db0889396422955e83565e45a47d20fd Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Fri, 8 Mar 2024 16:01:37 +0100 Subject: [PATCH 3/8] Add new example, describe signature handling --- draft-ietf-oauth-selective-disclosure-jwt.md | 13 ++++--- .../specification.yml | 13 +++++++ .../specification.yml | 38 +++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 examples/json_serialization_flattened/specification.yml create mode 100644 examples/json_serialization_general/specification.yml diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index 3988b714..0cd3a0fa 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -778,12 +778,13 @@ unprotected header parameters are defined: Disclosure as described in (#creating_disclosures). * `kb_jwt`: A Key Binding JWT as described in (#kb-jwt). -If a Key Binding JWT is present, the digest in the `sd_hash` claim MUST be taken over -a string built as described in (#integrity-protection-of-the-presentation), -where the Issuer-signed JWT is built by concatenating the protected header, the -payload, and the unprotected header of the JWS JSON serialized SD-JWT using a -`.` character as a separator, and using the Disclosures from the `disclosures` -member of the unprotected header. +If a Key Binding JWT is present, the digest in the `sd_hash` claim MUST be taken +over a string built as described in (#integrity-protection-of-the-presentation). +The "Issuer-signed JWT" part is built by concatenating the protected header, the +payload, and the signature of the JWS JSON serialized SD-JWT using a `.` +character as a separator, and using the Disclosures from the `disclosures` +member of the unprotected header. In case of multiple signatures, only the first +one is used. ## Flattened JSON Serialization diff --git a/examples/json_serialization_flattened/specification.yml b/examples/json_serialization_flattened/specification.yml new file mode 100644 index 00000000..46d685eb --- /dev/null +++ b/examples/json_serialization_flattened/specification.yml @@ -0,0 +1,13 @@ +user_claims: + !sd sub: john_doe_42 + !sd given_name: John + !sd family_name: Doe + !sd birthdate: "1940-01-01" + +holder_disclosed_claims: + given_name: true + family_name: true + +key_binding: True + +serialization_format: "json" diff --git a/examples/json_serialization_general/specification.yml b/examples/json_serialization_general/specification.yml new file mode 100644 index 00000000..3dc5f807 --- /dev/null +++ b/examples/json_serialization_general/specification.yml @@ -0,0 +1,38 @@ +user_claims: + !sd sub: john_doe_42 + !sd given_name: John + !sd family_name: Doe + !sd birthdate: "1940-01-01" + +holder_disclosed_claims: + given_name: true + family_name: true + +key_binding: True + +serialization_format: "json" + +settings_override: + key_settings: + key_size: 256 + kty: EC + issuer_keys: + - kty: EC + d: Ur2bNKuBPOrAaxsRnbSH6hIhmNTxSGXshDSUD1a1y7g + crv: P-256 + x: b28d4MwZMjw8-00CG4xfnn9SLMVMM19SlqZpVb_uNtQ + y: Xv5zWwuoaTgdS6hV43yI6gBwTnjukmFQQnJ_kCxzqk8 + kid: issuer-key-1 + - kty: EC + crv: P-256 + d: WsGosxrp0XK7VEviPL9xBm3fBb7Xys2vLhPGhESNoXY + x: bN-hp3IN0GZB3OlaQnHDPhY4nZsZbQyo4wY-y1NWCvA + y: vaSsH5jt9zt3aQvTvrSaFYLyjPG9Ug-2vntoNXlCbVU + kid: issuer-key-2 + + holder_key: + kty: EC + d: 5K5SCos8zf9zRemGGUl6yfok-_NiiryNZsvANWMhF-I + crv: P-256 + x: TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc + y: ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ From af21774c16e9d388f2ccd809d1705db460803ce2 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Mon, 11 Mar 2024 09:50:41 +0100 Subject: [PATCH 4/8] Clarification proposed by Brian Co-authored-by: Brian Campbell <71398439+bc-pi@users.noreply.github.com> --- draft-ietf-oauth-selective-disclosure-jwt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index 0cd3a0fa..bbc935b2 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -784,7 +784,7 @@ The "Issuer-signed JWT" part is built by concatenating the protected header, the payload, and the signature of the JWS JSON serialized SD-JWT using a `.` character as a separator, and using the Disclosures from the `disclosures` member of the unprotected header. In case of multiple signatures, only the first -one is used. +one is used for the Disclosures and Key Binding JWT. ## Flattened JSON Serialization From 0c5136cf299b1da27fa80274e44ca7df743a7058 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Mon, 11 Mar 2024 09:52:34 +0100 Subject: [PATCH 5/8] Add changelog entry --- draft-ietf-oauth-selective-disclosure-jwt.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index bbc935b2..2ec0b236 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -784,7 +784,7 @@ The "Issuer-signed JWT" part is built by concatenating the protected header, the payload, and the signature of the JWS JSON serialized SD-JWT using a `.` character as a separator, and using the Disclosures from the `disclosures` member of the unprotected header. In case of multiple signatures, only the first -one is used for the Disclosures and Key Binding JWT. +one is used for the Disclosures and Key Binding JWT. ## Flattened JSON Serialization @@ -1743,6 +1743,8 @@ data. The original JSON data is then used by the application. See -09 + * New structure for JSON-serialized SD-JWTs/KB-JWTs to better align with JAdES. + -08 * Make RFCs 0020 and 7515 normative references From cc1f562f009afb2d84b984dca18c711b62f93b1d Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Tue, 30 Apr 2024 17:14:06 +0200 Subject: [PATCH 6/8] Update draft-ietf-oauth-selective-disclosure-jwt.md --- draft-ietf-oauth-selective-disclosure-jwt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index 4b9c729c..9d44c991 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -819,7 +819,7 @@ Verification of the JWS JSON serialized SD-JWT follows the same rules defined in (#verification), except for the following aspects: * The SD-JWT does not need to be split into component parts and the Disclosures - can be found in the respective member of the JSON object. + can be found in the `disclosures` member of the unprotected header. * To verify the digest in `sd_hash` in the Key Binding JWT, the Verifier MUST assemble the string to be hashed as described in (#json_serialization_unprotected_headers). From 57f0284c1cada56a420ce206cf36d1bd18066e97 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Tue, 30 Apr 2024 17:14:42 +0200 Subject: [PATCH 7/8] Update draft-ietf-oauth-selective-disclosure-jwt.md --- draft-ietf-oauth-selective-disclosure-jwt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/draft-ietf-oauth-selective-disclosure-jwt.md b/draft-ietf-oauth-selective-disclosure-jwt.md index 9d44c991..3568fddf 100644 --- a/draft-ietf-oauth-selective-disclosure-jwt.md +++ b/draft-ietf-oauth-selective-disclosure-jwt.md @@ -815,7 +815,7 @@ Serialization: ## Verification of the JWS JSON Serialized SD-JWT -Verification of the JWS JSON serialized SD-JWT follows the same rules defined in +Verification of the JWS JSON serialized SD-JWT follows the rules defined in (#verification), except for the following aspects: * The SD-JWT does not need to be split into component parts and the Disclosures From 88b4608ca9e9cf0086ad4469a8bb658e84a145d5 Mon Sep 17 00:00:00 2001 From: Daniel Fett Date: Wed, 15 May 2024 16:20:04 +0200 Subject: [PATCH 8/8] Switch back to master --- .github/workflows/ghpages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghpages.yml b/.github/workflows/ghpages.yml index 514bfa92..5faa6cff 100644 --- a/.github/workflows/ghpages.yml +++ b/.github/workflows/ghpages.yml @@ -30,7 +30,7 @@ jobs: - name: "Install SD-JWT tooling" run: | python3 -m pip install --upgrade pip - python3 -m pip install git+https://github.com/openwallet-foundation-labs/sd-jwt-python.git@danielfett/new-json-serialization + python3 -m pip install git+https://github.com/openwallet-foundation-labs/sd-jwt-python.git # Build the local examples - name: "Build local examples"