@silverpill @raucao @lain @sozialwelten @koteisaev
Sorry for the delayed response, but yes.
The naive approach would be:
- Convert both party's Ed25519 keys to X25519 keys
- ECDH(Sender static, Recipient static) -> k
- HKDF(k) -> Shared secret
The problem with this approach is that, if either side's private key gets compromised, all historical traffic is trivially decryptable. (Static-Static ECDH)
Perfect forward secrecy (compromise of either key does not give attacker the ability to read past messages) requires at least one extra round trip, which is not great in this setting.
The tweak I suggested is:
- Convert both party's Ed25519 keys to X25519 keys
- Sender generates a ephemeral (throw away) X25519 key
- ECDH(Sender static, Recipient static) -> k_1
- ECDH(Sender ephemeral, Recipient static) -> k_2
- HKDF(k_1 | k_2) -> Shared secret
- Sender discards the ephemeral key
With this improvement, sender long term key compromise does not allow decryption of past traffic, because the ephemeral keypair is long gone into the void (one-way forward secrecy, Static-Static + Ephemeral-Static ECDH).
Note: While the theoretical safety of reusing a Ed25519 key for also doing X25519 was an open question, there are proofs that it is safe.