w3c / did-core

W3C Decentralized Identifier Specification v1.0
https://www.w3.org/TR/did-core/
Other
405 stars 94 forks source link

Supported ciphers in a DID document #185

Closed tplooker closed 4 years ago

tplooker commented 4 years ago

Currently a DID document supports expressing cryptographic material and how that cryptographic material is authorized such as to validate assertions or authenticate as acting on behalf of the DID subject. Other proof purposes like key agreement enable another party to establish a shared secret via diffie-helman with the DID subject. However in order for one party to prepare a cipher that is decrypt-able by the DID subject. The encrypting party must know what ciphers the did subject supports. This issue is raising the question whether the DID document is the place for this information to exist. See below for a sample DID document

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:example:123456789abcdefghi",
  "keyAgreement": [{
    "id": "did:example:123456789abcdefghi#keys-1",
    "type": "RsaVerificationKey2018",
    "controller": "did:example:123456789abcdefghi",
    "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
  }],
 "supportedCiphers": [
  "A256GCM",
  "C20P"
  ],
  "service": [{
    "id":"did:example:123456789abcdefghi#messaging",
    "type": "MessagingService",
    "serviceEndpoint": "https://example.com/messaging/"
  }]
}
OR13 commented 4 years ago

As @csuwildcat noted, the list of supported ciphers could be exposed by the same serviceEndpoint.

However, there will also be the offline first needs of did methods, such as did:key or pdf variants. In such cases, it may be desirable to embed the supported ciphers in the did document.

I think it would be wise for us to support exposing preferences for ciphers, if we are exposing keyAgreement... and leave it up to the parties to decide if they want to expose the communication channel they will be using, or do that somewhere else...

tplooker commented 4 years ago

Agreed the case could definitely be made that this functionality could be shifted into service endpoints however this likely makes it service dependent rather than being core functionality supplied by the did document.

tplooker commented 4 years ago

@msporny @dlongley interested to hear your opinions and the implications of having this functionality in the DID document for the EDV/PDS work?

msporny commented 4 years ago

@msporny @dlongley interested to hear your opinions and the implications of having this functionality in the DID document for the EDV/PDS work?

I'm hesitant... feels like it's at the wrong level of abstraction and might not be necessary at all.

It might be something that you want to express as a part of the Key Agreement Verification Method, probably in the type. Remember that a signature cryptosuite is a tight coupling of canonization algorithm, hash algorithm, and signature algorithm. Key agreement cryptosuites should probably be designed in the same way (in general). If there are two different key agreement mechanisms for the same type, then you could associate it w/ the verification method, but not at the top level of the DID Document.

It's on my todo list to do a deeper dive on this, but other items are going to prevent me from getting to it for a while and I'm concerned that folks are going to start pushing to have it at the root of the DID document (which I'm probably going to push back against until I'm educated enough to have a more specific opinion).

Was thinking something like this:

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:example:123456789abcdefghi",
  "keyAgreement": [{
    "id": "did:example:123456789abcdefghi#keys-6",
    "type": "X25519KeyAgreementKey2019",
    "publicKeyBase58": "jf892...jf98b",
    "supportedCiphers": ["CipherA", "CipherB"]
    "controller": "did:example:123456789abcdefghi"
  }],
  "service": [{
    "id":"did:example:123456789abcdefghi#messaging",
    "type": "MessagingService",
    "serviceEndpoint": "https://example.com/messaging/"
  }]
}

... but then again, that presumes that it's ok to have two different ciphers (really, key exchange protocols)... which feels like too much algorithm agility.

Sorry, that's all I have at the moment... an uneducated guess at a general direction. :)

OR13 commented 4 years ago

I'm hearing from this that Key Agreement Suite, should specify supported ciphers, and that we should not support "optionality" here... which feels right to me. We could support a table for a given key agreement suite, similar to the approach we took here: https://github.com/transmute-industries/lds-jws2020, but it sounds like it would be better to make everything tighter coupled with less flexibility. One key agreement suite, one key type, one supported cipher suite...

tplooker commented 4 years ago

