ring icon indicating copy to clipboard operation
ring copied to clipboard

X25519 (and/or ECDH in general) with static keys

Open danburkert opened this issue 8 years ago • 14 comments

Hi, while attempting to add ring as a backend to a Noise implementation, I found that ring does not support DH key agreement with static keys. Static DH is required for the protocol. Is static DH support planned? Are there any workarounds in the meantime (perhaps a way to unsafely clone the key?).

danburkert avatar Nov 05 '16 18:11 danburkert

Are there any workarounds in the meantime (perhaps a way to unsafely clone the key?).

We do everything we can do to ensure that isn't possible.

Hi, while attempting to add ring as a backend to a Noise implementation, I found that ring does not support DH key agreement with static keys. Static DH is required for the protocol. Is static DH support planned?

Yes, it is. In particular, I explicitly want to make it possible to implement Noise using ring.

Basically, we need to create a ring::agreement::StaticKeyPair to go alongside ring::agreement::EphemeralPrivateKey. In fact, ring::signature::Ed25519KeyPair isn't too far from what we need.

So, at this point, it's simply a matter of getting the code and tests written.

briansmith avatar Nov 06 '16 01:11 briansmith

To clarify some things:

  • The key generation function should be like Ed25519KeyPairs, not like EphemeralPrivateKey's generate_serializable(), which returns the key pair object and a serialized representation of the private + public key. Otherwise, the caller won't be able to save the key pair bytes to disk.
  • Also like Ed25519KeyPair, StaticKeyPair needs to save the public key within the StaticKeyPair object. This is different from EphemeralPrivateKey. EphemeralPrivateKey's public key handling is optimized for the fact that the public key is only needed once and isn't always needed at the same time as the private key. This is why we have EphemeralPrivateKey and not EphemeralKeyPair.
  • As stated above, generate_serializable() needs to give the caller a serialized sequence of bytes that encodes the key pair. That means there needs to be a function that de-serializes that sequence of bytes, again similar to Ed25519KeyPair. For now, it is OK to do this the same way as Ed25519KeyPair for X25519 keys. In the future I will almost definitely switch this to use a self-describing typed file format.
  • Since you only need X25519 for Noise, it is OK to defer the work on the P-256 and P-384 variants. In fact, you can just name it X25519StaticKeyPair and avoid all the agreement::Algorithm stuff, for now. Eventually we'll generalize it to work for P-256 and P-384.

briansmith avatar Nov 16 '16 09:11 briansmith

Hi @danburkert, I took a peek at your fork and saw that you started working on this a couple weeks ago. Are you planning to keep working on it? Is there anything I can do to help, beyond the writing of notes in my previous comment above? Thanks!

briansmith avatar Nov 24 '16 01:11 briansmith

Hi @briansmith. Unfortunately I will not have any time soon to wrap it up. The notes you gave are good, and if I get time to revisit in the future I will definitely take them into account, I just can't promise when that would be.

danburkert avatar Nov 29 '16 17:11 danburkert

Hi @briansmith. Unfortunately I will not have any time soon to wrap it up. The notes you gave are good, and if I get time to revisit in the future I will definitely take them into account, I just can't promise when that would be.

Understood. Thanks!

briansmith avatar Dec 13 '16 00:12 briansmith

Is there no way to simply create an ec private key from DER/PEM/etc?

sauyon avatar May 05 '17 05:05 sauyon

It's coming soon. ECDSA code is already written. X25519 and P-256/P-384 ECDH will follow shortly.

briansmith avatar May 05 '17 06:05 briansmith

Depends on #508.

briansmith avatar May 07 '17 20:05 briansmith

Hi, I have a similar problem. I want to be able to perform DH key agreement with static keys, but it seems like ring's agreement::EphemeralPrivateKey interface doesn't allow to import my own private key.

Edit: I added a bounty for this issue.

Bountysource

realcr avatar Nov 18 '17 16:11 realcr

Hi, @briansmith I am trying to implement the X25519StaticKeyPair, what I want to do is the following:

Introduce a struct name X25519StaticPair as you mentioned above,

pub struct X22519StaticKeyPair {
    private_key: ec::PrivateKey,
    public_key: [u8; 32usize],
    alg: &'static Algorithm,
}

then implement it with the following function:

  • pub fn generate(rng: &rand::SecureRandom) -> Result<Self, error::Unspecified> to generate a pair of keys.
  • pub fn from_private_key(private_key: ec::PrivateKey) -> Result<Self, error::Unspecified> to generate a pair of keys according the given PrivateKey
  • pub fn from_bytes(bytes: untrusted::Input) -> Result<Self, error::Unspecified> to generate a pair of keys according the given serialized private key.

and some helper function, like the private_key() -> &ec::PrivateKey and so on...

Finally, the place of the agree() function is confusing me, if place it inside the impl X25519StaticKeyPair block, that will make the API inconsistent(compare with agree_ephemeral), but if I place it outside the impl block, the naming is a problem, maybe x25519_agree() will be a choice? Notice that this function doesn't consume PrivateKey.

Anything I miss?

kamyuentse avatar Nov 28 '17 06:11 kamyuentse

I'm interested in this functionality. It seems like #602 implements this. Do you think this will be merged soon?

jprider63 avatar Mar 06 '18 17:03 jprider63

I'm also interested! Please don't make me use OpenSSL. I don't want to go back into the dark. :(

fmckeogh avatar Oct 29 '18 11:10 fmckeogh

Adding my interest for non ethereal Agreement using X25519. Trying to implement whisper systems double ratcheting algorithm and recommended in their docs https://signal.org/docs/specifications/doubleratchet/#recommended-cryptographic-algorithms

TheBestJohn avatar Nov 19 '18 12:11 TheBestJohn

I'll bump this because I am interested too.

I'm not happy to see the "premier" crypto library for Rust lack this basic feature for half a decade, especially after multiple MRs appear to implement it.

ColonelThirtyTwo avatar Apr 07 '22 20:04 ColonelThirtyTwo

@briansmith Is this still worked on? This issue has been open for 6 years now, and in 2017 you stated the following:

It's coming soon. ECDSA code is already written. X25519 and P-256/P-384 ECDH will follow shortly.

There have been 2 MRs to this point as far as I can tell which both seem to implement this? At this point, are there any plans to support this?

JavaDerg avatar Apr 06 '23 22:04 JavaDerg