-
Notifications
You must be signed in to change notification settings - Fork 218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC 0021 - Sender and recipient identifiers used in envelope as DID key references #104
Comments
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
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. |
Another observation with the current approach is that the |
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 |
Thanks, yes |
Signed-off-by: Daniel Hardman <[email protected]>
I've been wondering about this myself. What's the status on this? Has it been accepted? |
Note:
All this to say that it might make sense to specify senders in the plaintext messages as well under some circumstances. |
@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 @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? |
@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. |
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. |
@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 |
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 ( 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. |
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, 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
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.
|
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. |
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 keysThe 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:
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 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 DependenciesIn 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 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 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 DIDsA given key can appear in many DID Docs. 4) We're not identifyingSomewhere 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 compromiseI 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. |
@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 If this was not part of @tplooker 's original question than I can make it a separate issue instead. |
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. |
@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. |
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 |
Thanks @dhh1128, as always your articulation on these issues is second to none :). First i'd like to point out, the field 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, 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. |
@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. |
@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 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 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 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 The |
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. |
I think @tplooker is right that per the JOSE specs 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.. |
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 |
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. |
@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. |
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. |
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. |
https://tools.ietf.org/html/rfc7516#section-4.1.6 There are a couple issues here...
By default when importing a JWK in many libraries, if a Here is an example of a DID Document which supports JWK: https://uniresolver.io/1.0/identifiers/did%3Abtcr%3Axxcl-lzpq-q83a-0d5
Maybe I got this wrong when I created it, but my goals where:
With this part established, you might see JWS/JWE/JWT related to this key of the following formats: Example 1
This is what a header would look like for non did related crypto, important to note that the
The Per https://tools.ietf.org/html/rfc7515#section-4.1.4
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 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/ |
Continue issue here: decentralized-identity/didcomm-messaging#20 |
Currently at the envelope level of did comm messages, when senders and recipients are referred to, public keys are used. For example in RFC
Below is the JWE header
Both the sender and the kid for the recipients are inline public keys.
The same is present in the non-repudiation envelope RFC
Below is the JWT header
Again the recipient, identified by the kid is an inline public key.
I think all of these references should be converted to did key references as the envelope level of did comms when speaking about senders and recipients of messages should be identified via did's rather than public keys.
This is the path already taken by did-auth-jose
The text was updated successfully, but these errors were encountered: