Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define an ISO mdoc profile for Digital Credential API in OIDF/DCP #219

Open
awoie opened this issue Jul 18, 2024 · 22 comments
Open

Define an ISO mdoc profile for Digital Credential API in OIDF/DCP #219

awoie opened this issue Jul 18, 2024 · 22 comments

Comments

@awoie
Copy link
Contributor

awoie commented Jul 18, 2024

ISO/IEC SC17/JTC1 WG10 had an in-person meeting in Korea in late June where a demo of the Digital Credentials API was provided (also including cross-device). WG10 asked OIDF if they can help with the following:

Since the browser API requires the specification of an additional protocol, at minimum WG10 needs to identify requirements for such a protocol.
Ideally, there should be only one protocol.

At the same time, time is of the essence and it was shared that the test event in October 2024 intends to already test and learn from browser API solutions. The meeting agreed to compile requirements for a protocol that runs on top of a browser API, share this with the OIDF, and ask them to expedite the development of their protocol. At the same time, WG10 members can compile a simple protocol (meeting the requirements) for the test event to learn from, to check if the requirements are complete, and to further inform the OIDF work. It was also pointed out that, as with the browser API, if a solution is being developed in another standards body there always is a risk that it may not fully do what is needed.

The meeting identified the following requirements for any protocol that runs on top of a browser API:

  1. Must be functionally the same as the existing (i.e. in ISO/IEC 18013-5 and amendment) device request and device response (i.e. nothing less and nothing more). This specifically includes the following:
  • Device response structure must be included in the response as specified in ISO/IEC 18013-5.
  • Response must be encrypted by the mdoc to a key provided by the RP, and all the details required to have interoperability need to be specified. (Already in B.4.3 of ISO/IEC 18013-7.)
  • To protect against certain phishing attacks, response encryption and mdoc authentication must be bound to the origin, e.g. RP URL.
  • There must be an option for the app to authenticate the key received from the RP to be used for response encryption. Mechanisms to be supported are:
    • Key in a certificate.
    • A key signed with a key that is authenticated by a certificate.
  1. Must be fully specified (i.e. no allowed options that, when exercised in any way, could lead to non-interoperability).

The intent with the “nothing more” requirement is to prevent a situation where the protocol has many options that do not add value for the “mdoc over browser API” case but have to be implemented in order to comply with the protocol specification.

The protocol can have the following features:

  • There can be an option to sign the request.

As a member of WG10 (I'm not speaking on their behalf) and OIDF/DCP, I would support this ask, especially to facilitate harmonization between OIDF and ISO.

Before jumping into the detailed requirements and how to address them, I think OIDF/DCP should think about: 1) are we going to support this ask (I do), 2) and how to address this structurally. Structurally, it could be done in the following way but feedback welcome:

Option 1:

  • try to address the requirements in the Digital Credential API profile Annex of OID4VP directly.

Option 2:

  • keep working on the Digital Credential API profile Annex of OID4VP (allows by design more options)
  • start working on a new ISO mdoc-specific profile for the Digital Credential API that makes choices similar to what HAIP does for SD-JWT VC, and try to address the requirements that ISO WG10 provided. The scope is probably smaller in this case, since issuance and presentation using HTTP-channels don't not have priority for now. The goal is that ISO WG10 can reference this profile in ISO 18013-7 2nd edition without having to define extra things.

Beyond the above, we can think about harmonization between HAIP and this new mdoc-specific profile, especially wrt the Digital Credentials API profile which I assume HAIP will also want to make some choices in the future. But I see this not as something we necessarily have to decide right away.

@Sakurann @jogu @tlodderstedt @martijnharing @tplooker @paulbastian @GarethCOliver @davidz25 @sbahloul

@tlodderstedt
Copy link
Collaborator

Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?

@awoie
Copy link
Contributor Author

awoie commented Jul 18, 2024

Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?

What is required for the ISO mdoc-specific part is really just defining the SessionTranscript which is the "thing" that gets signed by the VP. This is essentially just defining where to put origin and other params in the SessionScript. This handover has to be done for SD-JWT VC and other credential formats as well.

@tlodderstedt
Copy link
Collaborator

what about the ISO specific identifiers and so, just what constitutes a profiles.

@awoie
Copy link
Contributor Author

awoie commented Jul 18, 2024

Is this limited to DC API profile? I'm asking since underneath there most be a OID4VP for mdoc profile. Would this then be done in the DCP WG, too?

What is required for the ISO mdoc-specific part is really just defining the SessionTranscript which is the "thing" that gets signed by the VP. This is essentially just defining where to put origin and other params in the SessionScript. This handover has to be done for SD-JWT VC and other credential formats as well.

It is a DCP WG decision if the requirements from the ISO WG can be included in the OID4VP DI API Annex already.

@martijnharing
Copy link

Hereby a proposal for a profile that addresses the request from ISO SC17/WG10. It defines all details necessary to have a successful interaction when the wallet and relying party implement the mandatory requirements of this profile. The profile has been designed to implement the requirements applicable to the openid4vp protocol for the digital credentials API as defined in annex a.

One of the open tasks before making a PR is to make sure it's WebIDL compatible. Making it WebIDL compatible could require making changes to the proposal.

Request object
This contains the Authorization Request dictionary.

It MUST have the following two elements:
vp_query_info (string)
response_encryption (string)

It MAY have the following element
verifier_authentications (array/sequence)

These elements have the following definitions:
vp_query_info
This is a new parameter for the Authorization Request.
This element contains the new query language. To support request signing, the value of this element MUST be BASE64URL(UTF8(vp_query)) where vp_query is the structure as defined in #vp_query.