Having thought about this more, I agree I don't want to encourage too much optionality in the did document. My feelings about putting them in the key agreement section are mixed. On one hand it is achieving more of a crypto suite feel, by bundling related crypto primitives. However I'd argue the section wouldn't then be called keyAgreement instead more like encryption? Also what would the implication around things like key wrapping operations?

OR13 commented 4 years ago

I agree, I've always been a little confused why keyAgreement isn't just publicKey, and why not have encryption point to a publicKey key like authentication does.

msporny commented 4 years ago

why not have encryption point to a publicKey

Because developers will end up doing horrible things if we put a bucket called encryption in the DID Document... where they will store their symmetric encryption keys and dump them to a ledger, pwn'ing data that they encrypt using that same key.

keyAgreement is associated with a verification method that is expected to be used with a modern encryption mechanism that uses authenticated encryption. The keyAgreement key is used to agree on a key which is then used to do authenticated encryption (it verifies... aka authenticates... the encrypted content).

Does that explain why we had considered encryption before and rejected it due to concern over people misunderstanding what that field is used for?

OR13 commented 4 years ago

this makes a lot more sense now... I think we should use keyAgreement types to lock down cipher suites.

dlongley commented 4 years ago

The keyAgreement key is used to agree on a key which is then used to do authenticated encryption (it verifies... aka authenticates... the encrypted content).

To be more precise, a few other layers are actually in there:

A keyAgreement key is used to agree on a shared secret that is used to derive a shared "key encryption key" that is used to wrap a content encryption key ("key wrapping") that is used in an authenticated encryption scheme to encrypt some content.

So, being able to encrypt some content for an intended recipient such that they can later authenticate and decrypt it relies upon that recipient having a keyAgreement verification method (e.g., an ECDH public key).

tplooker commented 4 years ago

@msporny, your rational wrt why not use the term encryption makes sense so I'm happy to continue to explore collapsing all this information into a keyAgreement section.

@dlongley wrt key wrapping, have you had any thought about whether there should be any more explicit information in a keyAgreement section describing the key wrapping algs supported? Or is it expected that this would be defined by the type of keyAgreement?

E.g does a key agreement key of X25519KeyAgreementKey2019 imply that I can do both direct keyAgreement and keyAgreement using a KDF + cipher?

msporny commented 4 years ago

I suggest we close this issue and open a new issue for @tplooker's comment made here (if he so desires): https://github.com/w3c/did-core/issues/185#issuecomment-586748625 .

I will close this issue shortly unless I hear an objection from @tplooker.

@tplooker open a new issue if you want for the item you raise above.

tplooker commented 4 years ago

@msporny, I'm happy to close and reopen another issue, but I'm unclear if a new issue has a distinctly different intent to what is currently asked by this issue, which remains un-resolved? That is, how do we express the ciphers supported by the did subject?

I'm happy to submit a PR that adds the functionality under the keyAgreement section however we have not defined that as a core proof purpose yet?

selfissued commented 4 years ago

I would oppose closing this until the issue is addressed in normative text.

OR13 commented 4 years ago

We will get to the first instance of keyAgreementKey X25519KeyAgreementKey2019 in the registry shortly... I will look to @dlongley for an answer to the question posted in https://github.com/w3c/did-core/issues/185#issuecomment-586748625

Or a more formal defintion of X25519KeyAgreementKey2019... I think we need to leave this open until we at least have this in the registry.

dlongley commented 4 years ago

@tplooker,

E.g does a key agreement key of X25519KeyAgreementKey2019 imply that I can do both direct keyAgreement and keyAgreement using a KDF + cipher?

I would prefer only the latter but admit that this is underspecified.

The trend in crypto is to "do the currently best thing" and don't get any more complicated than that; don't support lots of options. There are a number of articles that have been written regarding the cryptographic "right answers" (for now), for example this one. For this reason, communities have been pushing to use "verification methods" that are pinned to specific years (to give a good human readable indication of whether or not using a key is still a good idea) and that reduce unnecessary cryptographic agility. Similarly, libraries have been written that reduce the choices to either one or two options:

  1. Whatever cryptographers currently recommend,
  2. Whatever large governments require.

