walt-id / waltid-identity

All-in-one open-source identity and wallet toolkit.
Apache License 2.0
119 stars 44 forks source link

Invalid use of EC signing keys for keyAgreement property of generated DID Documents #579

Closed cpatsonakis closed 2 months ago

cpatsonakis commented 3 months ago

Describe the bug DID registrar classes, on input any EC key type that is currently supported, i.e., secp256r1, secp256k1 and ed25519, use that same key to also populate the keyAgreement property of the generated DID document. However, according to the JWA (RFC 7518) standard, key agreement with EC keys should be handled via the ECDH-ES (RFC 8037) algorithm. The ECDH-ES specification, among others, states that:

Example output of the Wallet API when creating a did:key with an ed25519 key:

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/jws-2020/v1"
  ],
  "id": "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs",
  "verificationMethod": [
    {
      "id": "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs",
      "type": "JsonWebKey2020",
      "controller": "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs",
      "publicKeyJwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "kid": "Znl2a8qM4ElTpitTENSJg93oJSm-PLrKs_pKItITy9M",
        "x": "O-EIiQgIiU88hYt3uDe1_tUekcGHRLfV5s8oms025J4"
      }
    }
  ],
  "assertionMethod": [
    "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs"
  ],
  "authentication": [
    "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs"
  ],
  "capabilityInvocation": [
    "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs"
  ],
  "capabilityDelegation": [
    "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs"
  ],
  "keyAgreement": [
    "did:key:z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs#z6MkiV17vrjSg2EDHWuRudxaXcYiAkuuTYnk1aS1hVnYPXbs"
  ]
}

Environment All environments as this is an issue with the waltid-did library.

pohutukawa commented 3 months ago

ECDH-ES for keyAgreement should also work with other key types but X25519 or X448. However, a key that's used for signing should usually not be used for encryption (via ECDH-ES) as well. So it could also be permissible to use secp256r1 or secp256k1 for keyAgreement, but they should be their own key pairs.

As a note: Ed25519 and X25519 (as well as Ed448 and X448) are related, and just different mathematical expressions of the same curve. However, the algorithms defined for it for EdDSA and ECDH respectively are structured differently, thus the key pairs/points on the curve will not work interchangeably. For that reason the private component of the EdDSA keys is usually (strictly speaking) also called the 'key seed' as opposed to the 'private key'. This avoids some problems with sloppy key management in implementations.

cpatsonakis commented 2 months ago

Hi! Thank you for your feedback.

Yes, even if a key can be used for multiple purposes, it is still a best practice to use it only for a specific purpose. This is a limitation of the current version of the API, i.e., it only allows one key to be specified when creating a DID. This is the topic of #581.

Yes, there exists a birational equivalence between Curve25519 and Edwards25519. I would not say that they are the same thing, since they do not have the exact same formula and because each X25519 public key can be actually mapped (from a maths perspective) to two Ed25519 public keys, but I digress.

Focusing on the topic of key agreement now.

It is true that ECDH can be performed with secp256r1 and secp256k1 keys. Indeed, in TLS-land it happens all the time! Also, it is a NIST-approved algorithm. This is a fact.

The original post conveys what the respective JOSE standard states, i.e., that ECDH-ES should only be executed with X25519 and X448. This is also a fact. Based on the previous point, is JOSE "wrong", or incomplete? One could argue that!

In DID-land, matters are a bit more fluid. To my knowledge, all DID-related specs, on the topic of key agreement, use exclusively X25519 keys (and not X448). The same holds for all DID method implementations (again, to my knowledge). This is also a fact. Are these specs "wrong", or incomplete? One could argue that!

In maths, or theoretical cryptography land, one can do ECDH with Ed25519 keys. An additional computation step of course is required. Moreover, one can also do signature verification with X25519 keys (doesn't make sense, but possible). This is also a fact. Are all the aforementioned specs "wrong", or incomplete?

What I am trying to get at is that we humans define these specs, each of which has its own merits, and we just agree to follow/adopt them.

In our case, since we are inhabitants of DID-land and we are mostly engaged with serializations of VCs that are built on top of the JOSE standards, it is "natural" to refer to these standards. However, there is no "rule" that mandates that we strictly follow them across the board.

Are secp256r1 and secp256k1 keys for keyAgreement important, or blocking factors for your use case?

pohutukawa commented 2 months ago

@cpatsonakis, good points and well presented argumentations.

Besides the different presentations of the related Ed25519 and X25519 curves, the algorithm of EdDSA via Ed25519 works differently. Diffie-Hellman with X25519 is pretty 'vanilla', whereas EdDSA uses the private key seed d not as a point coordinate directly, but applies a hash over it. So the notion of private/public key is slightly different here, and thus the usage of an EdDSA (e.g. with Ed25519) key pair will not work with a DH key agreement directly.

For what we want/need is the use of Ed25519 (authentication/signing) and X25519 (key agreement/encryption), keeping it aligned with what the DID community is currently doing. I had only mentioned secp256r1 and secp256k1 for completeness as well as for the popularity either in the corporate world (secp256r1) and the blockchain world (secp256k1) respectively, with also BLS signatures (BLS12-381 curve) gaining traction recently.

Immediately we will have need for support for X25519 for keyAgreement, while the future will likely also (not just for us) demand support for other key pairs/curves for the different purposes to be exposed via a DID registry. So the unavailability of an X25519 keyAgreement would be the blocking factor in our case.

cpatsonakis commented 2 months ago

Hello!

Thank you for your feedback, we now have a clear understanding of your requirements.

We would like to inform you that we have added this item in our development backlog.

Temporarily closing this issue for now.

If you happen to have any additional feedback, or comments, on this subject, please add them here and the issue will be automatically re-opened.

Thank you again for your input!

pohutukawa commented 2 months ago

@cpatsonakis, is there any indication on when that backlog item would be addressed as part of your development work? Just a rough indication would suffice.