LoupVaillant / Monocypher

An easy to use, easy to deploy crypto library
https://monocypher.org
Other
614 stars 80 forks source link

Workarounds for missing X25519+HChaCha20? #259

Closed snej closed 1 year ago

snej commented 1 year ago

My application uses the functions crypto_key_exchange and crypto_key_exchange_public_key that were removed in 4.0. This is for compatibility with the SecretHandshake auth protocol used by Scuttlebutt. I assume that the remaining crypto_x25519 API will not be compatible.

If I can’t use that functionality, I can’t upgrade Monocypher past 3.x. Is there some workaround?

snej commented 1 year ago

Looking at commit 8ca818ac071ac92bf1f08031d953486dea62895c, I see the implementations were pretty trivial — crypto_key_exchange_public_key was identical to crypto_x25519_public_key, and crypto_key_exchange was simply

    crypto_x25519(shared_key, your_secret_key, their_public_key);
    crypto_hchacha20(shared_key, shared_key, zero);

Curious why these were deprecated or removed, since they’re safer than the remaining key exchange API, i.e. the shared secret is more random.

LoupVaillant commented 1 year ago

Ah, sorry for the break. You have it right: make the exchange, then hash it with HChacha20.

The reason for the removal of crypto_key_exchange() is that in practice you often want to hash more than the shared secret (it's often a good idea to hash the public keys as well) and when you do proper authenticated key exchange with forward secrecy and all the bells and whistles, you end up hashing several exchanges at once, and HChacha20 is utterly unsuited to that.

So in practice crypto_key_exchange() ends up having fewer and fewer legitimate uses, and is less high level than I though back in 2017. What we really want is use crypto_x25519() as a building block for proper key exchange (any decade now, pinky promise). Hence the removal.

LoupVaillant commented 1 year ago

I haven't given you the entire reason for the removal: one function is an alias. I removed all of them to facilitate bindings so it would have become a single function call. The other is (as you've seen) just 2 function calls. This makes the crypto_key_exchange*() API incredibly shallow, and that shallowness also contributed to its removal.

If that's okay with you I'll close this. Feel free to reopen if you think I missed something.