Merge pull request #15 from DebugSteven/develop

Create new types for keys and clear values on drop
This commit is contained in:
Henry de Valence 2019-01-10 09:58:44 -08:00 committed by GitHub
commit 1dcab60930
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 165 additions and 110 deletions

View file

@ -20,16 +20,19 @@ exclude = [
travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"} travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
[dependencies.curve25519-dalek] [dependencies.curve25519-dalek]
version = "^0.19" version = "1"
default-features = false default-features = false
[dependencies.rand_core] [dependencies.rand_core]
default-features = false default-features = false
version = "0.2" version = "0.2"
[dependencies.clear_on_drop]
version = "0.2"
[dev-dependencies] [dev-dependencies]
criterion = "0.2" criterion = "0.2"
rand = "0.5" rand = "0.6"
[[bench]] [[bench]]
name = "x25519" name = "x25519"
@ -38,6 +41,6 @@ harness = false
[features] [features]
default = ["std", "nightly", "u64_backend"] default = ["std", "nightly", "u64_backend"]
std = ["curve25519-dalek/std"] std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly"] nightly = ["curve25519-dalek/nightly", "clear_on_drop/nightly"]
u64_backend = ["curve25519-dalek/u64_backend"] u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"] u32_backend = ["curve25519-dalek/u32_backend"]

View file

@ -25,28 +25,28 @@ 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::generate_secret()` and then First, Alice uses `x25519_dalek::EphemeralSecret::new()` and then
`x25519_dalek::generate_public()` to produce her secret and public keys: `x25519_dalek::EphemeralPublic::from()` to produce her secret and public keys:
```rust ```rust
extern crate x25519_dalek; extern crate x25519_dalek;
extern crate rand; extern crate rand;
use x25519_dalek::generate_secret; use x25519_dalek::EphemeralPublic;
use x25519_dalek::generate_public; use x25519_dalek::EphemeralSecret;
use rand::OsRng; use rand::OsRng;
let mut alice_csprng = OsRng::new().unwrap(); let mut alice_csprng = OsRng::new().unwrap();
let alice_secret = generate_secret(&mut alice_csprng); let alice_secret = EphemeralSecret::new(&mut alice_csprng);
let alice_public = generate_public(&alice_secret); let alice_public = EphemeralPublic::from(&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 = generate_secret(&mut bob_csprng); let bob_secret = EphemeralSecret::new(&mut bob_csprng);
let bob_public = generate_public(&bob_secret); let bob_public = EphemeralPublic::from(&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
@ -54,15 +54,16 @@ loudly meows `bob_public` back to Alice. Alice now computes her
shared secret with Bob by doing: shared secret with Bob by doing:
```rust ```rust
use x25519_dalek::diffie_hellman; use x25519_dalek::EphemeralPublic;
use x25519_dalek::EphemeralSecret;
let shared_secret = diffie_hellman(&alice_secret, &bob_public.as_bytes()); let shared_secret = EphemeralSecret::diffie_hellman(alice_secret, &bob_public);
``` ```
Similarly, Bob computes the same shared secret by doing: Similarly, Bob computes the same shared secret by doing:
```rust ```rust
let shared_secret = diffie_hellman(&bob_secret, &alice_public.as_bytes()); let shared_secret = EphemeralSecret::diffie_hellman(bob_secret, &alice_public);
``` ```
Voilá! Alice and Bob can now use their shared secret to encrypt their Voilá! Alice and Bob can now use their shared secret to encrypt their

View file

@ -11,26 +11,28 @@
#[macro_use] #[macro_use]
extern crate criterion; extern crate criterion;
extern crate curve25519_dalek;
extern crate rand; extern crate rand;
extern crate x25519_dalek; extern crate x25519_dalek;
use criterion::Criterion; use criterion::Criterion;
use curve25519_dalek::montgomery::MontgomeryPoint;
use rand::OsRng; use rand::OsRng;
use x25519_dalek::generate_public; use x25519_dalek::EphemeralPublic;
use x25519_dalek::generate_secret; use x25519_dalek::EphemeralSecret;
use x25519_dalek::diffie_hellman;
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: [u8; 32] = generate_secret(&mut csprng); let bob_secret: EphemeralSecret = EphemeralSecret::new(&mut csprng);
let bob_secret: [u8; 32] = generate_secret(&mut csprng); let bob_public: EphemeralPublic = EphemeralPublic::from(&bob_secret);
let bob_public: [u8; 32] = generate_public(&bob_secret).to_bytes();
c.bench_function("diffie_hellman", move |b| { c.bench_function("diffie_hellman", move |b| {
b.iter(|| b.iter_with_setup(
diffie_hellman(&alice_secret, &bob_public) || EphemeralSecret::new(&mut csprng),
|alice_secret| alice_secret.diffie_hellman(&bob_public),
) )
}); });
} }

View file

@ -32,21 +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::generate_secret()` and //! First, Alice uses `x25519_dalek::EphemeralSecret::new()` and
//! `x25519_dalek::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::generate_secret; //! use x25519_dalek::EphemeralPublic;
//! use x25519_dalek::generate_public; //! 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 = generate_secret(&mut alice_csprng); //! let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! let alice_public = generate_public(&alice_secret); //! let alice_public = EphemeralPublic::from(&alice_secret);
//! # } //! # }
//! ``` //! ```
//! //!
@ -57,13 +57,13 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::generate_secret; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::generate_public; //! # 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 = generate_secret(&mut bob_csprng); //! let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! let bob_public = generate_public(&bob_secret); //! let bob_public = EphemeralPublic::from(&bob_secret);
//! # } //! # }
//! ``` //! ```
//! //!
@ -76,21 +76,20 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::generate_secret; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::generate_public; //! # 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 = generate_secret(&mut alice_csprng); //! # let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! # let alice_public = 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 = generate_secret(&mut bob_csprng); //! # let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! # let bob_public = generate_public(&bob_secret); //! # let bob_public = EphemeralPublic::from(&bob_secret);
//! # //! #
//! use x25519_dalek::diffie_hellman; //! #
//! //! let shared_secret = EphemeralSecret::diffie_hellman(alice_secret, &bob_public);
//! let shared_secret = diffie_hellman(&alice_secret, &bob_public.as_bytes());
//! # } //! # }
//! ``` //! ```
//! //!
@ -101,20 +100,19 @@
//! # extern crate rand; //! # extern crate rand;
//! # //! #
//! # fn main() { //! # fn main() {
//! # use x25519_dalek::diffie_hellman; //! # use x25519_dalek::EphemeralPublic;
//! # use x25519_dalek::generate_secret; //! # use x25519_dalek::EphemeralSecret;
//! # use x25519_dalek::generate_public;
//! # use rand::thread_rng; //! # use rand::thread_rng;
//! # //! #
//! # let mut alice_csprng = thread_rng(); //! # let mut alice_csprng = thread_rng();
//! # let alice_secret = generate_secret(&mut alice_csprng); //! # let alice_secret = EphemeralSecret::new(&mut alice_csprng);
//! # let alice_public = 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 = generate_secret(&mut bob_csprng); //! # let bob_secret = EphemeralSecret::new(&mut bob_csprng);
//! # let bob_public = generate_public(&bob_secret); //! # let bob_public = EphemeralPublic::from(&bob_secret);
//! # //! #
//! let shared_secret = diffie_hellman(&bob_secret, &alice_public.as_bytes()); //! let shared_secret = EphemeralSecret::diffie_hellman(bob_secret, &alice_public);
//! # } //! # }
//! ``` //! ```
//! //!
@ -126,6 +124,8 @@
#![cfg_attr(feature = "bench", feature(test))] #![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)] #![deny(missing_docs)]
extern crate clear_on_drop;
extern crate curve25519_dalek; extern crate curve25519_dalek;
extern crate rand_core; extern crate rand_core;

View file

@ -12,6 +12,8 @@
//! This implements x25519 key exchange as specified by Mike Hamburg //! This implements x25519 key exchange as specified by Mike Hamburg
//! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748). //! and Adam Langley in [RFC7748](https://tools.ietf.org/html/rfc7748).
use clear_on_drop::clear::Clear;
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
use curve25519_dalek::montgomery::MontgomeryPoint; use curve25519_dalek::montgomery::MontgomeryPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
@ -19,6 +21,76 @@ use curve25519_dalek::scalar::Scalar;
use rand_core::RngCore; use rand_core::RngCore;
use rand_core::CryptoRng; use rand_core::CryptoRng;
/// A DH ephemeral public key.
pub struct EphemeralPublic(pub (crate) MontgomeryPoint);
impl From<[u8; 32]> for EphemeralPublic {
/// Given a byte array, construct an x25519 `EphemeralPublic` key
fn from(bytes: [u8; 32]) -> EphemeralPublic {
EphemeralPublic(MontgomeryPoint(bytes))
}
}
/// A DH ephemeral secret key.
pub struct EphemeralSecret(pub (crate) Scalar);
/// Overwrite ephemeral secret key material with null bytes when it goes out of scope.
impl Drop for EphemeralSecret {
fn drop(&mut self) {
self.0.clear();
}
}
impl EphemeralSecret {
/// Utility function to make it easier to call `x25519()` with
/// an ephemeral secret key and montegomery point as input and
/// a shared secret as the output.
pub fn diffie_hellman(self, their_public: &EphemeralPublic) -> SharedSecret {
SharedSecret(self.0 * their_public.0)
}
/// Generate an x25519 `EphemeralSecret` key.
pub fn new<T>(csprng: &mut T) -> Self
where T: RngCore + CryptoRng
{
let mut bytes = [0u8; 32];
csprng.fill_bytes(&mut bytes);
EphemeralSecret(clamp_scalar(bytes))
}
}
impl<'a> From<&'a EphemeralSecret> for EphemeralPublic {
/// Given an x25519 `EphemeralSecret` key, compute its corresponding
/// `EphemeralPublic` key.
fn from(secret: &'a EphemeralSecret) -> EphemeralPublic {
EphemeralPublic((&ED25519_BASEPOINT_TABLE * &secret.0).to_montgomery())
}
}
/// A DH SharedSecret
pub struct SharedSecret(pub (crate) MontgomeryPoint);
/// Overwrite shared secret material with null bytes when it goes out of scope.
impl Drop for SharedSecret {
fn drop(&mut self) {
self.0.clear();
}
}
impl SharedSecret {
/// View this shared secret key as a byte array.
#[inline]
pub fn as_bytes(&self) -> &[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
@ -27,7 +99,7 @@ use rand_core::CryptoRng;
/// # Returns /// # Returns
/// ///
/// A `Scalar`. /// A `Scalar`.
fn decode_scalar(scalar: &[u8; 32]) -> Scalar { fn clamp_scalar(scalar: [u8; 32]) -> Scalar {
let mut s: [u8; 32] = scalar.clone(); let mut s: [u8; 32] = scalar.clone();
s[0] &= 248; s[0] &= 248;
@ -37,86 +109,63 @@ fn decode_scalar(scalar: &[u8; 32]) -> Scalar {
Scalar::from_bits(s) Scalar::from_bits(s)
} }
/// Generate an x25519 secret key.
pub fn generate_secret<T>(csprng: &mut T) -> [u8; 32]
where T: RngCore + CryptoRng
{
let mut bytes = [0u8; 32];
csprng.fill_bytes(&mut bytes);
bytes
}
/// Given an x25519 secret key, compute its corresponding public key.
pub fn generate_public(secret: &[u8; 32]) -> MontgomeryPoint {
(&decode_scalar(secret) * &ED25519_BASEPOINT_TABLE).to_montgomery()
}
/// The x25519 function, as specified in RFC7748. /// The x25519 function, as specified in RFC7748.
pub fn x25519(scalar: &Scalar, point: &MontgomeryPoint) -> MontgomeryPoint { pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
let k: Scalar = decode_scalar(scalar.as_bytes()); (clamp_scalar(k) * MontgomeryPoint(u)).to_bytes()
(&k * point)
} }
/// Utility function to make it easier to call `x25519()` with byte arrays as
/// inputs and outputs.
pub fn diffie_hellman(my_secret: &[u8; 32], their_public: &[u8; 32]) -> [u8; 32] {
x25519(&Scalar::from_bits(*my_secret), &MontgomeryPoint(*their_public)).to_bytes()
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
fn do_rfc7748_ladder_test1(input_scalar: &Scalar, fn do_rfc7748_ladder_test1(input_scalar: [u8; 32],
input_point: &MontgomeryPoint, input_point: [u8; 32],
expected: &[u8; 32]) { expected: [u8; 32]) {
let result = x25519(&input_scalar, &input_point); let result = x25519(input_scalar, input_point);
assert_eq!(result.0, *expected); assert_eq!(result, expected);
} }
#[test] #[test]
fn rfc7748_ladder_test1_vectorset1() { fn rfc7748_ladder_test1_vectorset1() {
let input_scalar: Scalar = Scalar::from_bits([ let input_scalar: [u8; 32] = [
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d,
0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd,
0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18,
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, ]); 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, ];
let input_point: MontgomeryPoint = MontgomeryPoint([ let input_point: [u8; 32] = [
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b,
0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c, ]); 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c, ];
let expected: [u8; 32] = [ let expected: [u8; 32] = [
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90,
0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f,
0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7,
0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52, ]; 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52, ];
do_rfc7748_ladder_test1(&input_scalar, &input_point, &expected); do_rfc7748_ladder_test1(input_scalar, input_point, expected);
} }
#[test] #[test]
fn rfc7748_ladder_test1_vectorset2() { fn rfc7748_ladder_test1_vectorset2() {
let input_scalar: Scalar = Scalar::from_bits([ let input_scalar: [u8; 32] = [
0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c,
0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5,
0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4,
0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, ]); 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, ];
let input_point: MontgomeryPoint = MontgomeryPoint([ let input_point: [u8; 32] = [
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3,
0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c,
0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e,
0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93, ]); 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93, ];
let expected: [u8; 32] = [ let expected: [u8; 32] = [
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d,
0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8,
0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52,
0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, ]; 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, ];
do_rfc7748_ladder_test1(&input_scalar, &input_point, &expected); do_rfc7748_ladder_test1(input_scalar, input_point, expected);
} }
#[test] #[test]
@ -124,14 +173,14 @@ mod test {
fn rfc7748_ladder_test2() { fn rfc7748_ladder_test2() {
use curve25519_dalek::constants::X25519_BASEPOINT; use curve25519_dalek::constants::X25519_BASEPOINT;
let mut k: Scalar = Scalar::from_bits(X25519_BASEPOINT.0); let mut k: [u8; 32] = X25519_BASEPOINT.0;
let mut u: MontgomeryPoint = X25519_BASEPOINT; let mut u: [u8; 32] = X25519_BASEPOINT.0;
let mut result: MontgomeryPoint; let mut result: [u8; 32];
macro_rules! do_iterations { macro_rules! do_iterations {
($n:expr) => ( ($n:expr) => (
for _ in 0..$n { for _ in 0..$n {
result = x25519(&k, &u); result = x25519(k, u);
// OBVIOUS THING THAT I'M GOING TO NOTE ANYWAY BECAUSE I'VE // OBVIOUS THING THAT I'M GOING TO NOTE ANYWAY BECAUSE I'VE
// SEEN PEOPLE DO THIS WITH GOLANG'S STDLIB AND YOU SURE AS // SEEN PEOPLE DO THIS WITH GOLANG'S STDLIB AND YOU SURE AS
// HELL SHOULDN'T DO HORRIBLY STUPID THINGS LIKE THIS WITH // HELL SHOULDN'T DO HORRIBLY STUPID THINGS LIKE THIS WITH
@ -140,8 +189,8 @@ mod test {
// NEVER EVER TREAT SCALARS AS POINTS AND/OR VICE VERSA. // NEVER EVER TREAT SCALARS AS POINTS AND/OR VICE VERSA.
// //
// ↓↓ DON'T DO THIS ↓↓ // ↓↓ DON'T DO THIS ↓↓
u = MontgomeryPoint(k.as_bytes().clone()); u = k.clone();
k = Scalar::from_bits(result.to_bytes()); k = result;
} }
) )
} }
@ -154,19 +203,19 @@ mod test {
// 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424 // 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424
do_iterations!(1); do_iterations!(1);
assert_eq!(k.as_bytes(), &[ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, assert_eq!(k, [ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f, 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79, ]); 0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79, ]);
do_iterations!(999); do_iterations!(999);
assert_eq!(k.as_bytes(), &[ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, assert_eq!(k, [ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c, 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, ]); 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, ]);
do_iterations!(999_000); do_iterations!(999_000);
assert_eq!(k.as_bytes(), &[ 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, assert_eq!(k, [ 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f, 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf, 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24, ]); 0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24, ]);
} }
} }