response_encryption
This is a new parameter for the Authorization Request.
This element contains the elements needed for response encryption. To support RP authentication, the value of this element MUST be BASE64URL(UTF8(response_encryption_parameters)). Where response_encryption_parameters is defined below.

response_encryption_paramaters
This dictionary MUST contain the type, nonce and jwk parameters and MAY contain the verifier_authentications parameter.

type is an element that defines the response encryption type, for this profile the value MUST be “mdoc_profile_encryption_1”.
nonce is the nonce as defined in section 5.
jwk contains the response encryption key of the verifier, the value MUST be a jwk as defined in RFC 7517.

verifier_authentications: This is an array of verifier_authentication. If present, it MUST contain at least one verifier_authentication.

verifier_authentication: This is an array that MUST contain two elements, type and value.
type is an element that defines the response encryption type.
value is an element the type dependent element that contains the verifier authentication information.

An example for verifier authentication are:
type: “verifier_authentication_example”
value: jws with detached signed data being the response_encryption_value

type: “request_signature_example”
value: array of two elements.
First element is base64url(utf8(client_info)), where client_info must contain expected_origins as defined in [xx] and MAY contain client_id and client_id_scheme.
Second element is a jws with the detached data being the concatenation of the first array element, vp_query_info and response_encryption values.

Response

The response structure is a dictionary that MUST have the following two elements:

type (string) is an element that defines the response encryption type
value is a type dependent element that contains the encrypted response

For this profile, type MUST be “mdoc_profile_encryption_1”.
For this profile, value MUST be a structure with two elements:

jwk contains the response encryption key of the verifier, the value MUST be a jwk as defined in RFC 7517
encrypted_data this contains the authorization response containing the encrypted authorization response as BASE64URL(UTF8(authorization_response)). The authorization_response MUST contain a single element vp_token. The vp_token contains the base64url encoded DeviceResponse as defined in 18013-5.

Note 1: It is still to be defined how the RP knows how to decode the elements in the vp_token array since that may be part of the update on the query language. Currently, this is implicit through the use of the profile parameter.
Note 2: The presentation_submission parameter is absent as that's part of the update to the query language in a different issue.

The value of the encrypted_response shall be calculated by taking the CBOR encoded DeviceResponse and encrypting it with HPKE (RFC 9180) with the following parameters:

Mode: Base
KEM: DHKEM_P256
KDF: HKDF_SHA256
AEAD: AES_128_GCM

The keys used are the Verifier and RP response encryption keys in the respective jwk elements.
The HPKE info parameter is the cbor encoded SessionTranscript.
The SessionTranscript MUST have the following structure:

SessionTranscript = [
  null,
  null,
  [
    "browser_handover_v1",
    response_encryption, ; the string from the request
    Origin ; this is a tstr containing the domain of the website making the request
  ]
]

@tlodderstedt
Copy link
Collaborator

@martijnharing thanks for sharing your proposal. I have to admit I don't understand how it fits into OID4VP. Can you please share request and response examples?

@jogu
Copy link
Collaborator

jogu commented Aug 6, 2024

@martijnharing just to follow up on the conversation in today's WG call, there's an example request that requests an encrypted response and has verifier authentication via the browser API here:

https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.3.2

and the response just comes back as an encrypted JWE as per the second example here:

https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.4

It's probably not super clear (for brevity the actual signed jwt request and encrypted jwe aren't shown in full), and the request for encryption is a combination of the response mode with jwt and the jwks with a "use": "enc" key - do let us know if it's overly confusing.

@bc-pi
Copy link
Member

bc-pi commented Aug 7, 2024

@martijnharing just to follow up on the conversation in today's WG call, there's an example request that requests an encrypted response and has verifier authentication via the browser API here:

https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.3.2

and the response just comes back as an encrypted JWE as per the second example here:

https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#appendix-A.4

It's probably not super clear (for brevity the actual signed jwt request and encrypted jwe aren't shown in full), and the request for encryption is a combination of the response mode with jwt and the jwks with a "use": "enc" key - do let us know if it's overly confusing.

As I tried to acknowledge on the call yesterday, I suspect it is rather confusion for someone coming to this without familiarity with the many layers of OAuthy stuff that's been built on here. And effectively a first draft at a profile for the W3C Digital Credentials API that is building further on that. But as @jogu says, a request for encryption is conveyed with with a response mode of w3c_dc_api.jwt and the jwks with a jwk with a "use": "enc". The resulting response with be JSON with a JWE as the value of the "response" member. And verifier authentication is achieved via signing the request (as a JWS/JWT that then is a member of the JSON request). Yes there's requests layered on requests and responses in responses. But that's the bed we've made for ourselves.

@martijnharing
Copy link

martijnharing commented Aug 9, 2024

Hereby an example, all the cryptographic structures should be correct as well

Static RP key:
  x: f8912ee0f912b6be683ba2fa0121b2630e601b2b628dff3b44f6394eaa9abdbc
  y: c2149d29d6ff1a3e091135177e5c3d9c57f3bf839761eed02c64dd82ae1d3bbf
Ephemeral RP key:
  x: 60e3392385041f51403051f2415531cb56dd3f999c71687013aac6768bc8187e
  y: e58deb8fdbe907f7dd5368245551a34796f7d2215c440c339bb0f7b67beccdfa
  d: de3b4b9e5f72dd9b58406ae3091434da48a6f9fd010d88fcb0958e2cebec947c