When those two are compatible, the philosophy is that there should be only one option (and thus no need to "choose" anything). To that end, I'm in favor of locking specific verification methods/keys down as much as possible.

dhh1128 commented 4 years ago

I wanted to largely +1 everything @dlongley said. However, I want to suggest a nuance: although locking down specific verification methods is uncontroversial to me, the specific sets of semantics (what bundles of functionality should be unlocked by particular methods, and what the names of those methods should be) still feels very controversial. I think we're very far from clear on those.

tplooker commented 4 years ago

@dlongley, thanks I agree with your comments, having the ability to revise the key type definition in future but for the same underlying key type e.g X25519 will enable us to remain current with changes in cryptographic best practise w.r.t to things like key wrapping anyway. So limiting the optionality around the definition for something like X25519KeyAgreementKey2019 i'm in agreement with.

Are we then saying that the definition of something like the X25519KeyAgreementKey2019 key type will require a supportedCiphers section featuring at least one valid encryption algorithm? Furthermore are the cipher algorithms declared in the supportedCiphers section of a keys definition stating that those ciphers are supported by the did subject for both encryption of the content encryption key as well as encryption of the content?

@dhh1128, I'm interested to hear your thoughts in regards to the naming of verification methods, I'm assuming you're speaking about the term keyAgreement in this context? @msporny earlier in this issue outlined the rationale for why that term has been used instead of something such as encryption.

dhh1128 commented 4 years ago

I'm assuming you're speaking about the term keyAgreement in this context?

Yes, but I think that particular one is relatively crisp. I'm more concerned about ones that bake into the spec the idea of capabilities, and ones that assume a signing key is used to sign credentials as well as all other artifacts that require signatures. I don't see any verification method for the act of registering a key on a blockchain, which I think is distinct. Etc.

tplooker commented 4 years ago

@dhh1128 ok great, r.e you question about registering a key on a blockchain, I think that is related to issue #195?

dlongley commented 4 years ago

So limiting the optionality around the definition for something like X25519KeyAgreementKey2019 i'm in agreement with.

+1. It may even be a good idea to start naming these suites even more generically going forward: BestCryptoKeyAgreementKey2020 (or just KeyAgreementKey2020) and then underneath the specific crypto is whatever is recommended in the year 2020 per the rules described above.

kdenhartog commented 4 years ago

I'm in favor of that. If we really need two options it would be

BestCryptoKeyAgreemetKey2020 => Whatever cryptographers currently recommend OldGovernmentKeyAgreementKey2020 => Whatever the government requires

And no bikeshedding is needed there 😎

msporny commented 4 years ago

It may even be a good idea to start naming these suites even more generically going forward: BestCryptoKeyAgreementKey2020 (or just KeyAgreementKey2020) and then underneath the specific crypto is whatever is recommended in the year 2020 per the rules described above.

While I'm supportive of this path, I don't think we'll be able to achieve it. I think the best we'll be able to do is some sort of hierarchy, like this:

... and so on.

brentzundel commented 4 years ago

Since adding the pending close label, this issue has received a lot of attention. Removing the label and leaving the issue open, @msporny, @talltree, @peacekeeper

OR13 commented 4 years ago

Sounds like we have decided on this thread to define some suites that support specific form so authenticated encryption...

https://www.iana.org/assignments/jose/jose.xhtml#web-encryption-compression-algorithms

For example ECDH-ES+A256KW + P256... The specific pairings for each need to be defined in a registry... similar to how we handle linked data signature suites...

We could add a recommendation for the JWS algs listed here:

https://github.com/transmute-industries/lds-jws2020

tplooker commented 4 years ago

I agree we are definitely making progress.

So just to bring this back to the original scope of the issue which was around supported ciphers.

The presence of a KeyAgreementKey2020 or X25519KeyAgreementKey2020 (depending on what we call it) in a did document, tells us the following information about the did subject.

Alternatively do we want to support other key lengths or do we want to another cipher instead of XChacha20Poly1305 as the default?

