Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getrandom #118

Merged
merged 10 commits into from
Mar 21, 2023
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ harness = false

[features]
default = ["alloc", "precomputed-tables", "zeroize"]
getrandom = ["rand_core/getrandom"]
zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"]
serde = ["dep:serde", "curve25519-dalek/serde"]
alloc = ["curve25519-dalek/alloc", "serde?/alloc", "zeroize?/alloc"]
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,21 @@ up on modern public key cryptography and have learned a nifty trick called
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::new()` and then
First, Alice uses `EphemeralSecret::random()` and then
`PublicKey::from()` to produce her secret and public keys:

```rust
use rand_core::OsRng;
use x25519_dalek::{EphemeralSecret, PublicKey};

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

Bob does the same:

```rust
# use rand_core::OsRng;
# use x25519_dalek::{EphemeralSecret, PublicKey};
let bob_secret = EphemeralSecret::new(OsRng);
let bob_secret = EphemeralSecret::random();
let bob_public = PublicKey::from(&bob_secret);
```

Expand Down
4 changes: 2 additions & 2 deletions benches/x25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ use x25519_dalek::EphemeralSecret;
use x25519_dalek::PublicKey;

fn bench_diffie_hellman(c: &mut Criterion) {
let bob_secret = EphemeralSecret::new(OsRng);
let bob_secret = EphemeralSecret::random_from_rng(OsRng);
let bob_public = PublicKey::from(&bob_secret);

c.bench_function("diffie_hellman", move |b| {
b.iter_with_setup(
|| EphemeralSecret::new(OsRng),
|| EphemeralSecret::random_from_rng(OsRng),
|alice_secret| alice_secret.diffie_hellman(&bob_public),
)
});
Expand Down
18 changes: 9 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
//! 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::new()` and then
//! First, Alice uses `EphemeralSecret::random_from_rng` and then
//! `PublicKey::from()` to produce her secret and public keys:
//!
//! ```rust
//! use rand_core::OsRng;
//! use x25519_dalek::{EphemeralSecret, PublicKey};
//!
//! let alice_secret = EphemeralSecret::new(OsRng);
//! let alice_secret = EphemeralSecret::random_from_rng(OsRng);
//! let alice_public = PublicKey::from(&alice_secret);
//! ```
//!
Expand All @@ -66,7 +66,7 @@
//! ```rust
//! # use rand_core::OsRng;
//! # use x25519_dalek::{EphemeralSecret, PublicKey};
//! let bob_secret = EphemeralSecret::new(OsRng);
//! let bob_secret = EphemeralSecret::random_from_rng(OsRng);
//! let bob_public = PublicKey::from(&bob_secret);
//! ```
//!
Expand All @@ -77,9 +77,9 @@
//! ```rust
//! # use rand_core::OsRng;
//! # use x25519_dalek::{EphemeralSecret, PublicKey};
//! # let alice_secret = EphemeralSecret::new(OsRng);
//! # let alice_secret = EphemeralSecret::random_from_rng(OsRng);
//! # let alice_public = PublicKey::from(&alice_secret);
//! # let bob_secret = EphemeralSecret::new(OsRng);
//! # 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);
//! ```
Expand All @@ -89,9 +89,9 @@
//! ```rust
//! # use rand_core::OsRng;
//! # use x25519_dalek::{EphemeralSecret, PublicKey};
//! # let alice_secret = EphemeralSecret::new(OsRng);
//! # let alice_secret = EphemeralSecret::random_from_rng(OsRng);
//! # let alice_public = PublicKey::from(&alice_secret);
//! # let bob_secret = EphemeralSecret::new(OsRng);
//! # 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);
//! ```
Expand All @@ -101,9 +101,9 @@
//! ```rust
//! # use rand_core::OsRng;
//! # use x25519_dalek::{EphemeralSecret, PublicKey};
//! # let alice_secret = EphemeralSecret::new(OsRng);
//! # let alice_secret = EphemeralSecret::random_from_rng(OsRng);
//! # let alice_public = PublicKey::from(&alice_secret);
//! # let bob_secret = EphemeralSecret::new(OsRng);
//! # 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);
Expand Down
59 changes: 52 additions & 7 deletions src/x25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ impl PublicKey {
/// This type is identical to the [`StaticSecret`] type, except that the
/// [`EphemeralSecret::diffie_hellman`] method consumes and then wipes the secret key, and there
/// are no serialization methods defined. This means that [`EphemeralSecret`]s can only be
/// generated from fresh randomness by [`EphemeralSecret::new`] and the compiler statically checks
/// that the resulting secret is used at most once.
/// generated from fresh randomness where the compiler statically checks that the resulting
/// secret is used at most once.
#[cfg_attr(feature = "zeroize", derive(Zeroize))]
#[cfg_attr(feature = "zeroize", zeroize(drop))]
pub struct EphemeralSecret(pub(crate) Scalar);
Expand All @@ -76,14 +76,29 @@ impl EphemeralSecret {
SharedSecret(self.0 * their_public.0)
}

/// Generate an x25519 [`EphemeralSecret`] key.
/// Generate a new [`EphemeralSecret`] with the supplied RNG.
#[deprecated(
since = "2.0.0",
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0"
)]
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
Self::random_from_rng(&mut csprng)
}

