decentralized-identity/did-registration

Specify signing requests / interface with wallets

Closed this issue · 6 comments

In cases where a DID Registrar interacts with an external wallet (see External Secret Mode) or a client-managed wallet (see Client-Managed Secret Mode), we should specify those interfaces.

Existing work that is related to this:

In the experimental client-managed secret flow with did:sov, the registrar currently returns a signing request like this:

{
  "jobId": "12345",
  "didState": {
    "state": "action",
    "action": "signPayload",
    "kid": null,
    "alg": "EdDsa"
    "payload": "6964656e7469666965723a56345347525538365a353864365456375042556536667c6f7065726174696f6e3a646573743a42527850353836484270474850706861517152374d767c747970653a317c7665726b65793a366769704764676f795a4c7745794b66326b61727a634d70316a50487843553236624b4336574a75364a4e6b7c70726f746f636f6c56657273696f6e3a327c72657149643a31363330353032333436323337393433303030",
  },
  "didRegistrarMetadata": { .. },
  "didDocumentMetadata": { .. }
}

I.e. it is asking the client to sign the value in payload.

But instead of a single payload, maybe multiple named "signing requests" in the form of a map should be supported, e.g.:

{
    "jobId": "1234",
    "didState": {
      "state": "action",
      "action": "signPayload",
      "signingRequest": {
        "signingRequest1": {
          "payload": {
             ...
          },
          "serializedPayload": "<-multibase->",
          "kid": null,
          "alg": "EdDsa",
          "verificationMethod": "..." // could point to a verificationMethod, incl. VerifiableConditions with threshold, etc.
          "proofPurpose": ".."  // ??
          },
          "signingRequest2": {
            "payload": "8784566",
            "kid": null,
            "alg": "ES256K"
        }
      }
    },
    "didRegistrationMetadata": {
    },
    "didDocumentMetadata": { }
}

Additional notes:

  • Maybe both a payload (in JSON) and a "serializedPayload" (bytes) should be included, so that the payload can be displayed to a human before signing; could be necessary for legal reasons, i.e. you can only sign what you understand
  • Maybe verificationMethod and/or proofPurpose could be re-used in such signing requests

This way, the next request would include a set of signing results matching the signing requests, e.g.:

{
    "jobId": "1234",
    "options": {
        "network": "danube",      // not really needed because of jobId
        "clientSecretMode": true, // not really needed because of jobId
        "signingResult": {
            "signingRequest1": "<-multibase->",
            "signingRequest2": "<-multibase->"
        }
    },
    "secret": { },
    "didDocument": { }
}

Additional notes:

  • Since network and clientSecretMode were already included in the first request, they can now be remembered as part of the jobId and don't have to be included again.

Signing requests could include an optional timeout that tells the client how long the driver will wait for the signature.

Just a thought on this, what if we built around the WebCrypto Sign API in order to make this work? This would enable the ability to implement these features within the browser as a standard API while also using a standardized interface that could be wrapped around things like propritary KMS services or utilize implementations that are made for like node.js.

Great idea @kdenhartog , I thought only about Universal Wallet and WebKMS, but not WebCrypto API. I just added a quick commit to mention that too in a number of places: 71a5f17

Great idea @kdenhartog , I thought only about Universal Wallet and WebKMS, but not WebCrypto API. I just added a quick commit to mention that too in a number of places: 71a5f17

The referenced commit looks good to me

I think the specification now sufficiently describes how signing requests and responses work:

Also, the section on "external secret mode" has been expanded a bit to explain the possible interface with wallets, including Universal Wallet, WebKMS, WebCrypto API:

So I'm closing this issue.