Closed frankhinek closed 7 months ago
It is helpful to specify alg
and I believe we should require it. Assuming you agree with that we have two possible avenues to explore:
The simplest way to do this would be to add a column to https://did-dht.com/registry/#key-type-index where we specify the associated alg
in accordance with the verification relationship type. I believe that this reduces implementation/usage risk.
For example, if you are using an Ed25519
for authentication
or assertion
then EDDSA makes sense.
If you are doing key agreement
then ECDH
makes sense, but you should probably specify X25519 (related: #47).
This removes the need to maintain a registry and gives implementers full control over specifying what they wish to. The risk here is ambiguity if it is unspecified, so we may need to make it a required property.
Open to other ideas as well!
cc: @selfissued it would be great to have your input here
If there's any chance of algorithm ambiguity, it's better to include "alg" in the the JWK than not.
@selfissued @decentralgabe It may be that we're saying the same thing or perhaps that there's a nuance that we should explore to work towards alignment.
The concern raised above is that there are cases where it is not possible to safely assume the alg
based solely on the JWK's kty
and crv
.
Let's start with an example where it is safe to assume the alg
given that a DID DHT document contains a verification method with the following public key material:
"publicKeyJwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "375SKiRFNsqZkAxD1pp4y-uWVFPG0jUsLQOe3inWPnU"
}
In practical usage, the alg
could be safely assumed to be EdDSA
(or Ed25519
given draft-ietf-jose-fully-specified-algorithms-00) based solely on the curve property Ed25519
.
An implementation of DID DHT could be written to automatically include alg: EdDSA
(or alg: Ed25519
) when expanding a DID with this verification to a DID document (i.e., read operation / resolve
function).
IMHO it is not safe to assume any specific alg
based solely on this public key:
"publicKeyJwk": {
"kty": "EC",
"crv": "secp256k1",
"x": "qTH-IrSngh6_rmWdT9itRYmmmdbaVkhJlhu_8I6rzDk",
"y": "t2tpsM53facozLz9MmOrd7hzorveQ7-vclyFnZkthtk"
}
While it is possible/likely that the alg
is ES256K
it could very well be intended for use in key agreement with a variant of ECDH or perhaps used for ECIES. There are algorithms that such a key could be used with that don't yet have JOSE / COSE registered algorithm names (e.g., Schnorr signatures). As. consequence, It does not seem like the DID DHT specification should advise that implementations automatically assume ECDSA usage whenever crv: secp256k1
(or secp256r1
) is present in a verification method's material.
We could consider attempting to deduce alg
values based on some combination of what is present in the JWK and whether the method appears in a particular verification relationship, but even then, you can't always deterministically select the alg
.
@frankhinek there is some nuance, so thanks for writing this out. I agree with you that it's not safe to assume alg
based solely on the kty
and cty
. That's separate from the statement we should always specify alg.
So how about a new proposal: alg
must be specified for all key types?
To reduce the burden on implementers we could have suggested default types that are implied unless overwritten (this would also save bytes), but this does add some complexity. I am also fine to just always include the alg
property.
Good suggestion.
One open question that raises is what implementers should do in the event that the alg
value they wish to use is not yet registered? Presumably we should encourage use of registered algorithms but permit usage of any public alg
values given that they are "understood and processed by implementations".
There are a number of alg
values that have been in draft for an extended period of time. For example:
alg
values from those expired drafts are in use by practitioners today and yet still are not listed in the IANA JOSE registry. Several alg
values have found their way to COSE but have yet to be registered in JOSE (some but not all of the below).
One additional reason to NOT require that alg
be specified in the DID document for all key types:
alg
values over its lifetime. Implementers would either have to reject otherwise valid messages due to an alg
mismatch OR would have to ignore the alg
in the DID document (which calls into question, why even have it specified?)For example, let's say this you control this DID:
{
"id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
"controller": "did:example:abcd",
"alsoKnownAs": [
"did:example:efgh",
"did:example:ijkl"
],
"verificationMethod": [
{
"id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0",
"type": "JsonWebKey",
"controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
"publicKeyJwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE",
"alg": "EdDSA",
"kid": "0"
}
},
{
"id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#example",
"type": "JsonWebKey",
"controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo",
"publicKeyJwk": {
"kty": "EC",
"crv": "P-256",
"x": "j3cCDZFyaC-EucYxsrt3Wen42S1uWV8W_pZyuHrboRk",
"y": "QqDEUuwZhrSE6zECuzxjRNw0erMsksvPT6uegReh2Vs"
}
}
],
"authentication": [
"did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
],
"assertionMethod": [
"did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
],
"capabilityInvocation": [
"did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
],
"capabilityDelegation": [
"did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0"
],
"keyAgreement": [
"did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#example"
],
"service": [
{
"id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#service-1",
"type": "TestService",
"serviceEndpoint": [
"https://test-service.com/1",
"https://test-service.com/2"
]
}
]
}
Initially, an app using DIDComm messaging uses the P-256
key identified by #example
for anonymous message encryption. All JWE's use an alg
value of ECDH-ES
and all recipients of said messages can verify the alg
matches the value present in the DID's document.
Then the app needs to transmit a message using sender authenticated encryption which mandates using the alg
value ECDH-1PU
in the JWE. What happens? Does the DID document need to be updated and re-published to the DHT so that the recipient can verify the message? Or does the recipient ignore the alg
mismatch between the JWE they received and what is in the DID document?
The next message needs to use anonymous encryption with an alg
of ECDH-ES
. Same question arises: update the DID document again or should other entities ignore the alg
mismatch?
Some days later another entity needs to send this DID a wrapped key and wants to encrypt it using a JWE with an alg
of ECDH-ES+A256KW
. What happens in this case? Can the sender use the #example
verification method key for this purpose or does it fail because the recipient doesn't have any verification methods in their DID document that support ECDH-ES+A256KW
?
This issue would repeat with every variant of alg
that is compatible with a given JWK (e.g., ECDH-1PU+A256KW
, etc.)
I believe this is one of the reasons that alg
is NOT a required property of a JWK but is a required property of both JWS and JWE. Mandating that implementers always include an alg
in the verification material of DID DHT documents may create more potential for issues / ambiguity rather than diminishing it.
Even with the case of Ed25519
keys that are, in practice, only ever used with EdDSA
: What happens when the new Ed25519
algorithm value starts being used if draft-ietf-jose-fully-specified-algorithms is adopted? There will be a period of months/years when libraries that developers use to work with JWKs, JWS, and JWE will only support an alg
of EdDSA
while others will be updated to use Ed25519
. What should implementations due as a result of these alg
mismatches? In other words, even if DID DHT specific libs were updated immediately that doesn't mean the ecosystem of many other libs across a dozen languages is going to snap to the new standard overnight.
One solution (albeit impractical to adopt) is for the alg
property to have been specified as an array to identify the algorithm(s) with which the key is intended to be used, much like was done for key_ops
. I'd imagine there was vigorous debate at the time when RFCs 7515-7520 were being drafted and perhaps revisiting why alg
remained an optional property of JWK could be helpful context.
because alg
is a string the array property wouldn't quite work, though that was my initial thought too.
this is clearly a complex problem, as you have outlined. my gut says - if you want multiple algorithms for a key specify that key multiple times with unique KIDs and algorithms. of course that will conflict with our guidance on using the thumbprint, and further complicates things.
what I'm still going back and forth on is whether it's better for implementers to specify the alg they're using in the JWK itself or to leave it empty intentionally. perhaps we allow it as an option, but ... then we should have some language around scenarios where the same key is used with multiple algorithms.
let's find some time to discuss with @selfissued to hear his expert perspective here
A key listed as a verification method in a DID Document may be used with multiple alg values over its lifetime.
Use of keys for multiple purposes and especially with different algorithms is a known bad security practice. Our design should explicitly forbid that.
There are a number of alg values that have been in draft for an extended period of time. For example: https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04#section-2 https://datatracker.ietf.org/doc/html/draft-amringer-jose-chacha-02
alg values from those expired drafts are in use by practitioners today and yet still are not listed in the IANA JOSE registry.
There's nothing magic about getting algorithms registered with IANA. It requires creating/finishing a draft that does so. If there's business need to use some of the algorithms, as opposed to the already registered ones, drafts could be created to do that. That said, if there's not a compelling need for them, there's not a good reason to do that work. We could discuss particulars, as appropriate.
Several alg values have found their way to COSE but have yet to be registered in JOSE (some but not all of the below).
As above, if there's a business reason to use these in JOSE, drafts can be created to register them. That's particularly easy now, with the JOSE working group being active again. Again, I'd be glad to discuss motivations for using particular algorithms.
What happens when the new Ed25519 algorithm value starts being used if draft-ietf-jose-fully-specified-algorithms is adopted?
It has been adopted and is now https://datatracker.ietf.org/doc/draft-ietf-jose-fully-specified-algorithms/. Feedback on the specification is welcomed.
Context
Test Vector 1 and Test Vector 2 include 'alg' properties in the example DID Document even though this information is not encoded in the Pkarr / DNS packet:
Question
Should
alg
be omitted from verification method JWKs in the DID Documents produced by DID DHT Resolvers and Clients?The
alg
property is optional in JWKs and primarily becomes relevant in the context of using the verification method material with a specific cryptographic algorithm. While in the case ofEd25519
keys, they are commonly used with theEdDSA
algorithm, but that need not always be the case. In the case ofsecp256k1
andsecp256r1
,ECDSA
is the most commonly used algorithm, but others such asECDH
orECIES
cannot be ruled out.It seems we ought to omit
alg
from the DID DHT specification and any examples to minimize the confusion that implementers should be automatically assuming an algorithm when reconstructing a DID Document.