wrap MontgomeryPoint in EphemeralPublic, impl From; remove byte fns for EphemeralSecret

This commit is contained in:
DebugSteven 2018-12-02 14:23:09 -05:00
parent a599644406
commit 734abac70b
4 changed files with 71 additions and 61 deletions

View file

@ -25,8 +25,8 @@ 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 kittens will be able to secretly organise to find their mittens, and then spend
the rest of the afternoon nomming some yummy pie! the rest of the afternoon nomming some yummy pie!
First, Alice uses `x25519_dalek::Ephemeral::generate_secret()` and then First, Alice uses `x25519_dalek::EphemeralSecret::new()` and then
`x25519_dalek::Ephemeral::generate_public()` to produce her secret and public keys: `x25519_dalek::EphemeralPublic::generate_public()` to produce her secret and public keys:
```rust ```rust
extern crate x25519_dalek; extern crate x25519_dalek;
@ -36,16 +36,16 @@ use x25519_dalek::Ephemeral;
use rand::OsRng; use rand::OsRng;
let mut alice_csprng = OsRng::new().unwrap(); let mut alice_csprng = OsRng::new().unwrap();
let alice_secret = Ephemeral::generate_secret(&mut alice_csprng); let alice_secret = EphemeralSecret::new(&mut alice_csprng);
let alice_public = Ephemeral::generate_public(&alice_secret); let alice_public = EphemeralPublic::generate_public(&alice_secret);
``` ```
Bob does the same: Bob does the same:
```rust ```rust
let mut bob_csprng = OsRng::new().unwrap(); let mut bob_csprng = OsRng::new().unwrap();
let bob_secret = Ephemeral::generate_secret(&mut bob_csprng); let bob_secret = EphemeralSecret::new(&mut bob_csprng);
let bob_public = Ephemeral::generate_public(&bob_secret); let bob_public = EphemeralPublic::generate_public(&bob_secret);
``` ```
Alice meows across the room, telling `alice_public` to Bob, and Bob Alice meows across the room, telling `alice_public` to Bob, and Bob

View file

@ -21,17 +21,18 @@ use curve25519_dalek::montgomery::MontgomeryPoint;
use rand::OsRng; use rand::OsRng;
use x25519_dalek::Ephemeral; use x25519_dalek::EphemeralPublic;
use x25519_dalek::EphemeralSecret;
fn bench_diffie_hellman(c: &mut Criterion) { fn bench_diffie_hellman(c: &mut Criterion) {
let mut csprng: OsRng = OsRng::new().unwrap(); let mut csprng: OsRng = OsRng::new().unwrap();
let alice_secret: Ephemeral = Ephemeral::generate_secret(&mut csprng); let alice_secret: EphemeralSecret = EphemeralSecret::new(&mut csprng);
let bob_secret: Ephemeral = Ephemeral::generate_secret(&mut csprng); let bob_secret: EphemeralSecret = EphemeralSecret::new(&mut csprng);
let bob_public: MontgomeryPoint = Ephemeral::generate_public(&bob_secret); let bob_public: EphemeralPublic = EphemeralPublic::from(&bob_secret);
c.bench_function("diffie_hellman", move |b| { c.bench_function("diffie_hellman", move |b| {
b.iter(|| b.iter(||
Ephemeral::diffie_hellman(&alice_secret, &bob_public) EphemeralSecret::diffie_hellman(&alice_secret, &bob_public)
) )
}); });
} }

View file

