2023-07-22 16:22:31 +00:00
# x25519-dalek [](https://crates.io/crates/x25519-dalek) [](https://docs.rs/x25519-dalek) [](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/x25519-dalek.yml)
2017-09-14 00:25:34 +00:00
A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key exchange,
2019-02-17 01:46:11 +00:00
with curve operations provided by
2018-05-15 23:00:06 +00:00
[curve25519-dalek ](https://github.com/dalek-cryptography/curve25519-dalek ).
2017-09-14 00:25:34 +00:00
2019-01-10 18:30:30 +00:00
This crate provides two levels of API: a bare byte-oriented `x25519`
function which matches the function specified in [RFC7748][rfc7748], as
2019-02-16 18:11:27 +00:00
well as a higher-level Rust API for static and ephemeral Diffie-Hellman.
2017-09-14 00:25:34 +00:00
2019-01-10 18:30:30 +00:00
## Examples
2017-09-14 00:25:34 +00:00
2019-01-10 18:30:30 +00:00
< a href = "https://shop.bubblesort.io" >
2019-02-17 01:46:11 +00:00
< img
2019-01-10 18:30:30 +00:00
style="float: right; width: auto; height: 300px;"
src="https://raw.githubusercontent.com/dalek-cryptography/x25519-dalek/master/res/bubblesort-zines-secret-messages-cover.jpeg"/>
< / a >
2017-09-14 00:25:34 +00:00
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!
2023-03-21 05:40:51 +00:00
First, Alice uses `EphemeralSecret::random()` and then
2019-02-16 18:11:27 +00:00
`PublicKey::from()` to produce her secret and public keys:
2017-09-14 00:25:34 +00:00
2023-03-31 17:53:51 +00:00
```ignore
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
use x25519_dalek::{EphemeralSecret, PublicKey};
2019-02-27 20:45:55 +00:00
2023-03-21 05:40:51 +00:00
let alice_secret = EphemeralSecret::random();
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
let alice_public = PublicKey::from(&alice_secret);
2017-09-14 00:25:34 +00:00
```
Bob does the same:
2023-03-31 17:53:51 +00:00
```ignore
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# use x25519_dalek::{EphemeralSecret, PublicKey};
2023-03-21 05:40:51 +00:00
let bob_secret = EphemeralSecret::random();
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
let bob_public = PublicKey::from(&bob_secret);
2017-09-14 00:25:34 +00:00
```
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:
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
```rust
2026-01-25 00:29:05 +00:00
# use getrandom::{SysRng, rand_core::UnwrapErr};
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# use x25519_dalek::{EphemeralSecret, PublicKey};
2026-01-25 00:29:05 +00:00
# let mut rng = UnwrapErr(SysRng);
2025-07-07 19:36:11 +00:00
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# let alice_public = PublicKey::from(&alice_secret);
2025-07-07 19:36:11 +00:00
# let bob_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# let bob_public = PublicKey::from(&bob_secret);
2019-02-16 18:11:27 +00:00
let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
```
Similarly, Bob computes a shared secret by doing:
2017-09-14 00:25:34 +00:00
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
```rust
2026-01-25 00:29:05 +00:00
# use getrandom::{SysRng, rand_core::UnwrapErr};
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# use x25519_dalek::{EphemeralSecret, PublicKey};
2026-01-25 00:29:05 +00:00
# let mut rng = UnwrapErr(SysRng);
2025-07-07 19:36:11 +00:00
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# let alice_public = PublicKey::from(&alice_secret);
2025-07-07 19:36:11 +00:00
# let bob_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# let bob_public = PublicKey::from(&bob_secret);
2019-02-16 18:11:27 +00:00
let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);
2017-09-14 00:25:34 +00:00
```
2019-02-16 18:11:27 +00:00
These secrets are the same:
2017-09-14 00:25:34 +00:00
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
```rust
2026-01-25 00:29:05 +00:00
# use getrandom::{SysRng, rand_core::UnwrapErr};
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# use x25519_dalek::{EphemeralSecret, PublicKey};
2026-01-25 00:29:05 +00:00
# let mut rng = UnwrapErr(SysRng);
2025-07-07 19:36:11 +00:00
# let alice_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# let alice_public = PublicKey::from(&alice_secret);
2025-07-07 19:36:11 +00:00
# let bob_secret = EphemeralSecret::random_from_rng(&mut rng);
Update doc examples to remove deprecated code and restore testing.
Closes #59.
The doc examples have code interspersed with text explaining the API. Because
each doctest executes independently, when these code examples are run as
doctests, they have to include parts of the previous examples with # lines.
These lines are hidden from Rustdoc output and do not appear in the rendered
docs, but they do appear when viewing the README.md on Github.
In order to hide these on Github, the code blocks were made non-executable,
with their content moved to a unit test. However, this meant that the example
API usage was not tested, and so when the unit test was updated to remove the
deprecated `rand_os`, there was no check that the examples stayed in sync with
the test, causing #59. To prevent this from reocurring in the future, go back
to executable tests of the API examples.
2020-08-18 01:47:31 +00:00
# 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);
2019-02-16 18:11:27 +00:00
assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());
2017-09-14 00:25:34 +00:00
```
2021-02-12 09:53:34 +00:00
Voilà! Alice and Bob can now use their shared secret to encrypt their
2017-09-14 00:25:34 +00:00
meows, for example, by using it to generate a key and nonce for an
authenticated-encryption cipher.
2019-02-16 18:11:27 +00:00
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.
2025-12-19 11:33:31 +00:00
# Use
2017-09-14 00:25:34 +00:00
2025-12-19 11:33:31 +00:00
To import `x25519-dalek` , add the following to your project's `Cargo.toml` :
2017-09-14 00:25:34 +00:00
2018-05-15 23:00:27 +00:00
```toml
2020-08-18 02:43:22 +00:00
[dependencies]
2026-06-18 05:42:04 +00:00
x25519-dalek = "3.0.0-rc.1"
2018-05-15 23:00:27 +00:00
```
2017-09-14 00:25:34 +00:00
2025-12-19 11:33:31 +00:00
# Feature Flags
This crate is `#[no_std]` compatible with `default-features = false` .
| Feature | Default? | Description |
| :--- | :--- | :--- |
| `zeroize` | ✓ | Implements `Zeroize` and `ZeroizeOnDrop` for `EphemeralSecret` , `ReusableSecret` , and `StaticSecret` |
| `precomputed-tables` | ✓ | Includes precomputed basepoint multiplication tables. This speeds up `PublicKey::from` by ~3x, at the cost of ~400KB added to the code size. |
| `getrandom` | | Exposes the `random()` constructor for `EphemeralSecret` , `ReusableSecret` , and `StaticSecret` |
| `reusable_secrets` | | Exposes the `ReusableSecret` struct |
| `static_secrets` | | Exposes the `StaticSecret` struct |
| `serde` | | Enables `serde` serialization/deserialization for `PublicKey` and `StaticSecret` |
2021-09-13 22:38:34 +00:00
# MSRV
2025-07-09 01:46:55 +00:00
Current MSRV is 1.85.
2021-09-13 22:38:34 +00:00
2019-01-10 18:30:30 +00:00
# Documentation
2017-09-14 00:25:34 +00:00
2019-01-10 18:30:30 +00:00
Documentation is available [here ](https://docs.rs/x25519-dalek ).
2023-06-24 03:54:38 +00:00
# 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][fiat]).
Further instructions and details regarding backends can be found in the [curve25519-dalek docs ](https://github.com/dalek-cryptography/curve25519-dalek#backends ).
2019-01-10 18:30:30 +00:00
# Note
This code matches the [RFC7748][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 ](https://shop.bubblesort.io/products/secret-messages-zine )
copyright © Amy Wibowo ([@sailorhg](https://twitter.com/sailorhg))
[rfc7748]: https://tools.ietf.org/html/rfc7748
2020-02-25 20:09:40 +00:00
# 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
2023-06-24 03:54:38 +00:00
[fiat]: https://github.com/mit-plv/fiat-crypto
2023-05-08 22:56:43 +00:00
[crypto_box]: https://github.com/RustCrypto/nacl-compat/tree/master/crypto_box