Coder Social home page Coder Social logo

Comments (30)

tplooker avatar tplooker commented on June 14, 2024 2

@llorllale my opinion is for us to use did key references or a did url as the identifier. Otherwise we are not leveraging did's as the identifier instead we are just using public keys.

The only resistance I have heard to this approach is that resolution now becomes a concern at this layer and what happens in the event this resolution fails for whatever reason. My response to this thinking is that, if we accept we want to refer to subjects as did's in the ecosystem (e.g is a relationship/connection between two dids not two sets of keys) then the reconciling of a public key to a did must happen somewhere and not doing it at this layer IMO is essentially kicking the proverbial can down the road for little benefit.

Another point to make is in a messaging protocol that uses public keys instead of dids as the referent for subjects at this layer, it then begs the question whether didcomm should really be called crypto-messaging or something that more accurately portrays that fact?

@dhh1128 @kdenhartog @TelegramSam @swcurran does any one else have some thoughts or opinions on this topic, it feels like this is a priority for us to discuss at the moment due to the fact @kdenhartog is reviewing the crypto envelope format and @llorllale and team are current building an implementation of this layer in go?

from aries-rfcs.

dhh1128 avatar dhh1128 commented on June 14, 2024 2

Okay, we have two interesting and rich comment streams going on, on related topics. One is here, in this issue, and one is in issue #201 . I am going to put the bulk of my comments here, and cross-reference them from the other issue, so I don't make redundant posts.

1) DID key references versus actual keys

The phrase "DID key references" in this issue title promotes the assumption that the encryption envelope should reference a key, and perhaps that caused my previous comments to be misunderstood. I am actually less concerned about the particulars of a mechanism for referring to keys, and more concerned about the assumption that an envelope should have references in the first place. I claim that an encryption envelope should contain a key value, not a key reference, and that the indirection is a mistake.

To see why, let me pose a situation in which indirection is used:

  • Alice sends a message to Bob. She encrypts a message with the keypair that is currently known as "foo" in her DID doc. The encryption envelope is built in the way this issue proposes -- the kid field in the JOSE header contains a reference to <alices-did>#foo or similar.
  • The message gets to delivered to Bob's mobile phone, but the phone is turned off while it charges.
  • Alice rotates the value of <alices-did>#foo. (Note that ability to change what #foo means in a DID doc is explicitly a feature in the DID spec, even though I tried to argue that the binding between a key's id and its value should be immutable.)
  • Bob turns on his phone, and the agent software on that phone now attempts to decrypt the message. It uses its DID resolver functionality to dereference <alices-did>#foo, gets a public key value, and attempts to verify that the message was in fact sent by that key. But of course it fails, since the value it gets from its dereference is not the value the message was encrypted with.

In my mind, this is an error. The validation question that should be asked on decryption is not "Did Alice's current 'foo' key encrypt/sign this?" but rather, "Was this encrypted/signed by a key that Alice called 'foo' at the time she sent the message?" This MUST be the question--otherwise you can't analyze historical communication, have an audit trail that makes sense, etc.

If you simply placed the key value in the JOSE header's kid field, this problem never happen; whether Bob decrypts instantaneously or a year or a decade later, you know exactly which key value was used to encrypt.

Now, you could say, "well, we'll simply say that the dereference must always be contextualized by the time that the message was sent." To that, I say: A) timestamping robustly in decentralized fabrics is really, really hard; B) what field in a JOSE header are you going to use to express the timestamp? It seems to me that it's far better to start from the actual key value that was used, and then check to see whether it's believable that it was the correct key value in a fuzzy time range, instead of starting from a key reference, and then hunting around for a key value that might have been current in approximately the right timeframe.

2) Circular Dependencies

In the TCP/IP stacks in all OSes I know, there are layers where hostnames can be used, and there are layers that require an actual IP address. At a high level, in an HTTP host header, or in the posix gethostbyname() function, using hostnames is fine (but optional). But on the wire, in actual packet addressing, it is not valid to use hostnames; at that layer, DNS and hostnames are not a thing. Only the IP address matters.

