whyoleg/cryptography-kotlin

Support Diffie-Hellman (DH) key agreement

Opened this issue · 3 comments

Hi, thank you for this awesome library!

One algorithm that I'd like to see implemented is plain Diffie-Hellman (DH).

Reason: As of now, even though ECDH is supported, DH is still required for a compliant SSH implementation (see RFC 9142, §4, diffie-hellman-group14-sha256 is MUST).

I did some preliminary research and it seems like this is the support on different platforms:

  • JDK: ✅ (via SunJCE JCA Provider)
  • OpenSSL: ✅
  • CommonCrypto: ✅
  • CryptoKit: ❌ (but as I understand it, CommonCrypto or OpenSSL could still be used as fallbacks on an Apple platform)
  • WebCrypto: ❌ (but https://www.npmjs.com/package/diffie-hellman exists)

Therefore I think it could be implemented by adding it to the JDK, OpenSSL and CommonCrypto providers, covering every platform except for web. The diffie-hellman npm package seems to wrap an integrated implementation on NodeJS but is a plain JS Impl for Browser (because WebCrypto does not support DH). I wouldn't consider a self-made plain JS implementation secure in regards to XSS or sidechannel/timing attacks, there is also a story about a vulnerable DH implementation in Firefox, which was removed. So, if this package is used, the web impl should atleast have some delicate API annotation warning about security considerations.

Generally speaking, I'd consider DH as a legacy algorithm (thanks to ECDH) but still required for certain protocols.

I'd be interested in helping with the implementation, if someone could give me some pointers on where to start. Should I open a new issue for this?

Originally posted by @RaphaelTarita in #15

Thanks for the interest in the library and helping with implementation! I agree, that it should be fine to support it in those three providers: JDK, OpenSSL and CommonCrypto.

I've prototyped an API for DH previously when designing the ECDH and key agreement API, so I do have some ideas on what the API should look like.
Overall, the API should look very similar to ECDH, with the only difference that we need to support an additional step: DH parameters generation and probably also DH parameters encoding/decoding into DER and PEM (https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf)
And for this, we need to extend the current key encoding/decoding/generation APIs a bit.

I've prepared a fast POC API here: 9fa609d
You can try to implement DH based on this API, and later, we will be able to validate it on the real implementation and make changes if needed. Feel free to ask any questions!
I will help with the contribution!

Hi, thank you so much for the prep work! I hope I can get to trying out some stuff today.

Just generally speaking, what is your opinion on how we should handle the web target(s)?

  • Option A: No DH provided on web targets, document reasoning
  • Option B: Provide DH via diffie-hellman npm package, including explicit warnings (@RequiresOptIn) when the plain JS impl is used (browser target), potentially in a different module
  • Option C: Provide (unsafe, unhardened) fallback kotlin impl with explicit warnings (@RequiresOptIn), potentially in a different module

Which option would you prefer? Or is there another approach you'd take?

I feel like at this moment, Option A is the best. Even now, not all algorithms are supported by web targets (using WebCrypto) in the library. And it's fine :)
Still, all algorithm definitions should be in common; it's just that the provider will not support it.
If there is a demand for DH in addition to ECDH for the web, we will consider it.