@ -32,20 +32,21 @@
//! incantations, the kittens will be able to secretly organise to find their //! 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! //! mittens, and then spend the rest of the afternoon nomming some yummy pie!
//! //!
//! First, Alice uses `x25519_dalek::Ephemeral::generate_secret()` and //! First, Alice uses `x25519_dalek::EphemeralSecret::new()` and
//! `x25519_dalek::Ephemeral::generate_public()` to produce her secret and public keys: //! `x25519_dalek::EphemeralPublic::from()` to produce her secret and public keys:
//! //!
//! ``` //! ```
//! extern crate x25519_dalek; //! extern crate x25519_dalek;
//! extern crate rand; //! extern crate rand;
//! //!
//! # fn main() { //! # fn main() {
//! use x25519_dalek::Ephemeral; //! use x25519_dalek::EphemeralPublic;
//! use x25519_dalek::EphemeralSecret;
//! use rand::thread_rng; //! use rand::thread_rng;
//! //!
//! let mut alice_csprng = thread_rng(); //! let mut alice_csprng = thread_rng();
//! let alice_secret = Ephemeral::generate_secret(&mut alice_csprng); //! let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! let alice_public = Ephemeral::generate_public(&alice_secret); //! let alice_public = EphemeralPublic::from(&alice_secret);
//! # } //! # }
//! ``` //! ```
//! //!
@ -56,12 +57,13 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::Ephemeral; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::EphemeralSecret;
//! # use rand::thread_rng; //! # use rand::thread_rng;
//! # //! #
//! let mut bob_csprng = thread_rng(); //! let mut bob_csprng = thread_rng();
//! let bob_secret = Ephemeral::generate_secret(&mut bob_csprng); //! let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! let bob_public = Ephemeral::generate_public(&bob_secret); //! let bob_public = EphemeralPublic::from(&bob_secret);
//! # } //! # }
//! ``` //! ```
//! //!
@ -74,19 +76,20 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::Ephemeral; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::EphemeralSecret;
//! # use rand::thread_rng; //! # use rand::thread_rng;
//! # //! #
//! # let mut alice_csprng = thread_rng(); //! # let mut alice_csprng = thread_rng();
//! # let alice_secret = Ephemeral::generate_secret(&mut alice_csprng); //! # let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! # let alice_public = Ephemeral::generate_public(&alice_secret); //! # let alice_public = EphemeralPublic::from(&alice_secret);
//! # //! #
//! # let mut bob_csprng = thread_rng(); //! # let mut bob_csprng = thread_rng();
//! # let bob_secret = Ephemeral::generate_secret(&mut bob_csprng); //! # let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! # let bob_public = Ephemeral::generate_public(&bob_secret); //! # let bob_public = EphemeralPublic::from(&bob_secret);
//! # //! #
//! //!
//! let shared_secret = Ephemeral::diffie_hellman(&alice_secret, &bob_public); //! let shared_secret = EphemeralSecret::diffie_hellman(&alice_secret, &bob_public);
//! # } //! # }
//! ``` //! ```
//! //!
@ -97,18 +100,19 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::Ephemeral; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::EphemeralSecret;
//! # use rand::thread_rng; //! # use rand::thread_rng;
//! # //! #
//! # let mut alice_csprng = thread_rng(); //! # let mut alice_csprng = thread_rng();
//! # let alice_secret = Ephemeral::generate_secret(&mut alice_csprng); //! # let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! # let alice_public = Ephemeral::generate_public(&alice_secret); //! # let alice_public = EphemeralPublic::from(&alice_secret);
//! # //! #
//! # let mut bob_csprng = thread_rng(); //! # let mut bob_csprng = thread_rng();
//! # let bob_secret = Ephemeral::generate_secret(&mut bob_csprng); //! # let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! # let bob_public = Ephemeral::generate_public(&bob_secret); //! # let bob_public = EphemeralPublic::from(&bob_secret);
//! # //! #
//! let shared_secret = Ephemeral::diffie_hellman(&bob_secret, &alice_public); //! let shared_secret = EphemeralSecret::diffie_hellman(&bob_secret, &alice_public);
//! # } //! # }
//! ``` //! ```
//! //!

View file