If we changed that--if the IP layer allowed hostnames in packets--then the IP layer would get a dependency on DNS. This would be fatal for performance. It would drastically complicate caching logic. It would also create a royal mess in implementation code. All the high-level code that deals in hostnames would now sit both above and below the IP layer. The lean, high-performance firmware implemented in specialized chips for IP routing would now need to link against complex libraries--much of it even higher level than the OS kernel--that is slow, non-deterministic, and much easier to hack.

The IP protocol was designed with a carefully constrained scope to avoid exactly these problems. At the level of IP, you "only" have to route to IP addresses, and if I put on my software architect hat, I think that's a very, very good thing. The internet is complicated enough as it is, without making things a hundred times harder.

Now, the parallel to crypto and DID layers is instructive. Crypto is like the IP protocol. DIDs are like TCP or HTTP -- something that sits above crypto and depends upon it.

The crypto envelope in DIDComm is very low level, and that's a good thing. The primitive that encrypts or signs something doesn't take a DID or a key reference as input. It takes a key value. The math involved demands exactly and only that key value. Anything else is extraneous. By constraining the crypto envelope to take this input, we are preventing the crypto layer from incurring a compile- and run-time dependency on the DID layer, which should sit above it. DIDs depend on crypto--not the other way around. The DID layer is exceedingly complex. It is network-sensitive, susceptible to timeouts and retries and hacking, requires a JSON parser that is aware of JSON-LD contexts, has varying levels of trust from different blockchains and different remoting configurations, etc. The last thing we want to do is take a purely mathematical operation and give it a dependency on something like that.

I get that did:key avoids many of these problems. Essentially, it's like saying, "Hey, let's embed hostnames in IP packet headers. But don't worry, these will be specially formatted hostnames that you can convert back into what you really want--IP addresses--without a lot of bother." My response is: this would bind all DIDComm envelopes to one particular DID method (bad in itself) that isn't mature (separately bad) and that then affects the versioning of all of DIDComm as it evolves (separately bad) -- and what benefit are we accruing with this weird kludge?

Sam has argued that the self-describing nature of DIDs is a desirable property, and I agree. If an indirection (referring to keys by reference) were actually useful in the crypto, I would feel differently. But the indirection is problematic (my point #1 above); we can only use it if the indirection is degenerate or lacks the very self-describing property Sam is touting. And this self-describing property is not not desirable from the standpoint of a crypto algorithm that only wants a key as its input. That desirability should manifest at a higher level, not when you're doing crypto. Pushing DIDs into the crypto layer destroys encapsulation.

3) One key, many DIDs

A given key can appear in many DID Docs. did:key:abc123 of course resolves into its own generated DID doc--but it can also appear in the authentication section of Alice and Bob's and Carol's DID docs. So even though we can turn such a key reference into a key with a degenerate resolution, and even though we could kludge our way past the timestamp problem, we don't actually know which DID doc's history to use to evaluate the rightness of using that key. I think that if we explore the implications of this a bit, we'll conclude that many of the benefits of a self-documenting DID are actually illusory here.

4) We're not identifying

Somewhere in the comment stream of this ticket or the other, someone suggested that what we're trying to do here is "identify" a key. This may be at the heart of my disconnect. I don't think that's true at all. We don't actually care about the identity of a key, and we're not trying to equate that key with an agent. The key is not an alternative or replacement identifier for anything. It's a key value -- a number needed as input to a crypto algorithm. Nothing more.

5) A compromise

I wouldn't be strongly opposed to the notion that a JOSE header could express the key value that was used to encrypt (this is an absolute requirement, IMO), and also supported an optional, auxiliary header that could give a reference for this key ("Identify" the key) in a larger context. That might have some benefits. But we should not be confused about which of these fields is input to the crypto function.

from aries-rfcs.

dhh1128 avatar dhh1128 commented on June 14, 2024 1