/// Generate a new [`EphemeralSecret`] with the supplied RNG.
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
let mut bytes = [0u8; 32];

csprng.fill_bytes(&mut bytes);

EphemeralSecret(Scalar::from_bits_clamped(bytes))
}

/// Generate a new [`EphemeralSecret`].
rozbb marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(feature = "getrandom")]
pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng)
}
}

impl<'a> From<&'a EphemeralSecret> for PublicKey {
Expand Down Expand Up @@ -125,14 +140,29 @@ impl ReusableSecret {
SharedSecret(self.0 * their_public.0)
}

/// Generate a non-serializeable x25519 [`ReusableSecret`] key.
/// Generate a new [`ReusableSecret`] with the supplied RNG.
#[deprecated(
since = "2.0.0",
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0."
)]
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
Self::random_from_rng(&mut csprng)
}

/// Generate a new [`ReusableSecret`] with the supplied RNG.
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
let mut bytes = [0u8; 32];

csprng.fill_bytes(&mut bytes);

ReusableSecret(Scalar::from_bits_clamped(bytes))
}

/// Generate a new [`ReusableSecret`].
rozbb marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(feature = "getrandom")]
pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng)
}
}

#[cfg(feature = "reusable_secrets")]
Expand Down Expand Up @@ -172,15 +202,30 @@ impl StaticSecret {
SharedSecret(self.0 * their_public.0)
}

/// Generate an x25519 key.
/// Generate a new [`StaticSecret`] with the supplied RNG.
#[deprecated(
since = "2.0.0",
note = "Renamed to `random_from_rng`. This will be removed in 2.1.0"
)]
pub fn new<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
Self::random_from_rng(&mut csprng)
}

/// Generate a new [`StaticSecret`] with the supplied RNG.
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
let mut bytes = [0u8; 32];

csprng.fill_bytes(&mut bytes);

StaticSecret(Scalar::from_bits_clamped(bytes))
}

/// Generate a new [`StaticSecret`].
#[cfg(feature = "getrandom")]
pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng)
}

/// Extract this key's bytes for serialization.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
Expand Down Expand Up @@ -276,11 +321,11 @@ impl SharedSecret {
/// use x25519_dalek::PublicKey;
///
/// // Generate Alice's key pair.
/// let alice_secret = StaticSecret::new(&mut OsRng);
/// let alice_secret = StaticSecret::random_from_rng(&mut OsRng);
/// let alice_public = PublicKey::from(&alice_secret);
///
/// // Generate Bob's key pair.
/// let bob_secret = StaticSecret::new(&mut OsRng);
/// let bob_secret = StaticSecret::random_from_rng(&mut OsRng);
/// let bob_public = PublicKey::from(&bob_secret);
///
/// // Alice and Bob should now exchange their public keys.
Expand Down
50 changes: 50 additions & 0 deletions tests/x25519_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,53 @@ fn rfc7748_ladder_test2() {
]
);
}

mod rand_core {

use super::*;
use ::rand_core::OsRng;

#[test]
fn ephemeral_from_rng() {
#[allow(deprecated)]
EphemeralSecret::new(OsRng);
EphemeralSecret::random_from_rng(OsRng);
}

#[test]
#[cfg(feature = "reusable_secrets")]
fn reusable_from_rng() {
#[allow(deprecated)]
ReusableSecret::new(OsRng);
ReusableSecret::random_from_rng(OsRng);
}

#[test]
fn static_from_rng() {
#[allow(deprecated)]
StaticSecret::new(OsRng);
StaticSecret::random_from_rng(OsRng);
}
}

#[cfg(feature = "getrandom")]
mod getrandom {

use super::*;

#[test]
fn ephemeral_random() {
EphemeralSecret::random();
}

#[test]
#[cfg(feature = "reusable_secrets")]
fn reusable_random() {
ReusableSecret::random();
}

#[test]
fn static_random() {
StaticSecret::random();
}
}