W.R.T key agreement algorithms I would like to also suggest that a KeyAgreementKey2020 also implies support for ECDH-1PU. Essentially the difference between ECDH-ES and ECDH-1PU is that ECDH-1PU involves a double DH which includes the senders static public key, so that the recipient(s) can authenticate the sender.

tplooker commented 4 years ago

Then for the NistVerificationKey2020 we would define the same as above accept using the namedCurve of secp384r1 and cipher of AES-GCM?

tplooker commented 4 years ago

Or the other option is that we do not allow supportedCiphers in keyAgreement keys because its assumed a particular keyAgreement key only supports a single cipher?

kdenhartog commented 4 years ago

I prefer the KeyAgreementSuite supporting only a single cipher approach. This makes for simplicity of implementations and makes it for better interoperability in my opinion.

dlongley commented 4 years ago

@kdenhartog,

I prefer the KeyAgreementSuite supporting only a single cipher approach. This makes for simplicity of implementations and makes it for better interoperability in my opinion.

+1

@tplooker,

The presence of a KeyAgreementKey2020 or X25519KeyAgreementKey2020 (depending on what we call it) in a did document, tells us the following information about the did subject.

They support ECDH and more specifically ECDH-ES in direct key agreement mode.

-1. I think key wrapping should always be used instead of using the shared key as a CEK (content encryption key). This allows much more flexibility in use cases for what I consider to be negligible overhead. When the shared secret (or more specifically, a key derived from it) is used as a KEK (key wrapping key) instead of a CEK, the CEK itself can often be rewrapped as needed instead of having to reencrypt the entirety of content. It also allows the same CEK to be reused across multiple recipients.

I think the scheme should always involve using a standard KDF on the derived shared secret to produce a KEK which is then used to wrap a CEK using a standard algorithm. The CEK should have a single size and be used with a single algorithm.

They also support the cipher of XC20P for the purposes of both content encryption and key wrapping (e.g ECDH-ES+XC20P256KW) with a content encryption key length of 256?

Do you have a link to an IETF spec where XC20P256KW is defined? I haven't seen it -- so our libraries have been favoring using AESKW.

If a supportedCiphers array element is declared in the key with KeyAgreementKey2020 then it extends the list of supported ciphers for the purposes of both key wrapping and content encryption support?

-1 ... I think another verification method should be minted for this.

Alternatively do we want to support other key lengths or do we want to another cipher instead of XChacha20Poly1305 as the default?

So, I'd like to see KeyAgreementKey2020 mean this:

ECDH-ES+A256KW using X25519 to derive the shared secret, which is fed into the standard Concat KDF described in RFC 7518 Section 4.6.2 to produce an AES-256 bit KEK. This KEK is used to wrap a 256-bit CEK for use with XChaCha20-Poly1305 (XC20P) authenticated encryption. I'd also like to see the APU/APV values for the Concat KDF locked down in a specific way.

W.R.T key agreement algorithms I would like to also suggest that a KeyAgreementKey2020 also implies support for ECDH-1PU. Essentially the difference between ECDH-ES and ECDH-1PU is that ECDH-1PU involves a double DH which includes the senders static public key, so that the recipient(s) can authenticate the sender.

I see that this: https://tools.ietf.org/id/draft-madden-jose-ecdh-1pu-03.html#rfc.section.2.2 is nearly identical to what I just described above modulo ECDH-1PU. I think we need to make sure this can work for existing use cases -- but if so, I could sign onto it. If not, we may need to support either ECDH-ES or ECDH-1PU. As always, I would prefer to support just one -- the latter appears to be better with minimal overhead, but ... use cases such as encrypting data for Encrypted Data Vaults (EDVs) need to be considered. I also haven't considered the implications on a similar NIST approved version of this.