The encrypted envelope in DIDComm is a crypto construct, atop which a DID-aware construct can be built. As a crypto construction, it doesn't know about DIDs. The crypto layer can't depend on the DID layer. Ignoring this rule will create a circular dependency hairball.

The pack() and unpack() functions should take keys, not references to DID keys and not DIDs that happen to be keys (did:key) and should represent those keys as keys (using multicodec), not as anything else.

I don't think this is even slightly controversial. It would take a lot to convince me otherwise. Nothing in this thread has budged the needle for me yet.

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

The other option is to make this behaviour non-binding, take the following example of the non-repudiation envelope

The JWT header could be extended

{
    "alg":"EdDSA",
    "kid":"FYmoFw55GeQH7SRFa37dkx1d2dZ3zUF8ckg7wmL7ofN4",
    "did_ref" : "did:example:12345#key-1"
}

This would allow the envelope layer proccessing to validate the key (identified by the kid) signed the message without resolving the did, however the processing can still also optionally resolve the did via the reference and return the assertion that the signer of the message was also a did subject.

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

Another observation with the current approach is that the alg property becomes the definer of the cryptographic primitive used with kid. If a did key reference is used, then this information can be found when the public key is resolved from the did doc.

from aries-rfcs.

peacekeeper avatar peacekeeper commented on June 14, 2024

Just a quick note that what you call a did key reference is a form of a "DID URL" (see Generic DID Syntax).

There's also an example similar to yours in the DID Resolution spec: https://w3c-ccg.github.io/did-resolution/#example-3

I think this could also be used directly as the kid, instead of introducing a new did_ref field, no?

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

Thanks, yes kid as a did url is my preferred option too, I was just pointing out that a separate field for the did url could yield benificial in the event the did url wasnt resolvable.

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

@tplooker @kdenhartog

I've been wondering about this myself. What's the status on this? Has it been accepted?

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

Note:

All this to say that it might make sense to specify senders in the plaintext messages as well under some circumstances.

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

@dhh1128 @kdenhartog @TelegramSam @swcurran I'd really appreciate guidance on this topic since we're about to reach the point in our development where we can no longer ignore this question.

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

This is related to this issue. #130 (comment) Where it is suggested that using the query string in a dud-URL’s would be on way to convey the crypto suite type for public keys making them boyh future proof and self contained. Reloution isalso aenabled. In general public keys should be DIDs for these reasons this may mean we need and ephemeral did method that is extremely lightweight but allows future proofing via crypto suite parameterizatio and also enables derived DIDs using similar mechanism.

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

@SmithSamuelM what would prevent you from miss reporting the crypto suite and associated information? In regards to ephemeral did's this is the intention of did:key I believe, which I am interested in using in the following ways

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

I agree with some of your assessment, however could you give an example of how this creates a circular dependency?

I think evidence with did-auth-jose git-did minimal-cipher and the SIOP-interop-project all of which use JOSE in one form or another and substitute the sender and recipient identifier fields with dids demonstrate that this can be implemented without a circular dependency i'm aware of.

Lets take packing an auth-crypted DIDComm message for example, if the arguments to pack a message instead of being a key were based on did-urls, the sender would resolve the did-url to get the public key and proceed with the message packing, following this in the recipients block,
they would quote the did-url in the kid field and their own reciprocate did for the connection or relationship in the sender field.

The recipient receiving the message would then iterate through the recipients block looking for a did they possessed keys to, if found, fetch that key from their wallet and decrypt the message. If the message was auth-crypted they would resolve the senders identifier and use that in combination with their private key they had already fetched to decrypt the message. In the process of doing this the resulting decryption would yield sender and recipient information in the context of did's rather than public keys.

Further more if we look into the JOSE specs.

To your point to about the encrypted envelope, yes it is a crypto construct but the kid field to quote the JWE spec

    The "kid" (key ID) header parameter is a hint indicating
    which key was used to encrypt the JWE. This allows originators
    to explicitly signal a change of key to recipients. The interpretation
    of the contents the "kid" parameter is unspecified. This header parameter 
    is OPTIONAL. 

