Closed AnomalRoil closed 2 years ago
@TelegramSam @kdenhartog @Baha-sk @dhh1128 ^ Thoughts?
Discussed in WG 20211011. Need a section in the guide about the assumptions of the discussion around PFS. We should remove the claim in the spec to clarify in the meantime.
Just to make sure we're on the same line here, not having PFS means DIDComm is either "just" a slow and expensive alternative to TLS, but with less security, or a more modern PGP without much more than newer algorithms built-in.
Indeed, any way that uses the keys in a DID to establish a TLS session is better off the bat, without need for Peer DID or anything fancy. Any connection that is expected to be interactive and not significantly asynchronous should opt for using TLS, IMO. (Do we already have a way of "converting" a DID into a self-signed TLS certificate? If not that might be a good idea to have such a thing.)
There's still the fact that DIDComm is non interactive in its key agreement, and more async friendly, allowing for "messages" to be sent easily across a variety of transports without caring about latency or so. But so is PGP. Actually from a security and feature point of view, PGP is roughly equivalent to DIDComm as far as I can tell. So, I'm not sure if the goal is to propose a "more modern PGP", or if we want to push things further.
Fixing DIDComm to include some kind of forward (and backward) secrecy is possible and might be interesting to do, but it would involve significant changes IMO.
But is that something important or not for DIDComm expected usages? (That's actually related to #245)
Actually from a security and feature point of view, PGP is roughly equivalent to DIDComm as far as I can tell.
Maybe from an encryption standpoint, but not from a transport standpoint and a protocol design standpoint, and other details. I'll have more comments on this later, but needed to point out the misalignment in this comparison.
Here, with ECDH-1PU, we are "just" in a C(1e, 2s) key agreement case (as per NIST.SP.800-56A terminology), which does not provide forward secrecy at all, as only C(2e, Xs) key agreements do so using 2 ephemeral keys: on for each party. But these are typically interactive (unless you're publishing unused pre-keys à la Signal to act as your ephemeral keys). The same is true for the ECDH-ES case as it is a C(1e, 1s) scheme.
I believe enhancing ECDH-1PU and ECDH-ES with a recipient epk
+ sender epk
will solve the PFS issue, but it will require an out of band epk
keys exchange and define how these keys are used along with the static ones (will it require upgraded ECDH-1PU and ECDH-ES algorithms using an additional kdf with the new recipient epk?). It also entails tying peer DIDs to epk
s, which means a DID is valid for the duration of an epk
which is usually valid for only 1 request. A solution to this would be to create special connection epk
field in the DID document for longer lived peer DIDs. The only issue is these epk
fields are not that much ephemeral anymore as they're persisted in the DID document.
This is definitely beyond the scope of DIDComm V2 given the timeline and the scope of changes needed to address this issue.
@AnomalRoil : I disagree with your assessment of the impact of this. You are not wrong in your analysis of the inaccurate paragraph or of why our key agreement mechanism does less than what PFS requires. But you are misunderstanding the way that session constructs can manifest in DIDComm. DID rotation is intended to be far, far easier than identity rotation or certificate rotation in TLS. DIDs can be thrown away without resetting a relationship. When that happens, you get perfect forward secrecy -- a co-opted DID today does not allow eavesdropping on old conversations. But this is not obvious when you assume that the only rotation is of something called "static keys," and the mapping for a "session" is a single one-way transmission of one message.
Without a requirement for DID Rotation (even though it's pretty easy) to occur on a regular frequency, I don't think it makes sense to say the protocol has PFS. If we were to consider placing this requirement in scope of the spec I think this would preference methods that can easily be created such as did:key and did:peer over ledger based dids which have delays in rotation or have a certain cost associated with that rotation. I'm not comfortable with making these requirements until we consider the impacts of this design choice further.
What if DIDs are only used for discovery and the 3xdh ((and) double ratchet) is applied for message encryption?
Could the protocol distinguish between interactive (Alice and Bob communicate directly) and non-interactive sessions (Alice and Bob communicate async -- one of them is offline)?
As @AnomalRoil suggested, one could have an interactive protocol if both are online Since DIDComm has mediators and mediator endpoints are/can be listed in the DID Doc., mediators could host the user prekeys (as in Signal)
Would this help to solve the problem?
-- In the libp2p+didcomm demo we worked (are working) on we took the approach summarised above
In the async case, we started to integrate the Signal Protocol (we just started);
(we plan to continue with the work)
I think this kind of approach would work fine for the next version. I'm inclined to defer such changes for a future version.
I propose that PR #307 fixes this, for now -- not that it adds PFS, but that it clarifies what the goals of PFS are, and how those goals might be achievable by users of DIDComm. We can do a more sophisticated fix in a later version.
PR #307 fixes this issue. Discussed WG 20220228.
While reviewing the spec, I noticed that it says:
This is actually wrong. It doesn't feature a triple key derivation as Signal does.
ECDH-1PU is not providing forward secrecy, nor weak forward secrecy in the case where the recipient static key is compromised. It also does not provide any backward secrecy.
That's because the sender has both an ephemeral key and a static key, and both are combined with only the recipient's long term static key to produce the shared key. This means that if the recipients' private static key is leaked, then all previous and future message meant for that recipient are compromised even without an active adversary.
Since there is no independent key material on the receiver side from one sender to the other (unless they are using dedicated Peer DIDs), compromising the long-term secret keys of the receiving DID allows to decrypt all ciphertexts that were ever sent to the corresponding public key, no matter what sender sent it.
In the Signal case, we have the so-called "one-time prekeys" that are published (and signed) and destroyed after receiving a message to ensure forward secrecy. Once a message has been decrypted on a device, there are no private keys on the device that would still allow to decrypt that message in its encrypted form. This is not the case with DIDComm.
Here, with ECDH-1PU, we are "just" in a C(1e, 2s) key agreement case (as per NIST.SP.800-56A terminology), which does not provide forward secrecy at all, as only C(2e, Xs) key agreements do so using 2 ephemeral keys: on for each party. But these are typically interactive (unless you're publishing unused pre-keys à la Signal to act as your ephemeral keys). The same is true for the ECDH-ES case as it is a C(1e, 1s) scheme.
More generally, we cannot guarantee the following to the receiving party:
Demo
keyAgreement
keyNow, Eve can decrypt all the ciphertexts C_1, ... C_4 corresponding to the messages just using the private key material she recovered in step 5. None of them is protected against this.
This isn't the case on the sender side. If Alice gets hacked instead of Bob in step 5, as long as she properly deleted ephemeral key material after sending each message, we cannot use her long-term keys to decrypt any of the ciphertexts.
Fixing this
There is no easy fix that wouldn't involve significant changes of the DIDComm protocol.
One way would be to have a similar system as Signal's signed One-Time Prekeys, but it requires a "server"/system to publish these and distributed them. It would also require significant rework of the KEX, since ECDH-1PU isn't doing a triple handshake (more like a double) and thus cannot provide FS. This would require moving to a triple handshake, so either X3DH just like Signal, or some equivalent Noise protocol ideally. (Using the Noise framework would anyway have been a good idea from the start from a "simplicity" and "security" POV.)
Another way would be to have some kind of interactive key establishment instead.
Typically using DIDComm to exchange Peer DIDs for both parties when "establishing a session" and then deleting these Peer DIDs after the end of the "session" would provide Forward Secrecy between "sessions". (As long as the Peer DIDs are then used to do key agreement for the messages in that session). This is tangentially related to #243
Any other proposals?
Notice that the lack of forward and backward secrecy also means DIDComm messaging has absolutely no interest for secure messaging, so this is an important issue IMO.
Furthermore it also makes the "expansiveness" of the ECDH-1PU handshake for each message totally unwarranted since it doesn't significantly increase the per-message security anyway.