If we adopt the above (ignoring the ECDH-1PU discussion for the moment), then the only differences between a NistKeyAgreementKey2020 and a KeyAgreementKey2020 may be XChaCha20-Poly1305 becomes AES-GCM and X25519 becomes P-256 (or P-384 as some have suggested may be necessary). It may even be the case that we can keep X25519, avoid P-256/P-384 entirely, and remain NIST-compliant (this would be ideal), see: https://tools.ietf.org/html/draft-ietf-lwig-curve-representations-09#section-4.1.

OR13 commented 4 years ago

ECDH-ES, ECDH-ES+A128KW[1], ECDH-ES+A192KW[1], ECDH-ES+A256KW[1]

C20PKW, XC20PKW, ECDH-ES+C20PKW, ECDH-ES+XC20PKW

https://www.npmjs.com/package/jose#detailed-support-matrix

All that is needed to support these is a table with mappings.

I'm not sure its a best practice to create a new key "type" for "key agreement" and "verification", its certainly not defined like that in JOSE: https://www.iana.org/assignments/jose/jose.xhtml

kty crvOrSize sig alg key agreement encryption
EC P-256 ES256 ECDH-ES+A256KW AES-GCM

For key type = JsonWebKey2020.

similar rows for other recommendations this year...

tplooker commented 4 years ago

Do you have a link to an IETF spec where XC20P256KW is defined? I haven't seen it -- so our libraries have been favouring using AESKW.

See here, it is currently a draft. You will note this also uses the single step kdf using the concatenation format.

Your above description means someone needs to support two ciphers, AES-GCM for KW and XChaCha20-Poly1305 for content encryption?

I see that this: https://tools.ietf.org/id/draft-madden-jose-ecdh-1pu-03.html#rfc.section.2.2 is nearly identical to what I just described above modulo ECDH-1PU. I think we need to make sure this can work for existing use cases -- but if so, I could sign onto it

Correct ECDH-1PU is just a double diffie-helman under the hood rather than a single, there is still an ephemeral key pair involved but also the senders static public key. Z is the product of the two shared secrets Ze and Zs derived from each diffie-helman, this is then used in with the single step KDF using the concatenation format much like ECDH-ES.

I can see it be advantageous to support both ECDH-ES and ECDH-1PU in the single keyAgreement key. Sometimes the software responsible for preparing a cipher may have static public keys and it is useful for these to be authenticated into the cipher and sometimes it may not.

kdenhartog commented 4 years ago

Of note, the XC20P256KW draft is being held up until XChacha20Poly1305 is moved through the IRTF CFRG. It would be useful to have more people provide discussion, feedback, and reviews on the CFRG mailing list to get it moving. I've been in discussion with the author and the chairs there and they're ok with it moving forward, but we need more feedback.

https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/?include_text=1

dhh1128 commented 4 years ago

Today on a DIDComm call at DIF, @tplooker suggested (if I understood correctly) that a key agreement key is the proper label to use to describe the public key that should be used in DIDComm to represent the sender's key in a message sent with authenticated encryption -- and that we should check to see whether that key appears in the sender's keyAgreement section of the DID doc to know whether the sender key was appropriately authorized. I am not convinced this is wrong, but my gut is telling me to be uncomfortable (perhaps due to my own ignorance). The key we're talking about is used to derive an ephemeral CEK for just the message in question, I believe -- but there is no long-lived negotiated, symmetric session key. So while that may narrowly satisfy the technical definition of a key agreement key, it feels like quite a different thing from a pragmatic view.

OR13 commented 4 years ago

Seems safe to say that keyAgreement is the place to put keys used for encryption for things like didcomm and encrypted data vaults.

OR13 commented 4 years ago

Related to the JOSE conversation: https://github.com/w3c-ccg/lds-jws2020#supported-jose-algorithms

We are gonna address this on the topic call I believe.

tplooker commented 4 years ago

The outstanding question for me on this issue is whether a single type of keyAgreement key is constrained to supporting only one content encryption cipher, this appears to be implied @dlongley in some of your prior comments? To me this would then mean a new keyAgreement key type is required when a new content encryption cipher is desired to be used?

What about supporting a model where a keyAgreement key has a single default encryption cipher that it must support, but further ciphers can be advertised and supported in a keyAgreement key via the supportedCiphers property.