Nothing precludes using an did-url as the identifier here rather than a public key.

On the sender/signer side with JWS's, this spec shows that having a resolvable identifier in the JOSE headers is encouraged, so that the product of verifying is not a public key but some other identifier to which someone is known by, in this case it is a URI.

4.1.2.  "jku" (JWK Set URL) Header Parameter

   The "jku" (JWK Set URL) Header Parameter is a URI [RFC3986] that
   refers to a resource for a set of JSON-encoded public keys, one of
   which corresponds to the key used to digitally sign the JWS.  The
   keys MUST be encoded as a JWK Set [JWK].  The protocol used to
   acquire the resource MUST provide integrity protection; an HTTP GET
   request to retrieve the JWK Set MUST use Transport Layer Security  

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

I am also curious regarding this circular dependency - I don't see it either.

More importantly though I am puzzled with using keys as identifiers when 1) we already have the concept of a DID, and 2) keys can be rotated.

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

@dhh1128 I can now see why it's not a good idea to identify the sender and recipients in the encryption envelope after reading your points (nevermind the fact that these headers aren't actually encrypted, thus eroding privacy).

The question that is not answered yet (and what I think @tplooker is asking in the opening comment of this thread) is how do we identify the sender of a DIDComm message?

Let's take a random example: my Agent receives a query message of the discover-features protocol. How can my Agent tell who sent this request?

If this was not part of @tplooker 's original question than I can make it a separate issue instead.

from aries-rfcs.

swcurran avatar swcurran commented on June 14, 2024

