w3c-ccg / ld-cryptosuite-registry

REGISTRY: Linked Data Keys Registry (managed by W3C Credentials Community Group)
https://w3c-ccg.github.io/ld-cryptosuite-registry/
Other
12 stars 4 forks source link

Linked Data Key Format Proposal: Split public key value and encoding #3

Open EternalDeiwos opened 6 years ago

EternalDeiwos commented 6 years ago

I found a limitation in the current format for Linked Data keys. There are quite a few ways of representing key material that may be encapsulated multiple times however the current format only provides a hint to the payload of the document in the name of the field such that:

  1. Only the outer-most encoding is provided. pem at least implies base64+der which can be used to infer whether what is being presented is pkcs1 or pkcs8 encoded; however each of these steps would be a lot easier if one didn't have to guess/infer the various levels of encapsulation around a key.
  2. Implementations should either hard-code or guess the name of the field that contains the public key.
  3. Signature Suites are not future proof. The current format implies that bespoke code be written per signature suite which discourages interoperability between key/signature types.

I would like to propose the following:

  1. Addition of a key type field: i.e. RSA keys may be used for RSA-PSS and RSA-PKCS1 signature types (differences in padding specification).
  2. Separation of key value and encoding into separate fields: i.e. "encoding": "PEM" or "encoding": "BASE64_DER_PKCS8" (without the PEM headers). These values and their meanings would be specified in the various signature suite specifications but also be self-descriptive.

An example of this might look like the following:

{
  "id": "did:example:123456789abcdefghi/keys/2",
  "type": "Ed25519SigningKey",
  "keyType": "ed25519",
  "owner": "did:example:123456789abcdefghi",
  "expires": "2017-02-08T16:02:20Z",
  "encoding": "BASE64_DER_PKCS8",
  "publicKey": "IOmA4R7TfhkYTYW87...CBMq2/gi25s="
}
msporny commented 6 years ago

Hey @EternalDeiwos, we had considered more variability in key encodings but have chosen not to provide the developer that level of granularity by design. Here's the thinking that went into this design pattern:

Crypto is hard and many developers get it wrong, especially around encoding formats such as BASE64_DER_PKCS8. The experts need to pick appropriate values for developers using these data structures and libraries. Based on this, we decided that we'd provide "cryptography suites". A cryptography suite is typically dated... like "type:": "Ed25519VerificationKey2018". This is really the only thing that a developer using the data structure and subsequent library needs to know/use. There is one thing that they can key off of to tell the software all of the other cryptographic parameters that are necessary. That's the goal, anyway.

It is up to the cryptography suite to specify all of the expected cryptography parameters so that developers don't have to try to understand what BASE64_DER_PKCS8 even means. For example, if you are using the RsaSignatureSuite2018 and are specifying an RsaVerificationKey2018, then the spec will state the expected encoding format(s). For example, if one were to use publicKeyPem the spec will state what the encoding format/formats for that will be the X.509 SubjectPublicKeyInfo in PEM format. Note that you can provide TWO or more encoding formats in a publicKey object. For example, I could express it in PEM format and JWK format... or PEM and base58 and jwk. For that reason, you can't split the encoding out into the object.

Now on to your suggestions:

Addition of a key type field: i.e. RSA keys may be used for RSASSA-PSS and RSASSA-PKCS1-v1_5 signature types (differences in padding specification).

For RSA keys, we have "RsaSignature2018", which uses RSASSA-PSS (IIRC). "RsaVerificationKey2018" use a X.509 SubjectPublicKeyInfo in PEM format for the publicKeyPem field. There are no other options for that signature suite. Others are welcome to create other signature suites with different parameters. The signature suites that we create are supposed to pick the best of breed cryptography options at the time they're created covering at least 80% of the use cases. Giving regular developers access to all the crypto knobs and levers has proven to be a bad idea over time.

Separation of key value and encoding into separate fields: i.e. "encoding": "PEM" or "encoding": "BASE64_DER_PKCS8" (without the PEM headers). These values and their meanings would be specified in the various signature suite specifications but also be self-descriptive.

If we do this, we couldn't have multiple encodings per publicKey... which some people have insisted that they have or they won't use Linked Data Signatures (unfortunately). For example, not supporting the JWK format resulted in hostility from the JOSE community. We have since attempted to reduce the hostility by supporting the JWK format AND using JWS as the signature encoding format for RsaSignature2018.

EternalDeiwos commented 6 years ago

Thanks for the explanation @msporny. It seems I made some incorrect assumptions (i.e. multiple encodings present in a single document). Re-reading the other documents with this in mind makes a bit more sense. I'll continue my investigation in the LD signature suites and see how far I can go with those.

I have one last question that is somewhat related: the signature suites that are referenced by this registry have examples for how key material should be represented, however the signature suite documents themselves make no reference to the format of the key material. There is also no mention of how to go about specifying this. The LD signatures document only mandates that the signature parameters and algorithms be specified.

Perhaps the signature suite documentation could be extended to define the format, identification and encoding of LD keys as well?

Otherwise I'm happy to consider my original query resolved and close this issue if you are.

OR13 commented 4 years ago

@EternalDeiwos related: https://github.com/w3c-ccg/lds-jws2020/issues/11

IMO, The signature suite documentation should be extended to define supported key representations explicitly.

This repo is for registering suites, and is not the place to define what a "valid suite is".

Please leave a comment here: https://github.com/w3c-ccg/ld-proofs/issues/25

OR13 commented 4 years ago

@msporny @EternalDeiwos please let me know if I can close this issue.

EternalDeiwos commented 4 years ago

No complaints from me.