Ephemeral device key:
  x: 5a88d182bce5f42efa59943f33359d2e8a968ff289d93e5fa444b624343167fe
  y: b16e8cf858ddc7690407ba61d4c338237a8cfcf3de6aa672fc60a557aa32fc67
  d: c1917a1579949a042f1ba9fc53a2df9b1bc47adf31c10f813ed75702d1c1f136
   
    const credential = await navigator.identity.get({
        digital: {
            providers: [{
                protocol: "openid4vp",
                   request: {
                       "vp_query_info": "eyJjcmVkZW50aWFscyI6IHsiYSI6IHsiZm9ybWF0IjogIm1zb19tZG9jIiwgIm1zb19tZG9jIjogeyJkb2N0eXBlX3ZhbHVlcyI6ICJjb20uZXhhbXBsZS5pZCJ9LCAiY2xhaW1zIjogW3sibmFtZXNwYWNlIjogImNvbS5leGFtcGxlLmVsZW1lbnRzIiwgImNsYWltX25hbWUiOiAibGFzdF9uYW1lIn0sIHsibmFtZXNwYWNlIjogImNvbS5leGFtcGxlLmVsZW1lbnRzIiwgImNsYWltX25hbWUiOiAiZG9jdW1lbnRfbnVtYmVyIn1dfX19",
                       "response_encryption": "eyJyZXNwb25zZV9tb2RlIjogInczY19kY19tZG9jXzEiLCAibm9uY2UiOiAiYXZvRFVWV1FvV2VQbmk2RzQ1UGZXQSIsICJqd2tzIjogeyJrZXlzIjogW3sia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIllPTTVJNFVFSDFGQU1GSHlRVlV4eTFiZFA1bWNjV2h3RTZyR2RvdklHSDQiLCAieSI6ICI1WTNyajl2cEJfZmRVMmdrVlZHalI1YjMwaUZjUkF3em03RDN0bnZzemZvIn1dfX0",
                       "verifier_authentications": [
                           [
                               "verifier_authentication_example",
                               "eyJhbGciOiAiRVMyNTYiLCAieDVjIjogIlZHaHBjMmx6Ym05MFlXTmxjblJwWm1sallYUmwifQ..iXpUwMEe9SpQilW6JJrl999Ev_efw7t7lDpJ45f9G8UvBKoEOv5LMef7jpr4HaOB-dK-iz5iCyi5bWpeLN3r8A"
                           ]
                       ]
                   }
            }]
        }
    });
    

where vp_query =
{
    "credentials": {
        "a": {
            "format": "mso_mdoc",
            "mso_mdoc": {
                "doctype_values": "com.example.id"
            },
            "claims": [
                {
                    "namespace": "com.example.elements",
                    "claim_name": "last_name"
                },
                {
                    "namespace": "com.example.elements",
                    "claim_name": "document_number"
                }
            ]
        }
    }
}