For your agent to have received a DIDComm message, your agent must have a connection established with the other agent/entity. For that, your agent must have created a keypair, put the public key into the did:peer and delivered to the other party. The sending agent would put into the message the public key (the one we're talking about) from their version of your did:peer DIDDoc. You would look up the key and find the related did:peer connection for that key. When you respond, you would use that connection.

If the message was signed, you could check the signature using the key you have in the did:peer for the connection from the other entity.

from aries-rfcs.

llorllale avatar llorllale commented on June 14, 2024

@swcurran Daniel's point number 4 above states explicitly that the key inserted in the encryption envelope is not meant to be used as an identifier.

from aries-rfcs.

swcurran avatar swcurran commented on June 14, 2024

I think Daniel is talking about something being more significant than a key used in the encryption of a message. No matter what, you have to look up the private key based on the public key. I don't think associating the key with a connection is inconsistent with what he is saying, but I'll leave it to him to explain.

The important point is that we don't want to use a DID for this. And in the related issue on this topic, I don't think we want to use a DID (even did:key even though it's not a DID) for an inline key.

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

Thanks @dhh1128, as always your articulation on these issues is second to none :). First i'd like to point out, the field kid is an identifier as the name key identifier suggests so we do have identifiers at this level and further more the JOSE spec does leave it free to elect what identifier to use here. The purpose of this identifier is for the sender to indicate as a reference what the recipient needs to use to decrypt the message. Its often convenient for this to be a public key, but it is important to note this is still acting as a reference to the private key in the same way a did key reference would be. If the kid was a did key reference, there is no resolution required for this step, provided private keys are index/tagged with the DID they are associated to in your wallet.

For example if I received an anon-crypted message from a party, as the recipient of that message I do not need to perform DID resolution, the kid would be a reference to a DID im in control of and I would simply fetch the private key from my wallet that represents that key reference.

I understand the other points you raise, however none of the above explanations answers the simple and original question that @llorllale re-referenced, how do we identify the sender of a DIDComm message? And when I say identify to be explicit I'm talking about reconciling a subject to the main identifier I will know them by aka their did.

Granted if we decide no-identification should happen at this crypto layer, we should still expose sufficient information to be able to reliably identify and reconcile the did-key link at the next level and at the moment without did key references I really don't see how this is possible in a scale-able manner.

Take the following example.

Say I'm in an n-wise relationship (e.g 50 people) whereby we all know each by DID's constructed for that relationship. I receive a message encrypted to my DID representing me in that n-wise relationship, how do I now know which out of the 49 people possibly sent me that message. Obviously the default answer is to iterate through 49 DID docs looking for a link to a public key I recovered from the decryption, but is that really a feasible and scale-able solution?

Another example, I get a non-repudiable based DIDComm message un-encrypted sent to me via email or text which is an ephemeral proof request, who sent this request, a public key? How do I establish a basis for making a decision on whether to respond? If there was a did key reference here, I can then discover information about that did e.g from public credential registries or a did to domain lookup.

from aries-rfcs.

tplooker avatar tplooker commented on June 14, 2024

@dhh1128 to the compromise you offer at the end of your previous comment, as I alluded to at the start of this issue I am more than happy to make this behavior non-binding, what I mean by that is include both the public key and the did key reference in the envelope, that way I believe we can achieve the best of both worlds.

from aries-rfcs.

dhh1128 avatar dhh1128 commented on June 14, 2024

@llorllale and @tplooker If you are using pairwise DIDs, then the DID/keys that receive the message identify the sender. If Alice uses pairwise DID X and keys 1 and 2 with Bob, and pairwise DID Y and keys 3 and 4 with Carol, then when she receives a message encrypted for DID Y and key 3, she knows it is from Carol. She can confirm this by checking that the key that signed/encrypted the message appears in Carol's DID doc. She doesn't have to exhaustively cycle through thousands of her relationships to figure out the sender; the target key(s)/DID tell her immediately. Most agent code uses public keys for either sender or receiver as equivalent indexes to relationships in exactly this way.

But Tobias's example of n-wise isn't addressed by this answer. Even though N-wise with N=50 is highly unbelievable--n-wise is nearly always going to have N=3 or N=5 or some other, much smaller number--this is a reasonable argument for what Tobias has been advocating.

If the message is sent by a party who wishes to remain anonymous, then this technique doesn't work, either. And it's not supposed to--to remain anonymous, the sender can't be identified. So I'm ignoring the relevance of that situation.

Most messages sent to public DIDs should fall into this same sender-intends-to-be-anonymous category. A public DID can receive an invitation to connect from an unidentified sender; the sender's identity gets constructed later. A public DID at an automated weather station could receive a request for a weather report from a party it doesn't recognize (whether the other party is using an ephemeral DID, a peer DID, a permanently registered public DID, or not DID at all--just keys)--in which case it will respond without doing a DID resolution, using the ~service decorator that Tobias has been exploring on issue #201 .

Tobias's other case--the ephemeral proof request--doesn't resonate for me, but a variant of it does. The reason it doesn't resonate for me as described is that to decide whether to reply to the proof request, I don't want a key reference; I want a DID itself as well as maybe other info like a description of why/how the proof request will be used. Conflating the key value, which I need for cryptographic operations like decryption and signature verification, with the metadata that I need for deciding whether to respond, is mixing two concerns. The job of the cryptographic envelope is to provide cryptographic guarantees, not to answer trust questions that belong to higher level protocols. So I think the answer to the question "how should I decide how to respond" is: "based on info in the decrypted/signature-verified message". That could include the ~service decorator or other things that we add there.

But I said that I do believe in a variant of the use case. If the question is changed to, "How should a routing agent decide if it will apply policy and route this message to the recipient's mobile phone?", NOW I think Tobias's point is pretty strong. At the level of DIDComm routing, higher-level trust questions should be invisible--but lower-level trust questions based purely on cryptographic properties are perfectly reasonable. A routing agent could have a policy that says, "never route messages that purport to come from a DID that's not on my whitelist", or "route messages from unfamiliar DIDs only between the hours and 9 am to 5 pm".

So that's a long way of me saying: "Okay. I could buy the desire for a field--maybe sid for sender id--in which a sender could make a claim about who sent the message. And the format of the field could be a DID or a DID URL that references a key."

This field would be ignored by the cryptographic methods. Those have no dependence on DID resolution--even the short-circuited variant of it offered by did:key. (Only the DID resolution layer should know that did:key short-circuits normal resolution, so even this short-circuit still introduces compile- and run-time dependencies on DID resolution, despite its low execution cost.) The input to the cryptographic methods is always kid, which always contains a multicodec-encoded public key value that identifies a key pair--it is never a DID or a DID key reference that introduces additional indirection, and it is not an identifier for a person or an agent--it is just an identifier for a key pair. When the cryptographic operation is signature verification, this public key value is to verify that the corresponding private key did the signing. When the cryptographic operation is decryption, this public key is used to verify that its corresponding private key carried out the encryption. This kid field is required, never optional and never empty unless a message is neither signed nor encrypted.

The sid field then becomes a way to ask non-cryptographic questions about the message, such as "Who does the sender claim to be?" Such a question could be tested by comparing the kid against the DID doc implied by the value of sid. You could examine the sid field and make policy decisions either before or after you do the cryptographic operations of verifying a signature or decrypting.

from aries-rfcs.

dhh1128 avatar dhh1128 commented on June 14, 2024

The only downside of this solution is that we have created a new field. This is allowed by JOSE, but it takes us further away from JOSE's standard behavior, not closer to it.

from aries-rfcs.

peacekeeper avatar peacekeeper commented on June 14, 2024

I think @tplooker is right that per the JOSE specs kid is for key references (e.g. DID URLs), not for key values. So if a key value rather than a key reference should be included in the message, then that's what jwk is for. Unfortunately as the name implies that would contain a JWK rather than a multicodec'd key value. So neither of those fields may be entirely correct in JOSE :(

I like @dhh1128's points about having a clean separation between the crypto layer and the DID layer. I have a few more thoughts on that but need to organize them first..

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

This discussion is very useful with lots of thoughtful comments. Instead of reproducing it all here. A lot of my comments are towards using DIDs as "unified" identifiers. The motivation for this arises from the idea that the internet is "broken" because the trust basis for interaction on the internet is broken. A solution which encompasses all the ways it is broken is to use unified self-certifying identifiers everywhere. Self-certifying being the important feature. This is a type of identity based crypto. This extends to zero-trust computing. Ephemeral DIDs as conceived in the unified identifier concept fill important roles. The motivation for making them DIDs and not some new identifier class is to share tooling and infrastructure but the semantics are a subset of full fledged DIDs. So if the discussion is that DIDs need to be more narrowly defined then the answer is to create a new class of identifier that is very DID like. If the answer is to maximally share tooling then the answer is to add a new DID method that enacapsultes the semantic differences from other DIDs. The semantic and functional differences are sufficient to make ephemeral DIDs work. Much of the discussion is conflating the definition of full fledged DIDS (narrowly defined) to what an ephemeral DID would look like. Identity based crypto encompasses the crypto layer @dhh1128. In this sense its more the characteristics of the particular identifier used for crypto than a separation of kind. See these two references for some background on DIDs as unified identifiers. Also on subject. I am using DIDs in a general sense as unified identifiers which means the "subject" could be any item of data. What I mean by "UNIFIED" identifier can be found in these references

https://github.com/SmithSamuelM/Papers/blob/master/presentations/DID_Everything_OpenWest2019.pdf
and
https://github.com/WebOfTrustInfo/rwot7-toronto/blob/master/final-documents/A_DID_for_everything.pdf

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

I see DIDs as a way to generalize the concepts of identity based crypto in very synergistic ways that also maximally leverages web 2.0 infrastructure.

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

@dhh1128's points about having a clean separation between the crypto layer and the DID layer is in my mind valid for narrowly defining DIDs. But if we are exanding DIDs to include an ephemeral class of DID then they separation no longer applies. The whole point of identity based crypto is to embed the crypto in the identifiers. In another sense it means that anywhere you see a public key then you have a place for identity based crypto. The identifier is the crypto layer. This bears restating.

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

The way I see it there are two fundamental issues. 1) specific to the RFC 2) Generic to using DIDs ephemerally.

