Merge branch 'release/0.4.0'

This commit is contained in:
Isis Lovecruft 2019-01-16 02:07:04 +00:00
commit b71d49e12f
No known key found for this signature in database
GPG key ID: AB41313533E8E812
7 changed files with 201 additions and 250 deletions

View file

@ -4,11 +4,11 @@ If you have questions or comments, please feel free to email the
authors.
For feature requests, suggestions, and bug reports, please open an issue on
[our Github](https://github.com/isislovecruft/x25519-dalek). (Or, send us
[our Github](https://github.com/dalek-cryptography/x25519-dalek). (Or, send us
an email if you're opposed to using Github for whatever reason.)
Patches are welcomed as pull requests on
[our Github](https://github.com/isislovecruft/x25519-dalek), as well as by
[our Github](https://github.com/dalek-cryptography/x25519-dalek), as well as by
email (preferably sent to all of the authors listed in `Cargo.toml`).
All issues on curve25519-dalek are mentored, if you want help with a bug just

View file

@ -1,7 +1,7 @@
[package]
name = "x25519-dalek"
version = "0.3.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>"]
version = "0.4.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>", "DebugSteven <debugsteven@gmail.com>"]
readme = "README.md"
license = "BSD-3-Clause"
repository = "https://github.com/dalek-cryptography/x25519-dalek"
@ -19,17 +19,18 @@ exclude = [
[badges]
travis-ci = { repository = "dalek-cryptography/x25519-dalek", branch = "master"}
[dependencies.curve25519-dalek]
version = "^0.19"
default-features = false
[package.metadata.docs.rs]
rustdoc-args = ["--html-in-header", ".cargo/registry/src/github.com-1ecc6299db9ec823/curve25519-dalek-0.13.2/rustdoc-include-katex-header.html"]
features = ["nightly"]
[dependencies.rand_core]
default-features = false
version = "0.2"
[dependencies]
curve25519-dalek = { version = "1", default-features = false }
rand_core = { version = "0.3", default-features = false }
clear_on_drop = { version = "0.2" }
[dev-dependencies]
criterion = "0.2"
rand = "0.5"
rand_os = "0.1"
[[bench]]
name = "x25519"
@ -38,6 +39,6 @@ harness = false
[features]
default = ["std", "nightly", "u64_backend"]
std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly"]
nightly = ["curve25519-dalek/nightly", "clear_on_drop/nightly"]
u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]

View file

@ -1,4 +1,5 @@
Copyright (c) 2017 Isis Agora Lovecruft. All rights reserved.
Copyright (c) 2017-2019 isis agora lovecruft. All rights reserved.
Copyright (c) 2019 DebugSteven. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View file

@ -1,17 +1,20 @@
# x25519-dalek [![](https://img.shields.io/crates/v/x25519-dalek.svg)](https://crates.io/crates/x25519-dalek) [![](https://docs.rs/x25519-dalek/badge.svg)](https://docs.rs/x25519-dalek) [![](https://travis-ci.org/dalek-cryptography/x25519-dalek.svg?branch=master)](https://travis-ci.org/dalek-cryptography/x25519-dalek)
A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key exchange,
as specified by Mike Hamburg and Adam Langley in
[RFC7748](https://tools.ietf.org/html/rfc7748), using
with curve operations provided by
[curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek).
This crate provides two levels of API: a bare byte-oriented `x25519`
function which matches the function specified in [RFC7748][rfc7748], as
well as a higher-level Rust API for ephemeral Diffie-Hellman.
## Examples
[![](https://raw.githubusercontent.com/dalek-cryptography/x25519-dalek/master/res/bubblesort-zines-secret-messages-cover.jpeg)](https://shop.bubblesort.io)
"Secret Messages" cover image and [zine](https://shop.bubblesort.io/products/secret-messages-zine)
copyright © Amy Wibowo ([@sailorhg](https://twitter.com/sailorhg))
<a href="https://shop.bubblesort.io">
<img
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>
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
@ -25,28 +28,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
the rest of the afternoon nomming some yummy pie!
First, Alice uses `x25519_dalek::generate_secret()` and then
`x25519_dalek::generate_public()` to produce her secret and public keys:
First, Alice uses `EphemeralSecret::new()` and then
`EphemeralPublic::from()` to produce her secret and public keys:
```rust
extern crate x25519_dalek;
extern crate rand;
extern crate rand_os;
use x25519_dalek::generate_secret;
use x25519_dalek::generate_public;
use rand::OsRng;
use x25519_dalek::EphemeralPublic;
use x25519_dalek::EphemeralSecret;
use rand_os::OsRng;
let mut alice_csprng = OsRng::new().unwrap();
let alice_secret = generate_secret(&mut alice_csprng);
let alice_public = generate_public(&alice_secret);
let alice_secret = EphemeralSecret::new(&mut alice_csprng);
let alice_public = EphemeralPublic::from(&alice_secret);
```
Bob does the same:
```rust
let mut bob_csprng = OsRng::new().unwrap();
let bob_secret = generate_secret(&mut bob_csprng);
let bob_public = generate_public(&bob_secret);
let bob_secret = EphemeralSecret::new(&mut bob_csprng);
let bob_public = EphemeralPublic::from(&bob_secret);
```
Alice meows across the room, telling `alice_public` to Bob, and Bob
@ -54,49 +57,43 @@ loudly meows `bob_public` back to Alice. Alice now computes her
shared secret with Bob by doing:
```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:
```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
meows, for example, by using it to generate a key and nonce for an
authenticated-encryption cipher.
# Warnings
[Our elliptic curve library](https://github.com/dalek-cryptography/curve25519-dalek)
(which this code uses) has received *one* formal cryptographic and security
review. It has not yet received what we would consider *sufficient* peer
review by other qualified cryptographers to be considered in any way, shape,
or form, safe.
This code matches the test vectors, as specified in
[RFC7748](https://tools.ietf.org/html/rfc7748), however:
**USE AT YOUR OWN RISK.**
# Documentation
Documentation is available [here](https://docs.rs/x25519-dalek).
# Installation
To install, add the following to your project's `Cargo.toml`:
```toml
[dependencies.x25519-dalek]
version = "^0.3"
version = "^0.4"
```
Then, in your library or executable source, add:
# Documentation
```rust
extern crate x25519_dalek;
```
Documentation is available [here](https://docs.rs/x25519-dalek).
# 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

View file

@ -1,36 +1,40 @@
// -*- mode: rust; -*-
//
// This file is part of x25519-dalek.
// Copyright (c) 2017 Isis Lovecruft
// Copyright (c) 2017-2019 isis agora lovecruft
// Copyright (c) 2019 DebugSteven
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - isis agora lovecruft <isis@patternsinthevoid.net>
// - DebugSteven <debugsteven@gmail.com>
//! Benchmark the Diffie-Hellman operation.
#[macro_use]
extern crate criterion;
extern crate rand;
extern crate curve25519_dalek;
extern crate rand_os;
extern crate x25519_dalek;
use criterion::Criterion;
use rand::OsRng;
use curve25519_dalek::montgomery::MontgomeryPoint;
use x25519_dalek::generate_public;
use x25519_dalek::generate_secret;
use x25519_dalek::diffie_hellman;
use rand_os::OsRng;
use x25519_dalek::EphemeralPublic;
use x25519_dalek::EphemeralSecret;
fn bench_diffie_hellman(c: &mut Criterion) {
let mut csprng: OsRng = OsRng::new().unwrap();
let alice_secret: [u8; 32] = generate_secret(&mut csprng);
let bob_secret: [u8; 32] = generate_secret(&mut csprng);
let bob_public: [u8; 32] = generate_public(&bob_secret).to_bytes();
let bob_secret: EphemeralSecret = EphemeralSecret::new(&mut csprng);
let bob_public: EphemeralPublic = EphemeralPublic::from(&bob_secret);
c.bench_function("diffie_hellman", move |b| {
b.iter(||
diffie_hellman(&alice_secret, &bob_public)
b.iter_with_setup(
|| EphemeralSecret::new(&mut csprng),
|alice_secret| alice_secret.diffie_hellman(&bob_public),
)
});
}

View file

@ -1,138 +1,35 @@
// -*- mode: rust; -*-
//
// This file is part of x25519-dalek.
// Copyright (c) 2017 Isis Lovecruft
// Copyright (c) 2017-2019 isis lovecruft
// Copyright (c) 2019 DebugSteven
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - isis agora lovecruft <isis@patternsinthevoid.net>
// - DebugSteven <debugsteven@gmail.com>
//! x25519 Diffie-Hellman key exchange
//!
//! A pure-Rust implementation of x25519 elliptic curve Diffie-Hellman key
//! exchange as specified by Mike Hamburg and Adam Langley in
//! [RFC7748](https://tools.ietf.org/html/rfc7748).
//!
//! # Examples
//!
//! [![](https://raw.githubusercontent.com/isislovecruft/x25519-dalek/master/res/bubblesort-zines-secret-messages-cover.jpeg)](https://shop.bubblesort.io)
//!
//! "Secret Messages" cover image and [zine](https://shop.bubblesort.io/products/secret-messages-zine)
//! copyright © Amy Wibowo ([@sailorhg](https://twitter.com/sailorhg))
//!
//! 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!
//!
//! First, Alice uses `x25519_dalek::generate_secret()` and
//! `x25519_dalek::generate_public()` to produce her secret and public keys:
//!
//! ```
//! extern crate x25519_dalek;
//! extern crate rand;
//!
//! # fn main() {
//! use x25519_dalek::generate_secret;
//! use x25519_dalek::generate_public;
//! use rand::thread_rng;
//!
//! let mut alice_csprng = thread_rng();
//! let alice_secret = generate_secret(&mut alice_csprng);
//! let alice_public = generate_public(&alice_secret);
//! # }
//! ```
//!
//! Bob does the same:
//!
//! ```
//! # extern crate x25519_dalek;
//! # extern crate rand;
//! #
//! # fn main() {
//! # use x25519_dalek::generate_secret;
//! # use x25519_dalek::generate_public;
//! # use rand::thread_rng;
//! #
//! let mut bob_csprng = thread_rng();
//! let bob_secret = generate_secret(&mut bob_csprng);
//! let bob_public = generate_public(&bob_secret);
//! # }
//! ```
//!
//! 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:
//!
//! ```
//! # extern crate x25519_dalek;
//! # extern crate rand;
//! #
//! # fn main() {
//! # use x25519_dalek::generate_secret;
//! # use x25519_dalek::generate_public;
//! # use rand::thread_rng;
//! #
//! # let mut alice_csprng = thread_rng();
//! # let alice_secret = generate_secret(&mut alice_csprng);
//! # let alice_public = generate_public(&alice_secret);
//! #
//! # let mut bob_csprng = thread_rng();
//! # let bob_secret = generate_secret(&mut bob_csprng);
//! # let bob_public = generate_public(&bob_secret);
//! #
//! use x25519_dalek::diffie_hellman;
//!
//! let shared_secret = diffie_hellman(&alice_secret, &bob_public.as_bytes());
//! # }
//! ```
//!
//! Similarly, Bob computes the same shared secret by doing:
//!
//! ```
//! # extern crate x25519_dalek;
//! # extern crate rand;
//! #
//! # fn main() {
//! # use x25519_dalek::diffie_hellman;
//! # use x25519_dalek::generate_secret;
//! # use x25519_dalek::generate_public;
//! # use rand::thread_rng;
//! #
//! # let mut alice_csprng = thread_rng();
//! # let alice_secret = generate_secret(&mut alice_csprng);
//! # let alice_public = generate_public(&alice_secret);
//! #
//! # let mut bob_csprng = thread_rng();
//! # let bob_secret = generate_secret(&mut bob_csprng);
//! # let bob_public = generate_public(&bob_secret);
//! #
//! let shared_secret = diffie_hellman(&bob_secret, &alice_public.as_bytes());
//! # }
//! ```
//!
//! Voilá! Alice and Bob can now use their shared secret to encrypt their
//! meows, for example, by using it to generate a key and nonce for an
//! authenticated-encryption cipher.
// Refuse to compile if documentation is missing, but only on nightly.
//
// This means that missing docs will still fail CI, but means we can use
// README.md as the crate documentation.
#![no_std]
#![cfg_attr(feature = "bench", feature(test))]
#![deny(missing_docs)]
#![cfg_attr(feature = "nightly", feature(external_doc))]
#![cfg_attr(feature = "nightly", deny(missing_docs))]
#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
#![doc(html_logo_url = "https://doc.dalek.rs/assets/dalek-logo-clear.png")]
//! Note that docs will only build on nightly Rust until
//! `feature(external_doc)` is stabilized.
extern crate clear_on_drop;
extern crate curve25519_dalek;
extern crate rand_core;
#[cfg(test)]
extern crate rand;
mod x25519;
pub use x25519::*;

View file

@ -1,17 +1,21 @@
// -*- mode: rust; -*-
//
// This file is part of x25519-dalek.
// Copyright (c) 2017 Isis Lovecruft
// Copyright (c) 2017-2019 isis lovecruft
// Copyright (c) 2019 DebugSteven
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - isis agora lovecruft <isis@patternsinthevoid.net>
// - DebugSteven <debugsteven@gmail.com>
//! x25519 Diffie-Hellman key exchange
//!
//! This implements x25519 key exchange as specified by Mike Hamburg
//! 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::montgomery::MontgomeryPoint;
use curve25519_dalek::scalar::Scalar;
@ -19,6 +23,76 @@ use curve25519_dalek::scalar::Scalar;
use rand_core::RngCore;
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.
///
/// By "decode" here, what is really meant is applying key clamping by twiddling
@ -27,7 +101,7 @@ use rand_core::CryptoRng;
/// # Returns
///
/// A `Scalar`.
fn decode_scalar(scalar: &[u8; 32]) -> Scalar {
fn clamp_scalar(scalar: [u8; 32]) -> Scalar {
let mut s: [u8; 32] = scalar.clone();
s[0] &= 248;
@ -37,86 +111,63 @@ fn decode_scalar(scalar: &[u8; 32]) -> Scalar {
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.
pub fn x25519(scalar: &Scalar, point: &MontgomeryPoint) -> MontgomeryPoint {
let k: Scalar = decode_scalar(scalar.as_bytes());
(&k * point)
pub fn x25519(k: [u8; 32], u: [u8; 32]) -> [u8; 32] {
(clamp_scalar(k) * MontgomeryPoint(u)).to_bytes()
}
/// 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)]
mod test {
use super::*;
fn do_rfc7748_ladder_test1(input_scalar: &Scalar,
input_point: &MontgomeryPoint,
expected: &[u8; 32]) {
let result = x25519(&input_scalar, &input_point);
assert_eq!(result.0, *expected);
fn do_rfc7748_ladder_test1(input_scalar: [u8; 32],
input_point: [u8; 32],
expected: [u8; 32]) {
let result = x25519(input_scalar, input_point);
assert_eq!(result, expected);
}
#[test]
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,
0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd,
0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18,
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, ]);
let input_point: MontgomeryPoint = MontgomeryPoint([
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, ];
let input_point: [u8; 32] = [
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
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] = [
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90,
0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f,
0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7,
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]
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,
0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5,
0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4,
0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, ]);
let input_point: MontgomeryPoint = MontgomeryPoint([
0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, ];
let input_point: [u8; 32] = [
0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3,
0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c,
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] = [
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d,
0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8,
0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52,
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]
@ -124,14 +175,14 @@ mod test {
fn rfc7748_ladder_test2() {
use curve25519_dalek::constants::X25519_BASEPOINT;
let mut k: Scalar = Scalar::from_bits(X25519_BASEPOINT.0);
let mut u: MontgomeryPoint = X25519_BASEPOINT;
let mut result: MontgomeryPoint;
let mut k: [u8; 32] = X25519_BASEPOINT.0;
let mut u: [u8; 32] = X25519_BASEPOINT.0;
let mut result: [u8; 32];
macro_rules! do_iterations {
($n:expr) => (
for _ in 0..$n {
result = x25519(&k, &u);
result = x25519(k, u);
// OBVIOUS THING THAT I'M GOING TO NOTE ANYWAY BECAUSE I'VE
// SEEN PEOPLE DO THIS WITH GOLANG'S STDLIB AND YOU SURE AS
// HELL SHOULDN'T DO HORRIBLY STUPID THINGS LIKE THIS WITH
@ -140,8 +191,8 @@ mod test {
// NEVER EVER TREAT SCALARS AS POINTS AND/OR VICE VERSA.
//
// ↓↓ DON'T DO THIS ↓↓
u = MontgomeryPoint(k.as_bytes().clone());
k = Scalar::from_bits(result.to_bytes());
u = k.clone();
k = result;
}
)
}
@ -152,21 +203,21 @@ mod test {
// 684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51
// After 1,000,000 iterations:
// 7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424
do_iterations!(1);
assert_eq!(k.as_bytes(), &[ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79, ]);
assert_eq!(k, [ 0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc,
0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f,
0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78,
0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79, ]);
do_iterations!(999);
assert_eq!(k.as_bytes(), &[ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, ]);
assert_eq!(k, [ 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55,
0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c,
0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87,
0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, ]);
do_iterations!(999_000);
assert_eq!(k.as_bytes(), &[ 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24, ]);
assert_eq!(k, [ 0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd,
0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f,
0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf,
0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24, ]);
}
}