where response_encryption_parameters =
{
    "response_mode": "w3c_dc_mdoc_profile_1",
    "nonce": "avoDUVWQoWePni6G45PfWA",
    "jwks": {
        "keys": [
            {
                "kty": "EC",
                "crv": "P-256",
                "x": "YOM5I4UEH1FAMFHyQVUxy1bdP5mccWhwE6rGdovIGH4",
                "y": "5Y3rj9vpB_fdU2gkVVGjR5b30iFcRAwzm7D3tnvszfo"
            }
        ]
    }
}
Authorization response:
{
    "encrypted_data": "hJCzPYw8X3e-uqM1l-XPmXOvsUYMTq4NlfruMBZeA-TXUraPUlao4CJzi4zR-HGV7pKZZr1H6txdWXtTjNdOw_n2bO5Ojj_s4H4HgGqRMo_L85NAFRTixzPhzCweZPgIBzWLh81njj3x-C5KnyDgbnLbEfJXaVYp6KRQteXnj15Jj6heD4FTOsIDiIBaHeNGe7wSPTEbsnvI3MCnkw0RZza3bVW2u0HNVDKV2VNCH0XRTNrnuctkuVZwtBhm7EZSqkUNsGajZ65w9E7HGUu_9MlhYl2p_ft6fLaijnrj60m-deIoj7S_DHS5WDa3QpY9gPbIhYFWFiJqYWF9gTzcyD90QA6uEvjkGfgnVPi1EwPSgHLfhcRrWdJ6RVSGoHrDUQH6mTs5uoWn6ysJj0TQ7BG-zIyrIP-9owgNN4UMeihCyMtq91v6DKbzvhg6rH0IhVLjj3h9x1hha6KcNv0ySSeW7s6lgaNGqIxmE1I21FAUowfAgpZOT9_kjOq-EwnBG31xF3w8DHwJlcm2bm5E7RevSHoTodSbAthMg2K32AvXAKQo14uf3J32rl-AbsHhi2TzHFrdL8IuSbH4XamdOGJxBKgUVL6xjrjlvnGC9W7ZSGa4cTPyx0iYBMMTmhll0rivxACXqjZveGnw51WHDJm5i9xhZli1MC0hGdCHcn_eFdCXI2IQ8YFdhTDvv9btvNHLkAmOSZhQpeXlSWIPoz20NKZ9Lk565uUQakMXILaHYtnzI--1h-M34gvO7EODDjPzh9X7WhnE-_nvPmMs46Dnuhmi7Z0eSzT8wOX8f67BYyFwDEepyXDMg0XlJ8555GeQxOcLBpVUCEkLl1xuC0LG40qPNP-tyHc2zXXAU5tLpKQb2tLiK_ksSuw9wM5xtjCBNSzcorS1P97FTTqI4f8ly-ZYIPX85WTSEDpaaTzF1Fvpl_JfOjL06ZTZbtf4JnC0-biVFpu-5TMTHEQFa-ve_nMCftxR7YIh3ByxYzoLok0jRT7ntgnAhQSO8xP3jtPoFT3sLHw9t-cEzxQ7j-CkrSqHh1h2-vJsnJWQhtvN65LeehyKFRlxh7KZ6H66PbnlZlhnLlLcdu94FMa1XPj0OvWbpJHZ-jkJZJu9NhaIcUgQZC1CmZ69lDZGxHoE2OjrdIJ58Y3k-mnGL4hVehUjJCJMzj5RpoUUeEDggGBPm_lc-ePf2gEIXqUaCikuxSiZ7uDfxCv2c0izoFGrMVY-Fx3KarQpGhs4QutQAxin1hahqvtx-IVwBI1FzaKNTU7oqI-4vNVl4lFu-IRQ5ofG1uYpyBgOfGNp4L_i_YhgTh_Gp0_HL4VkyhsW_8l9ZgD2SomPyMOFw5TL90PPTO55hf4Q6w0lVOK81SgvwTHaAzqtDJaNC07inTLGzO6erxjZiOIB6V1T9-dA46PsDUm98vzpR2JHK2jGNvVb6VnrgC-Ej7Fkco2Kz8IoY6iMNaOaA-XZgRiYRTdpdLeZvMK24JoLzdZMZQLkyRqM2PofsD5wvSU6HnDR7-eOFw-F09nc7HDlMoiI_NVb2gWja0KAk8Njxdeg4K5vdtjWbwOZyskSw_8iFfW10RWHq4MUbp-XcxpyO6yg_RTzE-0CALyDo7-BM91CJRYCkg__Bdy1I89e9HkbemN-n3oozbqd0nj1YuquFaqT8nZtqp3LDQS1zEdMyFB5z3Z6gSIfOKizE0AyVeiuefUJI6EuulPMYrNlsrRMFa2XQyQjjlSwcVJ7FV2_3p-WEY1anfVcz2-my3LA05mztbVQUaYUl-K48FGpJa6PGpB2UvoPFrd5wgVajwtvqOoZr2skOpOuJIX-iRobgR4wQVs1Sgm89NaOegW_uDWjv9OQhCRRSicoTtG4-DVBPKNPk3ZTprNf7czkI-FnuT8ujbZfSRSNLZUPc_wRovgChH-GYIE7IlCQwN4pZZzFP8mzx7buM8YUicbl5wxEK4PcVQcObgYroyghM9LtcVC3izJYiYaKlEaCfF8M5zdw7bET3CPr8X0XvUmsPon4Kp6iur1tAC7O-W8ptC9xf-2UOm_hR42nFN6B6eKMhmAFNH2D05nY-cPckT511RKYh-RH3xaMMMt6jUtkozsvKbmBfihZkCqUEjf84v0-Z4sUx9ufE5U1Hg_BLpfeFcGMno4nWGZ9hED3UTNxXR-QyXYb71ObVcfPWaogVb48R_OOceaV-PloOwkttDE9x-pqv2XK7jXhL44gk08rV1p6DoknXr90lnG24lXc6Y9dTPwEPI3w67_uBcaEEo6rfMEEJOcl--tYQ0-lqf30WKnfqc61QBazI3xqvHxEKG-lJQDR-C4QGE7GLkRIQVLRAeC8WO0ANwE9E9cbapN-3OapdGbZU0EEyxvU9DySgp8acjRV_VWFeTSYmLIXZsoxGMoqkTi_xLOWFe3CIzcYnTVpt92LuKY0He4-aQoiMZrHGXHhI2yqiepIvQKJDexi-4r16guKYSM5ancro-41EUZfe6WWT4LlmQcsM2xKrrW1674LfdhoFlB9ZCj_AfRTzWCq79FPpx6q6BkTzqKv8uLO3r2FGvg4V4xhOyj7gu2V-en_Rvcvc8EL_SnHW_rnFMBV1OFcbkwj4AND7C2P_rq6-wRzVTEQc3R-hAZMyihnT-KksQr8hUbWolvGp5lL4jpAc1j73SARHg2y2-QCBmyt29oQOaqSGDm0KWFdFqNpMAgguo1_jAQhhow3n6XFVSjQDJ_VIfe15nev1qEji2vjv7can_gEMs9kzY16a7h-flqX7PBdQ07UGr9Bt1d9uCPXCt9_QvaoZAbq4zNT7FXhntxGZf72Fx8Esz0kaPKWu6dodnDFUZllWhb6AnPbHJ29hwQ3rIKwrwlGLKbq7pewgzxgoFIhisWvP2N2rn03I9BoQZItWYc6Ca5BCW0MoNYJXnpktbGYF-WB10UaSaiarw4FsXU6rn_z1k2wU6juHANN8y_M7TkGxpxgt1G0MZLwIE_LGqPH_cW68YyH5DNQqOSSQDKjqfvCXdyE0S8s69sWC45fEnHt4tq5lbFFmgU_ooq9BKjMmktDPy9y9RAVLFP0veQGLv0JSIaWiJPpvelva0RA1aRyNnObzqEY9NI7O5fkBjK92xgXs-XOhJ8TMQrWtsWNgld8KBPXiLCrU4cbd41Sae8U-EOwA1Qerdt8LmoPkXB_aFvvzoBozCbM-X6mLvqCsC7v7tdUkwALFN0DuCTGWde-JhDWEUohm62mN8U8vXD5gCVOXRhlWFtC5hBNk0MV7Lb6E8c5D8cuAkItqUEgUI_P-RL5ESQ_lrsSYhmubdpAEx_s2zyhNvUTFfskonRrP4cMWH4ogxeiX-ryl7P5-9vkhoBy91k18U8K8ADtJZDLIM1n8OVSXgP_RknfwEcNTZVrSPdJYrjl7S7cR4Nn6abnbaGvADvK9u4F2aGVPwMAAsSgJt2qDbrBBpzxxaI1ttbLwTzGdy-e2AHdlVvqpMLMAUw99F47hnoq11rjI2tbpkjA3NUUpGSPhRfE_x0zRee13RJ9dBy6zLue1RZQYPC8otP1DvIwDC2yo98-8-WhAIcd5aK_s0DFbt3VpjYpNzuGZpRsUfFGijf-mp-KK3c1oK4QZkre5XrS4OprM3BI97AdL9WsC0ixtqEGVdVhTpbJD2oncbeXXc2mnSF5-8hhEQMcL7wcRezFbrK3yP2orKt_FXQG-yuApHBlNLJn0tmzz1NVNevG7BRmeU0Nr2Goi2nHTkoFjKS-_zcXEqq7q0PXtV77E_1o_d-YsFg0L91cSkyMN83FhJNsmz9EQr7ajNmEJVVZEEFfZcnk0ZZkwqjWfTtFCa6N5hX4buoeC-OF_qp__69Vll-VTPiV4QEsFB_cAce_air_ouwV8Pg4SeManNWEIfQ60fmJLe8NVX8rZp6X6m0iI3lqRqDXfYPgLHF_vjXPINE80Ng",
    "jwks": [
        {
            "kty": "EC",
            "crv": "P-256",
            "x": "WojRgrzl9C76WZQ_MzWdLoqWj_KJ2T5fpES2JDQxZ_4",
            "y": "sW6M-Fjdx2kEB7ph1MM4I3qM_PPeaqZy_GClV6oy_Gc"
        }
    ]
}

