#key-exchange #diffie-hellman #x25519 #curve25519 #secret-key

no-std x25519-dalek

X25519 elliptic curve Diffie-Hellman key exchange in pure-Rust, using curve25519-dalek

20 releases (7 stable)

2.0.1 Feb 7, 2024
2.0.0 Aug 12, 2023
2.0.0-rc.3 Jun 24, 2023
2.0.0-rc.2 Mar 31, 2023
0.1.0 Oct 24, 2017

#90 in Cryptography

Download history 185056/week @ 2024-08-15 189684/week @ 2024-08-22 201442/week @ 2024-08-29 204069/week @ 2024-09-05 195372/week @ 2024-09-12 194215/week @ 2024-09-19 197616/week @ 2024-09-26 215163/week @ 2024-10-03 202294/week @ 2024-10-10 222771/week @ 2024-10-17 216997/week @ 2024-10-24 200361/week @ 2024-10-31 201738/week @ 2024-11-07 202698/week @ 2024-11-14 197139/week @ 2024-11-21 167320/week @ 2024-11-28

808,291 downloads per month
Used in 1,235 crates (211 directly)

BSD-3-Clause

1MB
26K SLoC

x25519-dalek CI

A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key exchange, with curve operations provided by curve25519-dalek.

This crate provides two levels of API: a bare byte-oriented x25519 function which matches the function specified in RFC7748, as well as a higher-level Rust API for static and ephemeral Diffie-Hellman.

Examples

Alice and Bob are two adorable kittens who have lost their mittens, and they wish to be able to send secret messages to each other to coordinate finding them, otherwise—if their caretaker cat finds out—they will surely be called naughty kittens and be given no pie!

But the two kittens are quite clever. Even though their paws are still too big and the rest of them is 90% fuzziness, these clever kittens have been studying up on modern public key cryptography and have learned a nifty trick called elliptic curve Diffie-Hellman key exchange. With the right incantations, the kittens will be able to secretly organise to find their mittens, and then spend the rest of the afternoon nomming some yummy pie!

First, Alice uses EphemeralSecret::random() and then PublicKey::from() to produce her secret and public keys:

use x25519_dalek::{EphemeralSecret, PublicKey};

let alice_secret = EphemeralSecret::random();
let alice_public = PublicKey::from(&alice_secret);

Bob does the same:

# use x25519_dalek::{EphemeralSecret, PublicKey};
let bob_secret = EphemeralSecret::random();
let bob_public = PublicKey::from(&bob_secret);

Alice meows across the room, telling alice_public to Bob, and Bob loudly meows bob_public back to Alice. Alice now computes her shared secret with Bob by doing:

# use rand_core::OsRng;
# use x25519_dalek::{EphemeralSecret, PublicKey};
# let alice_secret = EphemeralSecret::random_from_rng(OsRng);
# let alice_public = PublicKey::from(&alice_secret);
# let bob_secret = EphemeralSecret::random_from_rng(OsRng);
# let bob_public = PublicKey::from(&bob_secret);
let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);

Similarly, Bob computes a shared secret by doing:

# use rand_core::OsRng;
# use x25519_dalek::{EphemeralSecret, PublicKey};
# let alice_secret = EphemeralSecret::random_from_rng(OsRng);
# let alice_public = PublicKey::from(&alice_secret);
# let bob_secret = EphemeralSecret::random_from_rng(OsRng);
# let bob_public = PublicKey::from(&bob_secret);
let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);

These secrets are the same:

# use rand_core::OsRng;
# use x25519_dalek::{EphemeralSecret, PublicKey};
# let alice_secret = EphemeralSecret::random_from_rng(OsRng);
# let alice_public = PublicKey::from(&alice_secret);
# let bob_secret = EphemeralSecret::random_from_rng(OsRng);
# let bob_public = PublicKey::from(&bob_secret);
# let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
# let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);
assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());

Voilà! Alice and Bob can now use their shared secret to encrypt their meows, for example, by using it to generate a key and nonce for an authenticated-encryption cipher.

This example used the ephemeral DH API, which ensures that secret keys cannot be reused; Alice and Bob could instead use the static DH API and load a long-term secret key.

Installation

To install, add the following to your project's Cargo.toml:

[dependencies]
x25519-dalek = "2"

MSRV

Current MSRV is 1.60.

Documentation

Documentation is available here.

Performance and backend selection

Performance is a secondary goal behind correctness, safety, and clarity, but we aim to be competitive with other implementations. To this end, we allow users to choose their backend, i.e., the underlying implementation of elliptic curve and scalar arithmetic. Different backends have different use cases. For example, if you demand formally verified code, you want to use the fiat backend (as it was generated from Fiat Crypto).

Further instructions and details regarding backends can be found in the curve25519-dalek docs.

Note

This code matches the RFC7748 test vectors. The elliptic curve operations are provided by curve25519-dalek, which makes a best-effort attempt to prevent software side-channels.

"Secret Messages" cover image and zine copyright © Amy Wibowo (@sailorhg)

See also

  • crypto_box: pure Rust public-key authenticated encryption compatible with the NaCl family of encryption libraries (libsodium, TweetNaCl) which uses x25519-dalek for key agreement

Dependencies

~0.4–1.6MB
~33K SLoC