If we agree that we can have ephemeral DIDs then they become a candidate for use in the RFC.

from aries-rfcs.

SmithSamuelM avatar SmithSamuelM commented on June 14, 2024

The concept of identity based crypto is to provide sufficient context in the identifier itself to perform the associated crypto operations. By embedding the crypto context in the identifier the crypto and identifier are more closely coupled which minimizes the exploit surface relative to crypto where the identifier and the crypto context are not self-contained. DIDs provide powerful ways to embed that context besides merely the DDo such as using the query parameters.

from aries-rfcs.

OR13 avatar OR13 commented on June 14, 2024

https://tools.ietf.org/html/rfc7516#section-4.1.6

There are a couple issues here...

  1. kid is used to identify keys (public and private JWK).
  2. how can a user resolve a public key, or look up a private key by kid
  3. how should kid be combined with DIDs / DDOs.

By default when importing a JWK in many libraries, if a kid is not provided, one will be generated according to https://tools.ietf.org/html/rfc7638.

Here is an example of a DID Document which supports JWK:

https://uniresolver.io/1.0/identifiers/did%3Abtcr%3Axxcl-lzpq-q83a-0d5

{
    "id" : "did:btcr:xxcl-lzpq-q83a-0d5#key-JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw",
    "type" : "EcdsaSecp256k1VerificationKey2019",
    "publicKeyJwk" : {
      "crv" : "secp256k1",
      "kid" : "JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw",
      "kty" : "EC",
      "x" : "dWCvM4fTdeM0KmloF57zxtBPXTOythHPMm1HCLrdd3A",
      "y" : "36uMVGM7hnw-N6GnjFcihWE3SkrhMLzzLCdPMXPEXlA"
    }
  }

