decentralized-identity / decentralized-identity/didcomm-messaging
Lack of session and expensive key agreements steps could hurt adoption
- Dominant language
- JavaScript
- Stars
- 193
- Forks
- 60
- PR merge metrics
- No merged PRs in 30d
Description
It appears that DIDComm is sessionless on purpose, see §1.3.2:
> In a partially disconnected world where a communication channel is not assumed to support duplex request-response, and where the security can’t be ignored as a transport problem, traditional TLS, login, and **expiring sessions are impractical**. Furthermore, centralized servers and certificate authorities perpetuate a power and UX imbalance between servers and clients that doesn’t fit with the peer-oriented DIDComm.
>
> DIDComm uses public key cryptography, not certificates from some parties and passwords from others. Its security guarantees are independent of the transport over which it flows. It is **sessionless** (though sessions can easily be built atop it). When authentication is required, all parties do it the same way.
At the same time, it appears that DIDComm is trying to make building synchronous RPC systems easy:
> Because of this, the fundamental paradigm for DIDComm is message-based, asynchronous, and simplex. Agent X sends a message over channel A. Sometime later, it may receive a response from Agent Y over channel B. This is much closer to an email paradigm than a web paradigm.
>
> On top of this foundation, it is possible to build elegant, synchronous request-response interactions. All of us have interacted with a friend who’s emailing or texting us in near-realtime. However, interoperability begins with a least-common-denominator assumption that’s simpler.
But currently we are requiring parties to do for each message:
- either a ECDH-1PU key agreement;
- or a ECDH-ES key agreement.
(Notice that these are built upon the original ECDH protocol meant to generate "shared session keys", and repurposed it into a mechanism to perform public key encryption of messages without having necessarily the notion of session.)
Being sessionless is nice because it allows **stateless** communications: we don't need to store the ephemeral key, nor the CEK key we're using to communicate with someone, and it also means we are not worried about long-lived keys, key rotation, IVs reuses, and so on.
But using the above algorithms can also hurt us on the performance side and cause scaling issues:
as pointed out by @vimmerru, ECDH-1PU uses 2 ECDH per participant key... which is worsened if we want to hide the sender (see #219) as it could require layering anoncrypt on top of authcrypt, thus introducing an extra ECDH step.
This is going to scale poorly with multiple recipients as is being discussed in #218.
In particular instant group messaging is more or less doomed if using DIDComm, which is a bit counter-intuitive since this repo is named "DIDComm-messaging".
This will even be worsened by the fact the we have relatively "high" security requirements and while X25519 performances might be acceptable, ECDH with P-384 is slow.
See for example [this](https://github.com/Spomky-Labs/jose/blob/master/doc/Performance.md#key-agreement) or that benchmark using [crypto-bench](https://github.com/briansmith/crypto-bench):
```
test agreement::p256::generate_key_pair ... bench: 9,665 ns/iter (+/- 1,045)
test agreement::p256::generate_key_pair_and_agree_ephemeral ... bench: 51,820 ns/iter (+/- 4,724)
test agreement::p384::generate_key_pair ... bench: 362,917 ns/iter (+/- 19,955)
test agreement::p384::generate_key_pair_and_agree_ephemeral ... bench: 708,025 ns/iter (+/- 56,641)
test agreement::x25519::generate_key_pair ... bench: 19,816 ns/iter (+/- 1,746)
test agreement::x25519::generate_key_pair_and_agree_ephemeral ... bench: 73,051 ns/iter (+/- 7,357)
```
And that's on a "modern CPU" with modern AVX2 instructions using a rust implementation... It sure could handle a chat with 10 people having 4 devices each, as that's only like `10*4*3=120` **_handshakes per message_** in a worst case scenario.
But that won't scale well with a 100 people or more. And that might hurt on JS or on embedded devices way earlier than that.
But notice that on more constrained devices, think IOT devices and such, [one ECDHE key agreement can cost easily _a few seconds_](https://datatracker.ietf.org/meeting/92/materials/slides-92-lwig-3.pdf), so sessionless DIDComm messaging would be totally impractical for such devices with our current design.
What are your thoughts?
@vimmerru proposed a few options such as:
> 1. Cache ECDH result for permanent keys
> 2. For anoncrypt(authcrypt()) mode Reuse ephemeral key for both operations
> 3. Use KDF that will allow long living keys with random nonces. For example, XC20P
On my side I can clearly see why we might want to remain stateless, thus making options 1 and 2 inapplicable... but this doesn't prevent us from having session based on some kind of deterministic KDF steps. One option we might want to consider is to have a deterministic KDF being triggered by data we keep within the message and that allows us to re-derive (cheaply) the same keys and thus keep the ability to have session-like communication, but that's complicating things.
(Also notice that elliptic curves are easy to derive child keys for from a parent key.)
So, are we aiming at being stateless or not?
If not, the above proposals seems like the best options to me, but require us introducing the notion of session in the specification, in my opinion.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.