where encrypted data contains:
{
    "vp_token": "o2d2ZXJzaW9uYzEuMGlkb2N1bWVudHOBo2dkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGxpc3N1ZXJTaWduZWSiam5hbWVTcGFjZXOgamlzc3VlckF1dGiEQ6EBJqEYIVkB9DCCAfAwggGVoAMCAQICFCuL9vlL42zupOgdrQ3xCJSsYjxrMAoGCCqGSM49BAMCMCMxFDASBgNVBAMMC3V0b3BpYSBpYWNhMQswCQYDVQQGEwJVUzAeFw0yMDEwMDEwMDAwMDBaFw0yMTEwMDEwMDAwMDBaMCExEjAQBgNVBAMMCXV0b3BpYSBkczELMAkGA1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASs56tzQOXZZIxacqmm9WdFx6rUNqA6Q-_qd7X6e4jwGX1X2Jg-GzfTpTn01Yg2XjjLv1uU1oxUe1vIcx3NLxRro4GoMIGlMB4GA1UdEgQXMBWBE2V4YW1wbGVAZXhhbXBsZS5jb20wHAYDVR0fBBUwEzARoA-gDYILZXhhbXBsZS5jb20wHQYDVR0OBBYEFBTikBemw1Yh_8emhre3LbBs0SNRMB8GA1UdIwQYMBaAFFT6I4OgTCjg2TB5ImHIDEiB0sALMA4GA1UdDwEB_wQEAwIHgDAVBgNVHSUBAf8ECzAJBgcogYxdBQECMAoGCCqGSM49BAMCA0kAMEYCIQCPHnIhN9_eBeeRP2I9xjml04mTm7T2aTZ_OQlYDPcv8wIhAOKOLn7UGjZX4Gy5XC4pIduJPs9c1RB-CnxICD0pXbAfWQVu2BhZBWmmZ3ZlcnNpb25jMS4wb2RpZ2VzdEFsZ29yaXRobWdTSEEtMjU2bHZhbHVlRGlnZXN0c6Jxb3JnLmlzby4xODAxMy41LjG4GQBYIHUWczO0e2wr-4bszB9DjPV68FU3GsVeHjWeIPJUrc6_AVggZ-U51hOevRMa70QbRFZF3YMbKzdbOQyl72J5sgXtRXECWCAzlDct23gFPzbV2Gl4DmHtoxPUSjkgkq2OBSei-_5VrgNYIC41rTxOUUu2exqdtRznTky5txRuQaxS2snOhrhhPbVVBFgg6lwzBLt8So3LUcTBO2UmT4RVQTQTQgk8ynhuBY-sLVkFWCD65If2i3oOh6dJd05W6eHcOo7Ht35JDSHw4dNHVmGqHQZYIH2D5Qeud9uBXeTYA7iFVdBRHYlMiXQ59XdAVkFqHHUzB1gg8FSaFF8c91y-7_qIHUhX3UONYnzzIXSxcxxMOOEsqTYIWCC2jIr8sqr3xYFBHSh33vFVvi6xIaQrybpbcxI3fgaPZglYIAs1h9HdDCoHo1v7Eg2ZoKv7XfVoZbt_oVzItWpm324MClggyYoXDPNuEau3JOmKdaU0PforbtPfLs-7jvLuVd1ByIELWCDsVuZg__vpiaCSRiQUKbeqYrgZgNIK7Pz6L7iK1B-1bQxYIBmXqvlCy2RUcXF1b5flYwz5CpTPI7yo-dYvqmal-2EcDVggb3eIRkKaG1fS6s__VKpacTsXXepM8SufQZr61hwl2r8OWCDP9AYLGK5pE8C5VkVfare7Shw6sAeXmAStqag0jdhGYw9YIDQDz7_Er-dI2axeIiReMvIzVYre0AS9CjjEaUJc5RjCEFggzuXafEWluj70StratJsExBGghXvX25HWtNjewzu1deARWCD5Tf2xEcc34dyzGno8v0l0coMWmgC0x4UtM3mS1x48qRJYICK-wbv-pZhZLArhZ4e9IWBxRYlY7ijbCiJ1qr_xQQQdE1ggNaiui6IgCQFr5OS-vuZPeMRAWsLvzZkonD1mXdnwKMAUWCDtzy20bxYGvq_cWHbkWTqTcLKgZkH6_qBwoXwKAgwfohVYIHbQll4QKja4ZuE4tch70zpQiwg37SZS7jUqWHNsa_lwFlggiXl2t2g5LJ1XYJBbpKjaMRKMtbZmWGW_0JEGI8tv4JoXWCCoG12PCgIJMdeqrf1-bbIKBux7JIZiN1ftZNuA1Xoe1xgYWCAIhVIAFVhiBJtTDRh67JtT5c4A9VChpN3vmbhpx0Z_jHdvcmcuaXNvLjE4MDEzLjUuMS5hYW12YaUAWCDWdov_0Gyf252joOY6Dt6_xPk81uDBEt3xBdCmw0EzLAFYIFjUqmvOEx_IiPQxPiKHEHkn4pGaV37iMTi_tkTYjRriAlggng1UErwg85HQzPagMREWYQ8veffxoWSR0qvkawPc5xMDWCAcqVIOi7o_Bbr67etasEXQN7LApg1sV_tT6a6ylfn-BARYIDrmBbcfq-7XzSYZWAvJ3KdqXxDEC_iTlowfMLfTwmOTbWRldmljZUtleUluZm-haWRldmljZUtleaQBAiABIVggljE9bGPiTjNydCv9saM7osiX3NaKuMdT5PvUjcprf5oiWCAfsyae3UGIV94bOaTkpEuS-khMqnIsIoKI8B0MA6LD1mdkb2NUeXBldW9yZy5pc28uMTgwMTMuNS4xLm1ETGx2YWxpZGl0eUluZm-jZnNpZ25lZMB0MjAyMC0xMC0wMVQxMzozMDowMlppdmFsaWRGcm9twHQyMDIwLTEwLTAxVDEzOjMwOjAyWmp2YWxpZFVudGlswHQyMDIxLTEwLTAxVDEzOjMwOjAyWlhAtrMhx1htTWhEQlOQBoLxRghQbBGnoOGH4rRmGAdhwfjqtFlrm2jbhm1GFRkGYzSqVKanHE7gr3fPWkGjluFvlWxkZXZpY2VTaWduZWSiam5hbWVTcGFjZXPYGEGgamRldmljZUF1dGihb2RldmljZVNpZ25hdHVyZYRDoQEmoPZYQCLmcjhi89rHd_VJx4IDDapRgaioeNK4xrpB61cN12AAdAmGcnzj-keTFP4Cu4c94h84m54GrhBUjiEFdS1kUnJmc3RhdHVzAA"
}

