Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Henry de Valence 2017-12-04 10:36:52 -08:00
commit 9422804e13
14 changed files with 46 additions and 126 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "curve25519-dalek"
version = "0.13.2"
version = "0.14.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
"Henry de Valence <hdevalence@hdevalence.ca>"]
readme = "README.md"
@ -12,6 +12,7 @@ categories = ["cryptography", "no-std"]
keywords = ["cryptography", "curve25519", "elliptic", "curve", "ECC"]
description = "A low-level cryptographic library for point, group, field, and scalar operations on a curve isomorphic to the twisted Edwards curve defined by -x²+y² = 1 - 121665/121666 x²y² over GF(2²⁵⁵ - 19)."
exclude = [
"**/.gitignore",
".gitignore",
".travis.yml",
]

View file

@ -44,22 +44,34 @@ Extensive documentation is available [here](https://docs.rs/curve25519-dalek).
To install, add the following to the dependencies section of your project's
`Cargo.toml`:
curve25519-dalek = "^0.13"
```toml
curve25519-dalek = "^0.14"
```
Then, in your library or executable source, add:
extern crate curve25519_dalek
extern crate curve25519_dalek;
## Features
On nightly Rust, using the `nightly` feature enables a radix-51 field
arithmetic implementation using `u128`s, which is approximately twice as
fast.
fast. It will also enable additional developer documentation when
compiling via `make doc-internal`.
By default, the benchmarks are not compiled without the `bench`
feature. To run the benchmarks, do:
```sh
cargo bench --features="bench"
```
## TODO
We intend to stabilise the following before curve25519-dalek-1.0.0:
* Implement hashing to a point on the curve (Elligator).
* Finish Ristretto (Decaf for curve25519) implementation.
* Finish Ristretto documentation.
## Contributing

4
fuzz/.gitignore vendored
View file

@ -1,4 +0,0 @@
target
corpus
artifacts

View file

@ -1,32 +0,0 @@
[package]
name = "curve25519-dalek-fuzz"
version = "0.0.1"
authors = ["Automatically generated"]
publish = false
[package.metadata]
cargo-fuzz = true
[dependencies.curve25519-dalek]
path = ".."
[features]
yolocrypto = ["curve25519-dalek/yolocrypto"]
nightly = ["curve25519-dalek/nightly"]
radix_51 = ["curve25519-dalek/radix_51"]
[dependencies.libfuzzer-sys]
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "decaf"
path = "fuzz_targets/decaf.rs"
[[bin]]
name = "scalar_constructor_accepts_256bit_values"
path = "fuzz_targets/scalar_constructor_accepts_256bit_values.rs"

View file

@ -1,21 +0,0 @@
#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate curve25519_dalek;
use curve25519_dalek::curve::ValidityCheck;
use curve25519_dalek::decaf::DecafPoint;
use curve25519_dalek::field::FieldElement;
fuzz_target!(|data: &[u8]| {
if data.len() != 32 {
return;
}
let mut field_bytes = [0u8; 32];
for (by, data) in field_bytes.iter_mut().zip(data.iter()) {
*by = *data;
}
let fe = FieldElement::from_bytes(&field_bytes);
let p = DecafPoint::elligator_decaf_flavour(&fe);
assert!(p.0.is_valid());
p.compress();
});

View file

@ -1,36 +0,0 @@
#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate curve25519_dalek;
use curve25519_dalek::scalar::Scalar;
/// Check that the Scalar constructor accepts 256-bit input values and
/// behaves correctly on them.
///
/// Specifically, we take 256-bit values `a` and `b` from the fuzzer
/// input data and check that `(a mod l) * (b mod l) == (a * b) mod l`.
fuzz_target!(|data: &[u8]| {
if data.len() != 64 {
return;
}
let mut a_bytes = [0u8; 32];
let mut b_bytes = [0u8; 32];
// Set a, b to be random 256-bit integers
a_bytes.copy_from_slice(&data[ 0..32]);
b_bytes.copy_from_slice(&data[32..64]);
// Compute c = a*b (mod l)
let c1 = &Scalar(a_bytes) * &Scalar(b_bytes);
// Compute c = (a mod l) * (b mod l)
let mut tmp = [0u8; 64];
tmp[0..32].copy_from_slice(&a_bytes[..]);
let a_mod_l = Scalar::reduce(&tmp);
tmp[0..32].copy_from_slice(&b_bytes[..]);
let b_mod_l = Scalar::reduce(&tmp);
let c2 = &a_mod_l * &b_mod_l;
assert_eq!(c1, c2);
});

View file

@ -97,7 +97,7 @@ pub const ED25519_BASEPOINT_POINT: ExtendedPoint = ExtendedPoint{
/// array is `i*P`, where `P` is a point of order 8 generating Ɛ[8].
///
/// Thus Ɛ[4] is the points indexed by 0,2,4,6 and Ɛ[2] is the points
/// indexed by 0,4.
/// indexed by 0,4.
pub const EIGHT_TORSION: [ExtendedPoint; 8] = [
ExtendedPoint{
X: FieldElement32([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),

View file

@ -38,11 +38,11 @@ use subtle::ConditionallyAssignable;
/// to \\(2\^{25+b}\\) or \\(2\^{26+b}\\), where \\(b = 1.75\\).
///
/// # Note
///
///
/// The `curve25519_dalek::field` module provides a type alias
/// `curve25519_dalek::field::FieldElement` to either `FieldElement64`
/// or `FieldElement32`.
///
///
/// The backend-specific type `FieldElement32` should not be used
/// outside of the `curve25519_dalek::field` module.
#[derive(Copy, Clone)]
@ -133,7 +133,7 @@ impl<'a, 'b> Mul<&'b FieldElement32> for &'a FieldElement32 {
let y1_19 = 19 * y[1]; // This fits in a u32
let y2_19 = 19 * y[2]; // iff 26 + b + lg(19) < 32
let y3_19 = 19 * y[3]; // if b < 32 - 26 - 4.248 = 1.752
let y4_19 = 19 * y[4];
let y4_19 = 19 * y[4];
let y5_19 = 19 * y[5]; // below, b<2.5: this is a bottleneck,
let y6_19 = 19 * y[6]; // could be avoided by promoting to
let y7_19 = 19 * y[7]; // u64 here instead of in m()
@ -181,7 +181,7 @@ impl<'a, 'b> Mul<&'b FieldElement32> for &'a FieldElement32 {
// How big is the contribution to z[i+j] from x[i], y[j]?
//
// Using the bounds above, we get:
//
//
// i even, j even: x[i]*y[j] < 2^(26+b)*2^(26+b) = 2*2^(51+2*b)
// i odd, j even: x[i]*y[j] < 2^(25+b)*2^(26+b) = 1*2^(51+2*b)
// i even, j odd: x[i]*y[j] < 2^(26+b)*2^(25+b) = 1*2^(51+2*b)
@ -191,7 +191,7 @@ impl<'a, 'b> Mul<&'b FieldElement32> for &'a FieldElement32 {
// (since 2^255 - 19 = 0 mod p). This adds a factor of 19, so
// we get the bounds (z0 is the biggest one, but calculated for
// posterity here in case finer estimation is needed later):
//
//
// z0 < ( 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 249*2^(51 + 2*b)
// z1 < ( 1 + 1 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 + 1*19 )*2^(51 + 2b) = 154*2^(51 + 2*b)
// z2 < ( 2 + 1 + 2 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 + 2*19 + 1*19 )*2^(51 + 2b) = 195*2^(51 + 2*b)
@ -232,15 +232,15 @@ impl FieldElement32 {
pub fn negate(&mut self) {
// Compute -b as ((2^4 * p) - b) to avoid underflow.
let neg = FieldElement32::reduce([
((0x3ffffed << 4) - self.0[0]) as u64,
((0x1ffffff << 4) - self.0[1]) as u64,
((0x3ffffff << 4) - self.0[2]) as u64,
((0x1ffffff << 4) - self.0[3]) as u64,
((0x3ffffff << 4) - self.0[4]) as u64,
((0x1ffffff << 4) - self.0[5]) as u64,
((0x3ffffff << 4) - self.0[6]) as u64,
((0x1ffffff << 4) - self.0[7]) as u64,
((0x3ffffff << 4) - self.0[8]) as u64,
((0x3ffffed << 4) - self.0[0]) as u64,
((0x1ffffff << 4) - self.0[1]) as u64,
((0x3ffffff << 4) - self.0[2]) as u64,
((0x1ffffff << 4) - self.0[3]) as u64,
((0x3ffffff << 4) - self.0[4]) as u64,
((0x1ffffff << 4) - self.0[5]) as u64,
((0x3ffffff << 4) - self.0[6]) as u64,
((0x1ffffff << 4) - self.0[7]) as u64,
((0x3ffffff << 4) - self.0[8]) as u64,
((0x1ffffff << 4) - self.0[9]) as u64,
]);
self.0 = neg.0;
@ -298,7 +298,7 @@ impl FieldElement32 {
// Since z[3] < 2^64, c < 2^(64-25) = 2^39,
// so z[4] < 2^26 + 2^39 < 2^39.0002
carry(&mut z, 4); carry(&mut z, 8);
// Now z[4] < 2^26
// Now z[4] < 2^26
// and z[5] < 2^25 + 2^13.0002 < 2^25.0004 (good enough)
// Last carry has a multiplication by 19:
@ -396,7 +396,7 @@ impl FieldElement32 {
const LOW_26_BITS: u32 = (1 << 26) - 1;
h[0] += 19*q;
// Now carry the result to compute r + 19q...
h[1] += h[0] >> 26;
h[0] = h[0] & LOW_26_BITS;
@ -416,7 +416,7 @@ impl FieldElement32 {
h[7] = h[7] & LOW_25_BITS;
h[9] += h[8] >> 26;
h[8] = h[8] & LOW_26_BITS;
// ... but instead of carrying the value
// (h[9] >> 25) = q*2^255 into another limb,
// discard it, subtracting the value from h.

View file

@ -9,7 +9,7 @@
// - Henry de Valence <hdevalence@hdevalence.ca>
//! The `u32` backend uses `u32`s and a `(u32, u32) -> u64` multiplier.
//!
//!
//! This code is intended to be portable, but it requires that
//! multiplication of two \\(32\\)-bit values to a \\(64\\)-bit result
//! is constant-time on the target platform.

View file

@ -70,7 +70,7 @@ pub const ED25519_BASEPOINT_POINT: ExtendedPoint = ExtendedPoint{
/// array is `i*P`, where `P` is a point of order 8 generating Ɛ[8].
///
/// Thus Ɛ[4] is the points indexed by 0,2,4,6 and Ɛ[2] is the points
/// indexed by 0,4.
/// indexed by 0,4.
pub const EIGHT_TORSION: [ExtendedPoint; 8] = [
ExtendedPoint {
X: FieldElement64([0, 0, 0, 0, 0]),

View file

@ -27,11 +27,11 @@ use subtle::ConditionallyAssignable;
/// grow up to \\(2\^{54}\\) between reductions modulo \\(p\\).
///
/// # Note
///
///
/// The `curve25519_dalek::field` module provides a type alias
/// `curve25519_dalek::field::FieldElement` to either `FieldElement64`
/// or `FieldElement32`.
///
///
/// The backend-specific type `FieldElement64` should not be used
/// outside of the `curve25519_dalek::field` module.
#[derive(Copy, Clone)]

View file

@ -9,11 +9,11 @@
// - Henry de Valence <hdevalence@hdevalence.ca>
//! The `u64` backend uses `u64`s and a `(u64, u64) -> u128` multiplier.
//!
//!
//! On x86_64, the idiom `(x as u128) * (y as u128)` lowers to `MUL`
//! instructions taking 64-bit inputs and producing 128-bit outputs. On
//! other platforms, this implementation is not recommended.
//!
//! other platforms, this implementation is not recommended.
//!
//! On Haswell and newer, the BMI2 extension provides `MULX`, and on
//! Broadwell and newer, the ADX extension provides `ADCX` and `ADOX`
//! (allowing the CPU to compute two carry chains in parallel). These

View file

@ -16,7 +16,7 @@ use core::ops::{Index, IndexMut};
use constants;
/// The `Scalar64` struct represents an element in
/// The `Scalar64` struct represents an element in
/// \\(\mathbb Z / \ell \mathbb Z\\) as 5 \\(52\\)-bit limbs.
#[derive(Copy,Clone)]
pub struct Scalar64(pub [u64; 5]);

View file

@ -10,7 +10,7 @@
//! This module contains internal curve representations which are not part
//! of the public API.
//!
//!
//! # Curve representations
//!
//! Internally, we use several different models for the curve. Here
@ -62,7 +62,7 @@
//! $$
//! \frac {W\_1} {W\_3} = \frac {XT} {ZT} = \frac X Z = x,
//! $$
//! and
//! and
//! $$
//! \frac {W\_2} {W\_3} = \frac {YZ} {ZT} = \frac Y T = y,
//! $$