Maybe I got this wrong when I created it, but my goals where:

  1. to not alter the default JWK that is generated by libraries (notice no did prefix in publicKeyJwk.kid), this supports compatibility with non DID crypto...
  2. DID Public Key Id property uses kid (this helps wallets handle decrypting / signing related to a specific DID.

With this part established, you might see JWS/JWE/JWT related to this key of the following formats:

Example 1

{
  "alg": "ES256K",
  "typ": "JWT",
  "kid": "JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw"
}

This is what a header would look like for non did related crypto, important to note that the kid field could be anything, it is just really helpful if its a proper thumbprint.

Example 2

{
  "alg": "ES256K",
  "typ": "JWT",
  "kid": "did:btcr:xxcl-lzpq-q83a-0d5#key-JUvpllMEYUZ2joO59UNui_XYDqxVqiFLLAJ8klWuPBw"
}

The kid field here provides a mechanism for getting the correct public key (or looking up the same private key).

Per https://tools.ietf.org/html/rfc7515#section-4.1.4

   The "kid" (key ID) Header Parameter is a hint indicating which key
   was used to secure the JWS.  This parameter allows originators to
   explicitly signal a change of key to recipients.  The structure of
   the "kid" value is unspecified.  Its value MUST be a case-sensitive
   string.  Use of this Header Parameter is OPTIONAL.

   When used with a JWK, the "kid" value is used to match a JWK "kid"
   parameter value.
  1. The structure of the "kid" value is unspecified.

  2. When used with a JWK, the "kid" value is used to match a JWK "kid" parameter value.

These 2 sentences are the most helpful. My interpretation of 1 + 2 is that "used to match" is not "MUST equal" and my proposed solution is therefore valid.

It is possible to generate a JWK where both the kid are equal, and it is possible to verify a JWS when they are not.

These examples are taken from the interop project:

https://github.com/decentralized-identity/interop-project

and

https://identity.foundation/lds-ecdsa-secp256k1-2019.js/demo/

from aries-rfcs.

TelegramSam avatar TelegramSam commented on June 14, 2024

Continue issue here: decentralized-identity/didcomm-messaging#20

from aries-rfcs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.