OR13 commented 4 years ago

I'd say its not, but like all cases where no constraint exists, it's probably best to make a recommendation that can be updated as the security landscape changes....

  1. Clear documentation / vocabulary
  2. Reasonable default recomendations
  3. Simple interface for developers and infosec community evaluate.
dlongley commented 4 years ago

@tplooker,

The outstanding question for me on this issue is whether a single type of keyAgreement key is constrained to supporting only one content encryption cipher, this appears to be implied @dlongley in some of your prior comments? To me this would then mean a new keyAgreement key type is required when a new content encryption cipher is desired to be used?

It is my preference that a new key agreement key type be created for each new protocol/set of ciphers whereby the type name is something akin to what @msporny said in his comment here: https://github.com/w3c/did-core/issues/185#issuecomment-598726990

That being said, there's no way to impose such a restriction on the people writing extensions; we can only give advice and strongly recommend this path because it simplifies things for users. Most users shouldn't have to know (and they don't!) which knobs to flip or choose to get the right security in the year 2020 or 2025.

Given that, I agree with @OR13's comment about "[making] a recommendation that can be updated as the security landscape changes" ... with a strong preference to make the above recommendation as the way these things should be done. Optionality should be limited within a given key type as much as possible because the alternative leads to security vulnerabilities.

OR13 commented 4 years ago

to give a concrete example, https://www.iana.org/assignments/jose/jose.xhtml#web-key-elliptic-curve

this registry makes it seem like P-256 is the best thing to use today:

P-256 | P-256 Curve | Recommended+ 
P-384 | P-384 Curve | Optional
P-521 | P-521 Curve | Optional 
Ed25519 | Ed25519 signature algorithm key pairs | Optional
Ed448 | Ed448 signature algorithm key pairs | Optional 
X25519 | X25519 function key pairs | Optional 
X448 | X448 function key pairs | Optional 
secp256k1 | SECG secp256k1 curve | Optional

and when you match those up with https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms

its again, not clear exactly what is being recommended here... are we recommending you support legacy potentially back-doored crypto because its in wide circulation and likely to have "interoperability" or are we recommending that you use cryptography that has some kind of "community approval" ala lib sodium / DJB....

see: https://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf

Why do people choose standardized curves?
- “Because they told me to”
- “Need to ensure interoperability”
- “The standards committee chose these curves for efficiency”
- “The standards committee chose these curves for security”
- “Obviously these curves have received much more cryptanalysis: standard makes a worthwhile target for attack”

We'll be discussing this and the benefits and trade offs wrt support for legacy crypto in the F2F session of algorithms, bring your pitch forks ;)

OR13 commented 4 years ago

I believe the consensus is have the suite make the recommendation.... and the suite specify the specific algs... and then an encryption consumer decide if they will use them..... this is supported by JsonWebKey2020 for example.

tplooker commented 4 years ago

Agree with @OR13 are there any remaining actionable's around adding text to that effect to existing key definitions or shall we close the issue? @msporny where would the above information be captured? In the registry?

OR13 commented 4 years ago

@tplooker not to volunteer you... but it might be worth adding some informative examples of encryption to the did core spec... a single JWE example would do wonders. I would not close this issue until at least 1 example of encryption using did documents was in did core.

OR13 commented 4 years ago

Related: https://github.com/digitalbazaar/minimal-cipher/issues/24

The folks at digital bazaar are leading the way here... but we need to be careful about just copying their approach for keyAgreementKey... and it would be helpful to have some of the people who created the JWE standard review this stuff in more detail ... ping @selfissued .

In particular, their current implementations does not work with P-384....

The naive developer (me) is going to do the following;

There is no interop problem at the cryptographic layer.... i wrote tests to confirm this... but hey, i could be wrong...

I cannot tell if there is an issue at the "mental model' layer... thats why I am asking here.

Their key agreement class is exposing deriveSecret which is really "scalar multiplication".... https://github.com/digitalbazaar/x25519-key-agreement-key-2019/blob/master/lib/X25519KeyPair.js#L285

compare that to the more popular web crypto API:

function deriveSecretKey(privateKey: any, publicKey: any) {
  return crypto.subtle.deriveKey(
    {
      name: 'ECDH',
      public: publicKey,
    },
    privateKey,
    {
      name: 'AES-GCM',
      length: 256,
    },
    true,
    ['encrypt', 'decrypt']
  );
}

Are these equivalent? or are they not? we need something that works for key types other than X25519, and we need interfaces for verification methods that are really only about "KeyAgreement" or "ECDH" that work for NIST Curves...

I'm not saying what they have doesn't work, or can not work.... I am saying I don't know if these are equivalent interfaces.... and at first glance, exposing raw scalar multiplication on a "KeyAgreementKey' Verification Method KeyPair Class seems like less of a good idea... when we could be exposing APIs that work out of the box with web crypto.

The terminology here is IMO.... not helping... we have concepts like ECDH and deriveSecretKey for 'AES-GCM'... inventing new terms for deriveSecret that is really just scalar multiplication on keys labled "keyAgreement" which are really just for "ecdh" and then asking developers to ponder if they must manually implement https://github.com/digitalbazaar/minimal-cipher/blob/master/algorithms/ecdhkdf.js is... less friendly than saying... DIDs work out of the box with window.crypto.subtle and node crypto / jose.....

dlongley commented 4 years ago

In particular, their current implementations does not work with P-384....

See https://github.com/digitalbazaar/minimal-cipher/issues/24 for an update on this. There was a misunderstanding around what deriveKey in the Web Crypto Subtle API does (it is just a key import wrapper around deriveBits) -- and there is a deriveBits function that can be called directly that performs the same function as deriveSecret. So there should not be a compatibility/API mismatch issue.

OR13 commented 4 years ago

Yes, thanks for explaining.

The answer to the question:

"What are the verification methods in the key agreement used for?"

is:

deriveBits / deriveSecret / ECDH / ECDH-ES+A256KW ...

"Do I need to implement ECDH KDF / A256KW myself?"

No, you can use window.crypto / node crypto / standard crypto libraries.... assuming you can handle the key conversion from whatever format is used.

"Do I have to name my keys used of Key Agreement / Encryption ... ___KeyAgreementKey___ ?"

Maybe, we're discussing the requirements associated with registering verification method type "names" here: https://github.com/w3c/did-spec-registries/pull/96

dlongley commented 4 years ago

Are these equivalent? or are they not? we need something that works for key types other than X25519, and we need interfaces for verification methods that are really only about "KeyAgreement" or "ECDH" that work for NIST Curves...

deriveBits from the Web Crypto API and deriveSecret from minimal-cipher are equivalent. These interfaces are compatible with any ECDH curves.

The terminology here is IMO.... not helping... we have concepts like ECDH and deriveSecretKey for 'AES-GCM'... inventing new terms for deriveSecret that is really just scalar multiplication on keys labled "keyAgreement" which are really just for "ecdh" and then asking developers to ponder if they must manually implement https://github.com/digitalbazaar/minimal-cipher/blob/master/algorithms/ecdhkdf.js is... less friendly than saying... DIDs work out of the box with window.crypto.subtle and node crypto / jose.....

So, to be clear, this is not new terminology. "Deriving a shared secret" is how Diffie-Hellman has been discussed likely since its inception. There are lots of APIs that involve deriving or "computing" a shared secret from a private ECDH key and a peer's public ECDH key. Node's API is called computeSecret. OpenSSL's API is called EVP_PKEY_derive where you pass in a parameter called secret to store the result. There are lots of other examples.

The fact that deriving a secret using two X25519 ECDH keys can be implemented with a scalar multiplication API via the NACL library is an implementation detail. Interoperability on key agreement comes from specs like RFC 7518 which is what minimal-cipher implements.

Furthermore, I agree that most users shouldn't even be using the "deriveSecret" API that outputs a raw secret. But it is a necessary building block. The primitives for generating a key are a "deriveSecret" API and a KDF. At a primitives level, you can swap in different ECDH keys (each that can be used to derive a shared secret) and different KDFs. The minimal-cipher library aims to limit choices to a CFRG/crypto experts/community recommended "current" set of choices and a NIST recommended (fips) set of choices for these primitives (and whenever they are the same, the library only gives you one option). The minimal-cipher API most users use has to do then with passing in a key that is compatible with either the "recommended" or "fips" current protocol and the data they want to encrypt/decrypt -- and that's it.

The KDF isn't an option here -- it's the same for FIPS and what is recommended by the crypto community, which is the KDF ("Concat KDF" from NIST.800-56A) as specified in RFC 7518 (note: As mentioned elsewhere, the deriveKey Web Crypto API doesn't even use a KDF!). Similarly, our key types should build in this sort of profile of current available choices so that users just say the type they want -- and they don't have to pick any other details. The Right Thing (TM) will just happen -- just pick if you want the "crypto community recommended choice" or the "NIST recommended/required choice" for the current calendar year.

dlongley commented 4 years ago

"Do I need to implement ECDH KDF / A256KW myself?"

No, you can use window.crypto / node crypto / standard crypto libraries.... assuming you can handle the key conversion from whatever format is used.

Unfortunately, this isn't true. Well, there may be some help in various crypto libraries, but window.crypto (Web Crypto Subtle API) does NOT implement the interoperable KDF from RFC 7518 for you. I don't think node's crypto libraries have support either. If you want compatibility with JOSE's ECDH-ES+A256KW per RFC 7518, you will need additional library support.

OR13 commented 4 years ago

"Do I need to implement ECDH KDF / A256KW myself?"

No, you can use window.crypto / node crypto / standard crypto libraries.... assuming you can handle the key conversion from whatever format is used.

Unfortunately, this isn't true. Well, there may be some help in various crypto libraries, but window.crypto (Web Crypto Subtle API) does NOT implement the interoperable KDF from RFC 7518 for you. I don't think node's crypto libraries have support either. If you want compatibility with JOSE's ECDH-ES+A256KW per RFC 7518, you will need additional library support.

:(

In this case, i think it would be wise for us to consider adding methods for LD Keys that is equivalent to the JWE APIs used here:

https://github.com/transmute-industries/did-key.js/blob/master/packages/x25519/src/__tests__/jose.test.ts#L27

reason being that handing a developers some bits and instructions to go find a library that does ECDH KDF / A256KW themselves... seems like a bad idea.

I suppose web crypto developers are screwed here.. they will be forced to solve this issue, but vanilla jose developers could simply import a popular jose library, do key conversion from base58 to jwk.. and be capable of standards based encryption with dids.

I think we might want to consider this approach when considering names for keys, KeyAgreementKey.

dlongley commented 4 years ago

@OR13,

reason being that handing a developers some bits and instructions to go find a library that does ECDH KDF / A256KW themselves... seems like a bad idea.

I suppose web crypto developers are screwed here.. they will be forced to solve this issue, but vanilla jose developers could simply import a popular jose library, do key conversion from base58 to jwk.. and be capable of standards based encryption with dids.

The Web Crypto API deriveKey method should never be used with ECDH -- it's a mistake and unsafe. See: https://github.com/w3c/webcrypto/issues/193#issuecomment-396075911 (and the rest of the thread if you want)

I agree that we should have APIs that simplify all of this for users so they can't get burned. I am also pointing out that the lower level primitives still need to be there so that things can be combined according to the latest expert advice. This is the same advice given in the above thread. There absolutely should be higher level APIs for common use (which is what minimal-cipher tries to provide with its encrypt/decrypt APIs). The KDF choices, etc. are not exposed there.

I think we might want to consider this approach when considering names for keys, KeyAgreementKey.

I'm not quite sure what you mean here, but if you mean that we should lock in all of these parameters (such as KDF choice, "apu"/"apv" and so on) for a given key type, I'm +1 to that. The average user should not have to concern themselves with ensuring that their shared secret bits of security are "uniformly distributed" and that they have incorporated enough of the public key information into the KDF process to "avoid subtle vulnerabilities".