Based on the comments a few changes are made:
Instead of using a jwk, a jwks is used. Since only a single key is present, I couldn't find a hard requirement that "use"="enc" has to be present, so that's left out for now.
The response_mode was left out in the original proposal since the two response modes defined in A.2 (w3c_dc_api and w3c_dc_api.jwt) both do not apply but leaving it out defaults to 'fragment' which is also not accurate. Therefore the response_mode parameter is used to indicate the profile that's used, the naming of that type is changed to be in line with the parameters currently defined in A.2.

This example uses the updated request structure that's currently under development. It also uses the 'verifier_authentication_example' mechanism, that allows to authenticate the verifier (through its key material), without needing to sign the full request (including the vp_query), which was discussed at IIW as one of the mechanisms to be supported.

@jogu
Copy link
Collaborator

jogu commented Aug 12, 2024

Hi Martijn

Thanks!

It might be worth thinking about how we progress this. In particular I think it's likely that anything that isn't mdoc specific (e.g. adding a new way to authenticate the verifier) should be split out into a separate issue that can investigate if that mechanism should be added to the browser API appendix and/or the core of OID4VP.

I'm not clear why response_mode=w3c_dc_api.jwt can't be used here, but if we need changes to response modes that should probably also be handled separately.

The mdoc profile itself should only build on top of what is already in the rest of the standard, specifying how to use the existing standard with mdoc - i.e. not specifying new behaviours unless they're dealing with an mdoc-specific problem.

@martijnharing
Copy link

Thanks for the suggestion, indeed if there are parts of the requirements and definitions that are in the profile proposal that instead should go in the browser-api annex itself then that's of course just as good (or even better). In order to make a concrete separate issue, which parts of the profile should those be exactly?

On the response_mode, the current text says:
"The value of the response_mode parameter MUST be w3c_dc_api when the response is neither signed nor encrypted." Since the response is encrypted, this requirements does not apply. The next part says:
"and w3c_dc_api.jwt when the response is signed and/or encrypted as defined in [Section 6.3]."
Most requirements in section 6.3 seem to be not applicable since [JARM] and section 6.3.1 define response modes that are all either using redirects or posts to transmit the response (i.e. none of them use the w3c_dc_api.jwt response mode). But since section 6.3 does talk about encrypting the response, one way to interpret this requirement is to say that it effectively means something like "whenever you do encryption (or signing) of the response, the response_type value MUST be w3c_dc_api.jwt". If that's the case then we can change the response type value to w3c_dc_api.jwt in the profile text and separately add back the response encryption type parameter “mdoc_profile_encryption_1” for this profile that fixes all the hpke encryption parameters to a single choice.

