Skip to content

Commit

Permalink
Add getrandom (#118)
Browse files Browse the repository at this point in the history
* Add getrandom to bring convenience random init functions

* Fix doc name

* Rename new to random_from_rng

* Deprecate new() in favor of random_from_rng()

* Simplify constructors documentation

Co-authored-by: Ciprian Dorin Craciun <[email protected]>
  • Loading branch information
pinkforest and cipriancraciun authored Mar 21, 2023
1 parent 6aabb9b commit 02a5ce2
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 23 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,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 @@ -71,8 +71,8 @@ impl AsRef<[u8]> for 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 @@ -84,14 +84,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`].
#[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 @@ -133,14 +148,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`].
#[cfg(feature = "getrandom")]
pub fn random() -> Self {
Self::random_from_rng(&mut rand_core::OsRng)
}
}

#[cfg(feature = "reusable_secrets")]
Expand Down Expand Up @@ -180,15 +210,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.
#[inline]
pub fn to_bytes(&self) -> [u8; 32] {
Expand Down Expand Up @@ -307,11 +352,11 @@ impl AsRef<[u8]> for 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();
}
}

0 comments on commit 02a5ce2

Please sign in to comment.