@ -23,61 +23,57 @@ use curve25519_dalek::scalar::Scalar;
use rand_core::RngCore; use rand_core::RngCore;
use rand_core::CryptoRng; use rand_core::CryptoRng;
/// A DH ephemeral key. /// A DH ephemeral public key.
#[repr(C)]
pub struct EphemeralPublic(pub (crate) MontgomeryPoint);
/// A DH ephemeral secret key.
#[repr(C)] #[repr(C)]
#[derive(Default)] // we derive Default in order to use the clear() method in Drop #[derive(Default)] // we derive Default in order to use the clear() method in Drop
pub struct Ephemeral(pub (crate) Scalar); pub struct EphemeralSecret(pub (crate) Scalar);
/// Overwrite ephemeral key material with null bytes when it goes out of scope. /// Overwrite ephemeral secret key material with null bytes when it goes out of scope.
impl Drop for Ephemeral { impl Drop for EphemeralSecret {
fn drop(&mut self) { fn drop(&mut self) {
self.0.clear(); self.0.clear();
} }
} }
/// Multiply this `Ephemeral` key by a `MontgomeryPoint`. /// Multiply this `EphemeralPublic` key by a `EphemeralSecret` key.
impl<'a, 'b> Mul<&'b MontgomeryPoint> for &'a Ephemeral { impl<'a, 'b> Mul<&'b EphemeralSecret> for &'a EphemeralPublic {
type Output = Ephemeral; type Output = EphemeralPublic;
fn mul(self, point: &'b MontgomeryPoint) -> Ephemeral { fn mul(self, secret: &'b EphemeralSecret) -> EphemeralPublic {
Ephemeral(Scalar::from_bits((point * self.to_bytes()).to_bytes())) EphemeralPublic(self.0 * secret.0)
} }
} }
impl Ephemeral { impl EphemeralSecret {
/// Convert this `Ephemeral` key to a `Scalar`.
#[inline]
pub fn to_bytes(&self) -> Scalar {
self.0
}
/// View this `Ephemeral` key as a `Scalar`.
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a Scalar {
&self.0
}
/// Utility function to make it easier to call `x25519()` with /// Utility function to make it easier to call `x25519()` with
/// an ephemeral secret key and montegomery point as input and /// an ephemeral secret key and montegomery point as input and
/// a shared secret as the output. /// a shared secret as the output.
pub fn diffie_hellman(&self, their_public: &MontgomeryPoint) -> SharedSecret { pub fn diffie_hellman(&self, their_public: &EphemeralPublic) -> SharedSecret {
SharedSecret(x25519(self.as_bytes(), &MontgomeryPoint(*their_public.as_bytes()))) SharedSecret(x25519(&self.0, &MontgomeryPoint(*their_public.0.as_bytes())))
} }
/// Generate an x25519 `Ephemeral` secret key. /// Generate an x25519 `EphemeralSecret` key.
pub fn generate_secret<T>(csprng: &mut T) -> Self pub fn new<T>(csprng: &mut T) -> Self
where T: RngCore + CryptoRng where T: RngCore + CryptoRng
{ {
let mut bytes = [0u8; 32]; let mut bytes = [0u8; 32];
csprng.fill_bytes(&mut bytes); csprng.fill_bytes(&mut bytes);
Ephemeral(decode_scalar(&bytes)) EphemeralSecret(decode_scalar(&bytes))
} }
/// Given an x25519 `Ephemeral` secret key, compute its corresponding public key. }
pub fn generate_public(&self) -> MontgomeryPoint {
(self.as_bytes() * &ED25519_BASEPOINT_TABLE).to_montgomery() impl From<&EphemeralSecret> for EphemeralPublic {
/// Given an x25519 `EphemeralSecret` key, compute its corresponding
/// `EphemeralPublic` key.
fn from(secret: &EphemeralSecret) -> EphemeralPublic {
EphemeralPublic((&ED25519_BASEPOINT_TABLE * &secret.0).to_montgomery())
} }
} }
@ -94,6 +90,15 @@ impl Drop for SharedSecret {
} }
} }
impl SharedSecret {
/// View this shared secret key as a byte array.
#[inline]
pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] {
&self.0.as_bytes()
}
}
/// "Decode" a scalar from a 32-byte array. /// "Decode" a scalar from a 32-byte array.
/// ///
/// By "decode" here, what is really meant is applying key clamping by twiddling /// By "decode" here, what is really meant is applying key clamping by twiddling