@Sakurann
Copy link
Collaborator

In order to make a concrete separate issue, which parts of the profile should those be exactly?

vp_query_info, response_encryption, response_encryption_parameters, verifier_authentications, type, jwt, are all features that duplicate existing openid4vp features and should be separate from mso_mdoc profile of the browser API profile of openid4vp.

sentences like The vp_token contains the base64url encoded DeviceResponse as defined in 18013-5. is what we would need in mso_mdoc profile I think.

JARM is defined separately from any redirects, so w3c_dc_api.jwt is the response_mode to use when returning encrypted responses over the browser API.

@Sakurann
Copy link
Collaborator

Sakurann commented Aug 13, 2024

Discussed in a WG call, agreed that next steps are to go back to smaller questions that led to the proposal such as those below (not capturing all of those, and my wording might not be accurate):

  • how to pass an encryption key in a trusted way in an unsigned request? (@tplooker pointed to Wallet-provided nonce  WICG/digital-credentials#92)
    • might need to clarify more on based on what wallet "trusts" the request from the verifier.
  • what JARM response mode to use to return encrypted response over the browser API.
  • what if verifier wants to pass multiple trust models, hoping one is supported by the wallet?

so that we can start clarifying things in the spec for things that are already defined but are not clear enough.
@martijnharing feel free to open new issues for those items that you already know would require a dedicated discussion. if not sure, feel free to start by posting in this issue.

also discussed that these things probably need to be fixed in general in the spec (outside the mdoc profile)

@martijnharing
Copy link

Hereby some further explanation for those questions, some possible ways forward and explanations for the choices made in the proposals.

For item 1, "how to pass an encryption key in a trusted way in an unsigned request".

This is mentioned in the WG10 ask as:
"There must be an option for the app to authenticate the key received from the RP to be used for response encryption. Mechanisms to be supported are:

  • Key in a certificate.
  • A key signed with a key that is authenticated by a certificate."

This means that we need to authenticate the information used for response encryption and transaction security. In the context of OpenID4VP, this includes the jwk for response encryption, the response encryption cryptographic requirements (e.g. algorithm, encryption profile etc), the nonce, and (if present) the expected origin.
The structure (or structures, see also the next item) that contain this authentication information needs a mechanism (e.g. type) to indicate which information is being authenticated in order to build up the correct structure to be signed.

The proposal does not use JAR for a few reasons, an important one being that JAR requires the full structure to be signed. This means that it's not possible to only sign the response encryption information (i.e. the query-language structure must always be signed as well).

In the proposal the authentication is done by signing the "response_encryption_paramaters" structure. This intermediate structure was used to facilitate signing the correct information but means a regrouping of the OpenID elements like nonce and jwks, which is not the preferred direction as indicated by the group. The other downside of this approach is that it this doesn't work well with the requirement for the elements to be encoded as WebIDL elements.
The solution that would likely address all of these concerns is to require a form of JSON canonicalization before creating and verifying the signature. Is something like RFC 8785 a possible solution for such an approach?

If that's possible, we can include the values of nonce, jwks, response encryption parameters, client_id, client_id_scheme, the response encryption parameters and the vp_query directly in the data to be signed structure for the verifier_authentication structure. This would also mean that we can include all of these parameters in the same way as is currently defined for the authorization_request, instead of needing the 2 new vp_query_info and response_encryption parameters.
For the verifier_authentication structure, the type element in the verifier_authentication structure would determine which of these elements must be included in the signature calculation, in order for the wallet to be able to verify the signature.

Issue#92 was mentioned, but that seems to address a different issue than the problem of authenticating the encryption information.

For item 3 "what if verifier wants to pass multiple trust models, hoping one is supported by the wallet?"

This is implicitly mentioned in the WG10 ask since the 18013-5 request structure supports multiple RP authentication signatures.

Not having the ability to support multiple RP authentication signatures would mean that it's not possible to request documents that use different trust models, or request documents from issuers (e.g. regions) that have different trust models. Not having those abilities would be a significant limitation of the protocol.

Most of the consequences and possible solutions are similar to the ones mentioned in item 1, since having multiple RP authentication signatures seems to not be supported by the JAR specification.

The proposal addresses this by defining an array of verifier_authentication elements, each of which can contain a signature for a trust model. As the elements that are signed by these structures is dynamic (see item 1), this mechanism supports both the scenario of signing the encryption information, as well as also signing the vp_query.

For item 2, "which JARM response mode to use to return encryption response over the browser api"

Annex A mentions that "[..] w3c_dc_api.jwt when the response is signed and/or encrypted as defined in Section 6.3."
Section 6.3 then mentions that JARM MAY be used to encrypt the authorization response. The JARM specification itself specifies response modes that use redirects or form_post. Section 6.3.1 defines the direct_post mode, which uses an HTTP POST mechanism. So none of the JARM response mode mechanisms in section 6 seem to be applicable.

If the intention of Annex A is to use the JARM specification, but to use a different response mode mechanisms that uses the browser api for transmission, we would also have to address a number of requirements in the JARM spec that are either not applicable or can have adverse effects in the context of using the browser api.
For example, JARM requires the aud element to be present and match the client ID, while Annex A requires that the client ID must be omitted when the requset is unsigned.

The proposal performs the response encryption using just 2 parameters in the response: the key used for encryption and the encrypted blob itself. Using the optional JARM mechanism to provide the encryption would mean duplicating algorithm information (e.g. the exact HPKE mode, the encryption profile) which seems to result in a more complex structure to implement and verify than what's currently proposed.
The proposal also defines a response mode parameter that defines both the encryption algorithm to be used, as well as how what parameters are included in the response encryption, e.g. what the contents is of the info parameter of the HPKE operation.

@bc-pi
Copy link
Member

bc-pi commented Aug 20, 2024

Apologies @martijnharing, some of my inability to understand the resistance to JARM and attachment to HPKE in this issue came through at the end of the call when the different #216 was being discussed. Hopefully the clarifications that @selfissued offered to make there will be helpful in this context too.

@tlodderstedt
Copy link
Collaborator

This proposal is based on a discussion with @jogu @martijnharing @awoie @danielfett @bc-pi:

We would like to omit canonicalization of the request, that's why the basis of the proposal is to use the multi signature feature provided by the JWS JSON Serialization.

The OID4VP request

{
  "expected_origins": [
    "https://origin1.example.com",
    "https://origin2.example.com"
  ],
  "response_type": "vp_token",
  "response_mode": "w3c_dc_api.jwt",
  "nonce": "n-0S6_WzA2Mj",
  "client_metadata": {
    "vp_formats": {
      "vc+sd-jwt": {
        "sd-jwt_alg_values": [ "PS256" ],
        "kb-jwt_alg_values": [ "PS256" ]
      }
    },
    "jwks": {
      "keys": [
        {
          "kty": "EC",
          "crv": "P-256",
          "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
          "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
          "use": "enc",
          "kid": "1"
        }
      ]
    }
  },
  "presentation_definition" or "vp_query": {}
}

would not contain client_id and client_id_scheme. It would be put into the payload element of the JSON Serialization structure.

    const credential = await navigator.identity.get({
        digital: {
            providers: [{
                        protocol: "openid4vp",
                        request: {
                          "payload": "eyAiaXNzIjogImh0dHBzOi8...NzY4Mzc4MzYiIF0gfQ",
                          "signatures": [
                           {
                              "protected": "eyJhbGciOiJFUzI1NiJ9",
                              "header": {
                                "client_id": "987647789",
                                "client_id_scheme": "x509_san_dns"
                              },
                              "signature": "PFwem0Ajp2Sag...T2z784h8TQqgTR9tXcif0jw"
                          },
                          {
                              "protected": "eyJhbGciOiJFUzI1NiJ9",
                              "header": {
                                "client_id": "https://rp.federation.eu",
                                "client_id_scheme": "entity_id"
                             },
                            "signature": "irgtXbJGwE2wN4Lc...2TvUodsE0vaC-NXpB9G39cMXZ9A"
                          }
                        ]}

Every "signatures" object has the additional data for a certain RP authentication credential (protected or unprotected).
Underneath every "signatures" object, the "signature" object has the respective signature over "payload" and "protected".
"protected" could contain the response encryption key, so it is signed and authenticated.

Open Questions:

  • Would we adopt this for the traditional OID4VP flow and the DC API?
  • Would we adopt this and still support signed requests for a single client id with JWS Compact Serialization?

@jogu
Copy link
Collaborator

jogu commented Sep 6, 2024

I've split the multiple RP authentication part out into issue #248 as it seems to be more generally applicable. (We should probably create issues for any other generally applicable parts.)

@jogu
Copy link
Collaborator

jogu commented Sep 10, 2024

Agreed on today's call that Martijn could open a PR.

@bc-pi
Copy link
Member

bc-pi commented Sep 11, 2024

Agreed on today's call that Martijn could open a PR.

While that is true, it was at the very end of the call at a point that I suspect many participants had lost the will to try to contribute. I can say with some certainty that that's where I was at that point in the call. I can also say with some certainty that it's not clear what that PR might entail. But I really hope that any such work will consider @jogu's very reasonable and appropriate comment from a month ago: "[that the] mdoc profile itself should only build on top of what is already in the rest of the standard, specifying how to use the existing standard with mdoc - i.e. not specifying new behaviours [behaviors] unless they're dealing with an mdoc-specific problem. [and even then considering if they are really mdoc-specific problems or just seem that way due to being viewed through an mdoc-specific lens]."

@jogu
Copy link
Collaborator

jogu commented Sep 11, 2024

Thanks @bc-pi. Yeah, sorry, my previous comment was probably overly brief, a side effect of trying to get through too much on yesterday's call. To record the other things I said on the call:

The profile is expected to define things for interoperability like which authorization_encryption_alg_values_supported value must be used for mdl, and what goes in the SessionTranscript - very similar to what part 7 does (although I really hope this ends up a lot shorter than part 7). That is to say, a strict profile of what is already in the rest of the spec, not introducing new features.

@bc-pi
Copy link
Member

bc-pi commented Sep 11, 2024

Hopefully the thoughtful work that @selfissued did in #243 to clarify signing and encryption with JARM responses will help with any persistent misunderstanding that's occurred in this context.

@jogu
Copy link
Collaborator

jogu commented Sep 12, 2024

I talked privately with Martijn a bit more about this just to check we didn't have any unsettled items left but it looks like we still need to discuss the encryption mechanism more in the working group to reach a consensus, so I've moved this to 'discuss' status.

@jogu jogu added discuss and removed ready-for-PR labels Sep 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants