mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-04 20:24:10 +00:00
Merge branch 'release/1.0.0-pre.0'
This commit is contained in:
commit
d58b663ea8
16 changed files with 333 additions and 240 deletions
15
Cargo.toml
15
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "curve25519-dalek"
|
||||
version = "0.21.0"
|
||||
version = "1.0.0-pre.0"
|
||||
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"Henry de Valence <hdevalence@hdevalence.ca>"]
|
||||
readme = "README.md"
|
||||
|
|
@ -26,7 +26,7 @@ features = ["nightly"]
|
|||
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
|
||||
|
||||
[dev-dependencies]
|
||||
sha2 = "0.7"
|
||||
sha2 = { version = "0.8", default-features = false }
|
||||
bincode = "1"
|
||||
criterion = "0.2"
|
||||
|
||||
|
|
@ -43,20 +43,18 @@ harness = false
|
|||
[dependencies]
|
||||
rand = { version = "0.5", default-features = false }
|
||||
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
|
||||
digest = "0.7"
|
||||
generic-array = "0.9"
|
||||
digest = { version = "0.8", default-features = false }
|
||||
clear_on_drop = "=0.2.3"
|
||||
subtle = { version = "1", default-features = false }
|
||||
subtle = { version = "2.0.0-pre.0", default-features = false }
|
||||
serde = { version = "1.0", optional = true }
|
||||
packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
rand = { version = "0.5", default-features = false }
|
||||
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
|
||||
digest = "0.7"
|
||||
generic-array = "0.9"
|
||||
digest = { version = "0.8", default-features = false }
|
||||
clear_on_drop = "=0.2.3"
|
||||
subtle = { version = "1", default-features = false }
|
||||
subtle = { version = "2.0.0-pre.0", default-features = false }
|
||||
serde = { version = "1.0", optional = true }
|
||||
packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true }
|
||||
|
||||
|
|
@ -80,3 +78,4 @@ avx2_backend = ["nightly", "u64_backend", "packed_simd"]
|
|||
# into the build script. Then, the build.rs emits the stage2_build
|
||||
# feature before the main-stage compilation.
|
||||
stage2_build = []
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ make doc-internal
|
|||
To import `curve25519-dalek`, add the following to the dependencies section of
|
||||
your project's `Cargo.toml`:
|
||||
```toml
|
||||
curve25519-dalek = "0.21"
|
||||
curve25519-dalek = "1.0.0-pre.0"
|
||||
```
|
||||
Then import the crate as:
|
||||
```rust,no_run
|
||||
|
|
|
|||
1
build.rs
1
build.rs
|
|
@ -10,7 +10,6 @@ extern crate byteorder;
|
|||
extern crate clear_on_drop;
|
||||
extern crate core;
|
||||
extern crate digest;
|
||||
extern crate generic_array;
|
||||
extern crate rand;
|
||||
extern crate subtle;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use core::convert::From;
|
|||
use core::ops::{Add, Neg, Sub};
|
||||
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
use edwards;
|
||||
use scalar_mul::window::{LookupTable, NafLookupTable5, NafLookupTable8};
|
||||
|
|
@ -76,8 +76,12 @@ impl From<ExtendedPoint> for edwards::EdwardsPoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for ExtendedPoint {
|
||||
fn conditional_assign(&mut self, other: &ExtendedPoint, choice: Choice) {
|
||||
impl ConditionallySelectable for ExtendedPoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
ExtendedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice))
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
|
||||
self.0.conditional_assign(&other.0, choice);
|
||||
}
|
||||
}
|
||||
|
|
@ -209,8 +213,12 @@ impl Identity for CachedPoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for CachedPoint {
|
||||
fn conditional_assign(&mut self, other: &CachedPoint, choice: Choice) {
|
||||
impl ConditionallySelectable for CachedPoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
CachedPoint(FieldElement32x4::conditional_select(&a.0, &b.0, choice))
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
|
||||
self.0.conditional_assign(&other.0, choice);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,15 +144,37 @@ pub enum Shuffle {
|
|||
pub struct FieldElement32x4(pub(crate) [u32x8; 5]);
|
||||
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
impl ConditionallyAssignable for FieldElement32x4 {
|
||||
fn conditional_assign(&mut self, other: &FieldElement32x4, choice: Choice) {
|
||||
impl ConditionallySelectable for FieldElement32x4 {
|
||||
fn conditional_select(
|
||||
a: &FieldElement32x4,
|
||||
b: &FieldElement32x4,
|
||||
choice: Choice,
|
||||
) -> FieldElement32x4 {
|
||||
let mask = (-(choice.unwrap_u8() as i32)) as u32;
|
||||
let mask_vec = u32x8::splat(mask);
|
||||
for i in 0..5 {
|
||||
self.0[i] = self.0[i] ^ (mask_vec & (self.0[i] ^ other.0[i]));
|
||||
}
|
||||
FieldElement32x4([
|
||||
a.0[0] ^ (mask_vec & (a.0[0] ^ b.0[0])),
|
||||
a.0[1] ^ (mask_vec & (a.0[1] ^ b.0[1])),
|
||||
a.0[2] ^ (mask_vec & (a.0[2] ^ b.0[2])),
|
||||
a.0[3] ^ (mask_vec & (a.0[3] ^ b.0[3])),
|
||||
a.0[4] ^ (mask_vec & (a.0[4] ^ b.0[4])),
|
||||
])
|
||||
}
|
||||
|
||||
fn conditional_assign(
|
||||
&mut self,
|
||||
other: &FieldElement32x4,
|
||||
choice: Choice,
|
||||
) {
|
||||
let mask = (-(choice.unwrap_u8() as i32)) as u32;
|
||||
let mask_vec = u32x8::splat(mask);
|
||||
self.0[0] ^= mask_vec & (self.0[0] ^ other.0[0]);
|
||||
self.0[1] ^= mask_vec & (self.0[1] ^ other.0[1]);
|
||||
self.0[2] ^= mask_vec & (self.0[2] ^ other.0[2]);
|
||||
self.0[3] ^= mask_vec & (self.0[3] ^ other.0[3]);
|
||||
self.0[4] ^= mask_vec & (self.0[4] ^ other.0[4]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
//! of signed limbs.
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::ops::{Add, AddAssign};
|
||||
use core::ops::{Sub, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::Neg;
|
||||
use core::ops::{Add, AddAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::{Sub, SubAssign};
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
/// A `FieldElement32` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
|
|
@ -219,11 +219,50 @@ impl<'a> Neg for &'a FieldElement32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for FieldElement32 {
|
||||
impl ConditionallySelectable for FieldElement32 {
|
||||
fn conditional_select(
|
||||
a: &FieldElement32,
|
||||
b: &FieldElement32,
|
||||
choice: Choice,
|
||||
) -> FieldElement32 {
|
||||
FieldElement32([
|
||||
u32::conditional_select(&a.0[0], &b.0[0], choice),
|
||||
u32::conditional_select(&a.0[1], &b.0[1], choice),
|
||||
u32::conditional_select(&a.0[2], &b.0[2], choice),
|
||||
u32::conditional_select(&a.0[3], &b.0[3], choice),
|
||||
u32::conditional_select(&a.0[4], &b.0[4], choice),
|
||||
u32::conditional_select(&a.0[5], &b.0[5], choice),
|
||||
u32::conditional_select(&a.0[6], &b.0[6], choice),
|
||||
u32::conditional_select(&a.0[7], &b.0[7], choice),
|
||||
u32::conditional_select(&a.0[8], &b.0[8], choice),
|
||||
u32::conditional_select(&a.0[9], &b.0[9], choice),
|
||||
])
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &FieldElement32, choice: Choice) {
|
||||
for i in 0..10 {
|
||||
self.0[i].conditional_assign(&other.0[i], choice);
|
||||
}
|
||||
self.0[0].conditional_assign(&other.0[0], choice);
|
||||
self.0[1].conditional_assign(&other.0[1], choice);
|
||||
self.0[2].conditional_assign(&other.0[2], choice);
|
||||
self.0[3].conditional_assign(&other.0[3], choice);
|
||||
self.0[4].conditional_assign(&other.0[4], choice);
|
||||
self.0[5].conditional_assign(&other.0[5], choice);
|
||||
self.0[6].conditional_assign(&other.0[6], choice);
|
||||
self.0[7].conditional_assign(&other.0[7], choice);
|
||||
self.0[8].conditional_assign(&other.0[8], choice);
|
||||
self.0[9].conditional_assign(&other.0[9], choice);
|
||||
}
|
||||
|
||||
fn conditional_swap(a: &mut FieldElement32, b: &mut FieldElement32, choice: Choice) {
|
||||
u32::conditional_swap(&mut a.0[0], &mut b.0[0], choice);
|
||||
u32::conditional_swap(&mut a.0[1], &mut b.0[1], choice);
|
||||
u32::conditional_swap(&mut a.0[2], &mut b.0[2], choice);
|
||||
u32::conditional_swap(&mut a.0[3], &mut b.0[3], choice);
|
||||
u32::conditional_swap(&mut a.0[4], &mut b.0[4], choice);
|
||||
u32::conditional_swap(&mut a.0[5], &mut b.0[5], choice);
|
||||
u32::conditional_swap(&mut a.0[6], &mut b.0[6], choice);
|
||||
u32::conditional_swap(&mut a.0[7], &mut b.0[7], choice);
|
||||
u32::conditional_swap(&mut a.0[8], &mut b.0[8], choice);
|
||||
u32::conditional_swap(&mut a.0[9], &mut b.0[9], choice);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@
|
|||
//! limbs with \\(128\\)-bit products.
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::ops::{Add, AddAssign};
|
||||
use core::ops::{Sub, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::Neg;
|
||||
use core::ops::{Add, AddAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::{Sub, SubAssign};
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
/// A `FieldElement64` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
|
|
@ -209,11 +209,35 @@ impl<'a> Neg for &'a FieldElement64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for FieldElement64 {
|
||||
impl ConditionallySelectable for FieldElement64 {
|
||||
fn conditional_select(
|
||||
a: &FieldElement64,
|
||||
b: &FieldElement64,
|
||||
choice: Choice,
|
||||
) -> FieldElement64 {
|
||||
FieldElement64([
|
||||
u64::conditional_select(&a.0[0], &b.0[0], choice),
|
||||
u64::conditional_select(&a.0[1], &b.0[1], choice),
|
||||
u64::conditional_select(&a.0[2], &b.0[2], choice),
|
||||
u64::conditional_select(&a.0[3], &b.0[3], choice),
|
||||
u64::conditional_select(&a.0[4], &b.0[4], choice),
|
||||
])
|
||||
}
|
||||
|
||||
fn conditional_swap(a: &mut FieldElement64, b: &mut FieldElement64, choice: Choice) {
|
||||
u64::conditional_swap(&mut a.0[0], &mut b.0[0], choice);
|
||||
u64::conditional_swap(&mut a.0[1], &mut b.0[1], choice);
|
||||
u64::conditional_swap(&mut a.0[2], &mut b.0[2], choice);
|
||||
u64::conditional_swap(&mut a.0[3], &mut b.0[3], choice);
|
||||
u64::conditional_swap(&mut a.0[4], &mut b.0[4], choice);
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &FieldElement64, choice: Choice) {
|
||||
for i in 0..5 {
|
||||
self.0[i].conditional_assign(&other.0[i], choice);
|
||||
}
|
||||
self.0[0].conditional_assign(&other.0[0], choice);
|
||||
self.0[1].conditional_assign(&other.0[1], choice);
|
||||
self.0[2].conditional_assign(&other.0[2], choice);
|
||||
self.0[3].conditional_assign(&other.0[3], choice);
|
||||
self.0[4].conditional_assign(&other.0[4], choice);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,12 +129,13 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
/// Test that SQRT_M1 is the positive square root of -1
|
||||
#[test]
|
||||
/// Test that SQRT_M1 is a square root of -1
|
||||
fn test_sqrt_minus_one() {
|
||||
let minus_one = FieldElement::minus_one();
|
||||
let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1;
|
||||
assert_eq!(minus_one, sqrt_m1_sq);
|
||||
assert_eq!(constants::SQRT_M1.is_negative().unwrap_u8(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -143,8 +144,6 @@ mod test {
|
|||
let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt();
|
||||
assert_eq!(was_nonzero_square.unwrap_u8(), 1u8);
|
||||
let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1;
|
||||
// XXX it seems we have flipped the sign relative to
|
||||
// the invsqrt function?
|
||||
assert_eq!(sign_test_sqrt, minus_one);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,15 +124,15 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::ops::{Add, Sub, Neg};
|
||||
use core::ops::{Add, Neg, Sub};
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
use constants;
|
||||
|
||||
use field::FieldElement;
|
||||
use edwards::EdwardsPoint;
|
||||
use field::FieldElement;
|
||||
use traits::ValidityCheck;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
@ -204,7 +204,7 @@ use traits::Identity;
|
|||
|
||||
impl Identity for ProjectivePoint {
|
||||
fn identity() -> ProjectivePoint {
|
||||
ProjectivePoint{
|
||||
ProjectivePoint {
|
||||
X: FieldElement::zero(),
|
||||
Y: FieldElement::one(),
|
||||
Z: FieldElement::one(),
|
||||
|
|
@ -268,8 +268,17 @@ impl ValidityCheck for ProjectivePoint {
|
|||
// Constant-time assignment
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl ConditionallyAssignable for ProjectiveNielsPoint {
|
||||
fn conditional_assign(&mut self, other: &ProjectiveNielsPoint, choice: Choice) {
|
||||
impl ConditionallySelectable for ProjectiveNielsPoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
ProjectiveNielsPoint {
|
||||
Y_plus_X: FieldElement::conditional_select(&a.Y_plus_X, &b.Y_plus_X, choice),
|
||||
Y_minus_X: FieldElement::conditional_select(&a.Y_minus_X, &b.Y_minus_X, choice),
|
||||
Z: FieldElement::conditional_select(&a.Z, &b.Z, choice),
|
||||
T2d: FieldElement::conditional_select(&a.T2d, &b.T2d, choice),
|
||||
}
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
|
||||
self.Y_plus_X.conditional_assign(&other.Y_plus_X, choice);
|
||||
self.Y_minus_X.conditional_assign(&other.Y_minus_X, choice);
|
||||
self.Z.conditional_assign(&other.Z, choice);
|
||||
|
|
@ -277,9 +286,16 @@ impl ConditionallyAssignable for ProjectiveNielsPoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for AffineNielsPoint {
|
||||
fn conditional_assign(&mut self, other: &AffineNielsPoint, choice: Choice) {
|
||||
// PreComputedGroupElementCMove()
|
||||
impl ConditionallySelectable for AffineNielsPoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
AffineNielsPoint {
|
||||
y_plus_x: FieldElement::conditional_select(&a.y_plus_x, &b.y_plus_x, choice),
|
||||
y_minus_x: FieldElement::conditional_select(&a.y_minus_x, &b.y_minus_x, choice),
|
||||
xy2d: FieldElement::conditional_select(&a.xy2d, &b.xy2d, choice),
|
||||
}
|
||||
}
|
||||
|
||||
fn conditional_assign(&mut self, other: &Self, choice: Choice) {
|
||||
self.y_plus_x.conditional_assign(&other.y_plus_x, choice);
|
||||
self.y_minus_x.conditional_assign(&other.y_minus_x, choice);
|
||||
self.xy2d.conditional_assign(&other.xy2d, choice);
|
||||
|
|
@ -296,7 +312,7 @@ impl ProjectivePoint {
|
|||
///
|
||||
/// This costs \\(3 \mathrm M + 1 \mathrm S\\).
|
||||
pub fn to_extended(&self) -> EdwardsPoint {
|
||||
EdwardsPoint{
|
||||
EdwardsPoint {
|
||||
X: &self.X * &self.Z,
|
||||
Y: &self.Y * &self.Z,
|
||||
Z: self.Z.square(),
|
||||
|
|
@ -311,7 +327,7 @@ impl CompletedPoint {
|
|||
///
|
||||
/// This costs \\(3 \mathrm M \\).
|
||||
pub fn to_projective(&self) -> ProjectivePoint {
|
||||
ProjectivePoint{
|
||||
ProjectivePoint {
|
||||
X: &self.X * &self.T,
|
||||
Y: &self.Y * &self.Z,
|
||||
Z: &self.Z * &self.T,
|
||||
|
|
@ -323,7 +339,7 @@ impl CompletedPoint {
|
|||
///
|
||||
/// This costs \\(4 \mathrm M \\).
|
||||
pub fn to_extended(&self) -> EdwardsPoint {
|
||||
EdwardsPoint{
|
||||
EdwardsPoint {
|
||||
X: &self.X * &self.T,
|
||||
Y: &self.Y * &self.Z,
|
||||
Z: &self.Z * &self.T,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
//! The Edwards arithmetic is implemented using the “extended twisted
|
||||
//! coordinates” of Hisil, Wong, Carter, and Dawson, and the
|
||||
//! corresponding complete formulas. For more details,
|
||||
//! see the [`curve_models` submodule][curve_models]
|
||||
//! see the [`curve_models` submodule][curve_models]
|
||||
//! of the internal documentation.
|
||||
//!
|
||||
//! ## Validity Checking
|
||||
|
|
@ -92,17 +92,17 @@
|
|||
// affine and projective cakes and eat both of them too.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::fmt::Debug;
|
||||
use core::iter::Iterator;
|
||||
use core::ops::{Add, Sub, Neg};
|
||||
use core::iter::Sum;
|
||||
use core::ops::{Add, Neg, Sub};
|
||||
use core::ops::{AddAssign, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::iter::Sum;
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use constants;
|
||||
|
|
@ -169,9 +169,9 @@ impl CompressedEdwardsY {
|
|||
let YY = Y.square();
|
||||
let u = &YY - &Z; // u = y²-1
|
||||
let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1
|
||||
let (is_nonzero_square, mut X) = FieldElement::sqrt_ratio(&u, &v);
|
||||
let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v);
|
||||
|
||||
if is_nonzero_square.unwrap_u8() != 1u8 { return None; }
|
||||
if is_valid_y_coord.unwrap_u8() != 1u8 { return None; }
|
||||
|
||||
// Flip the sign of X if it's not correct
|
||||
let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7);
|
||||
|
|
@ -328,10 +328,12 @@ impl CompressedEdwardsY {
|
|||
|
||||
impl Identity for EdwardsPoint {
|
||||
fn identity() -> EdwardsPoint {
|
||||
EdwardsPoint{ X: FieldElement::zero(),
|
||||
Y: FieldElement::one(),
|
||||
Z: FieldElement::one(),
|
||||
T: FieldElement::zero() }
|
||||
EdwardsPoint {
|
||||
X: FieldElement::zero(),
|
||||
Y: FieldElement::one(),
|
||||
Z: FieldElement::one(),
|
||||
T: FieldElement::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,12 +360,14 @@ impl ValidityCheck for EdwardsPoint {
|
|||
// Constant-time assignment
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl ConditionallyAssignable for EdwardsPoint {
|
||||
fn conditional_assign(&mut self, other: &EdwardsPoint, choice: Choice) {
|
||||
self.X.conditional_assign(&other.X, choice);
|
||||
self.Y.conditional_assign(&other.Y, choice);
|
||||
self.Z.conditional_assign(&other.Z, choice);
|
||||
self.T.conditional_assign(&other.T, choice);
|
||||
impl ConditionallySelectable for EdwardsPoint {
|
||||
fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint {
|
||||
EdwardsPoint {
|
||||
X: FieldElement::conditional_select(&a.X, &b.X, choice),
|
||||
Y: FieldElement::conditional_select(&a.Y, &b.Y, choice),
|
||||
Z: FieldElement::conditional_select(&a.Z, &b.Z, choice),
|
||||
T: FieldElement::conditional_select(&a.T, &b.T, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -373,7 +377,9 @@ impl ConditionallyAssignable for EdwardsPoint {
|
|||
|
||||
impl ConstantTimeEq for EdwardsPoint {
|
||||
fn ct_eq(&self, other: &EdwardsPoint) -> Choice {
|
||||
self.compress().as_bytes().ct_eq(other.compress().as_bytes())
|
||||
self.compress()
|
||||
.as_bytes()
|
||||
.ct_eq(other.compress().as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -897,7 +903,7 @@ impl Debug for EdwardsBasepointTable {
|
|||
mod test {
|
||||
use field::FieldElement;
|
||||
use scalar::Scalar;
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
use constants;
|
||||
use super::*;
|
||||
|
||||
|
|
|
|||
136
src/field.rs
136
src/field.rs
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
|
@ -195,40 +195,19 @@ impl FieldElement {
|
|||
t21
|
||||
}
|
||||
|
||||
/// Given `FieldElements` `u` and `v`, attempt to compute
|
||||
/// `sqrt(u/v)` in constant time.
|
||||
/// Given `FieldElements` `u` and `v`, compute either `sqrt(u/v)`
|
||||
/// or `sqrt(i*u/v)` in constant time.
|
||||
///
|
||||
/// This function always returns the nonnegative square root, if it exists.
|
||||
///
|
||||
/// It would be much better to use an `Option` type here, but
|
||||
/// doing so forces the caller to branch, which we don't want to
|
||||
/// do. This seems like the least bad solution.
|
||||
/// This function always returns the nonnegative square root.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// - `(1u8, sqrt(u/v))` if `v` is nonzero and `u/v` is square;
|
||||
/// - `(0u8, zero)` if `v` is zero;
|
||||
/// - `(0u8, garbage)` if `u/v` is nonsquare.
|
||||
/// - `(Choice(1), +sqrt(u/v)) ` if `v` is nonzero and `u/v` is square;
|
||||
/// - `(Choice(1), zero) ` if `u` is zero;
|
||||
/// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero;
|
||||
/// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square).
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// let one = FieldElement::one();
|
||||
/// let two = &one + &one;
|
||||
/// let four = &two * &two;
|
||||
///
|
||||
/// // two is nonsquare mod p
|
||||
/// let (two_is_square, two_sqrt) = FieldElement::sqrt_ratio(&two, &one);
|
||||
/// assert_eq!(two_is_square.unwrap_u8(), 0u8);
|
||||
///
|
||||
/// // four is square mod p
|
||||
/// let (four_is_square, four_sqrt) = FieldElement::sqrt_ratio(&four, &one);
|
||||
///
|
||||
/// assert_eq!(four_is_square.unwrap_u8(), 1u8);
|
||||
/// assert_eq!(four_sqrt.is_negative().unwrap_u8
|
||||
/// ```
|
||||
///
|
||||
pub fn sqrt_ratio(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) {
|
||||
pub fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) {
|
||||
// Using the same trick as in ed25519 decoding, we merge the
|
||||
// inversion, the square root, and the square test as follows.
|
||||
//
|
||||
|
|
@ -258,11 +237,14 @@ impl FieldElement {
|
|||
let mut r = &(u * &v3) * &(u * &v7).pow_p58();
|
||||
let check = v * &r.square();
|
||||
|
||||
let correct_sign_sqrt = check.ct_eq( u);
|
||||
let flipped_sign_sqrt = check.ct_eq(&(-u));
|
||||
let i = &constants::SQRT_M1;
|
||||
|
||||
let correct_sign_sqrt = check.ct_eq( u);
|
||||
let flipped_sign_sqrt = check.ct_eq( &(-u));
|
||||
let flipped_sign_sqrt_i = check.ct_eq(&(&(-u)*i));
|
||||
|
||||
let r_prime = &constants::SQRT_M1 * &r;
|
||||
r.conditional_assign(&r_prime, flipped_sign_sqrt);
|
||||
r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i);
|
||||
|
||||
// Choose the nonnegative square root.
|
||||
let r_is_negative = r.is_negative();
|
||||
|
|
@ -273,42 +255,20 @@ impl FieldElement {
|
|||
(was_nonzero_square, r)
|
||||
}
|
||||
|
||||
/// For `self` a nonzero square, compute 1/sqrt(self) in
|
||||
/// constant time.
|
||||
/// Attempt to compute `1/sqrt(self)` in constant time.
|
||||
///
|
||||
/// It would be much better to use an `Option` type here, but
|
||||
/// doing so forces the caller to branch, which we don't want to
|
||||
/// do. This seems like the least bad solution.
|
||||
/// Convenience wrapper around `sqrt_ratio_i`.
|
||||
///
|
||||
/// This function always returns the nonnegative square root.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// - `(1u8, 1/sqrt(self))` if `self` is a nonzero square;
|
||||
/// - `(0u8, zero)` if `self` is zero;
|
||||
/// - `(0u8, garbage)` if `self` is nonsquare.
|
||||
/// - `(Choice(1), +sqrt(1/self)) ` if `self` is a nonzero square;
|
||||
/// - `(Choice(0), zero) ` if `self` is zero;
|
||||
/// - `(Choice(0), +sqrt(i*u/v)) ` if `self` is a nonzero nonsquare;
|
||||
///
|
||||
pub fn invsqrt(&self) -> (Choice, FieldElement) {
|
||||
FieldElement::sqrt_ratio(&FieldElement::one(), self)
|
||||
}
|
||||
|
||||
/// chi calculates `self^((p-1)/2)`.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// * If this element is a non-zero square, returns `1`.
|
||||
/// * If it is zero, returns `0`.
|
||||
/// * If it is non-square, returns `-1`.
|
||||
pub fn chi(&self) -> FieldElement { // extra25519.chi
|
||||
// The bits of (p-1)/2 = 2^254 -10 are 0110111111...11.
|
||||
//
|
||||
// nonzero bits of exponent
|
||||
let (t19, _) = self.pow22501(); // 249..0
|
||||
let t20 = t19.pow2k(4); // 253..4
|
||||
let t21 = self.square(); // 1
|
||||
let t22 = t21.square(); // 2
|
||||
let t23 = &t22 * &t21; // 2,1
|
||||
let t24 = &t20 * &t23; // 253..4,2,1
|
||||
|
||||
t24
|
||||
FieldElement::sqrt_ratio_i(&FieldElement::one(), self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,6 +352,45 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqrt_ratio_behavior() {
|
||||
let zero = FieldElement::zero();
|
||||
let one = FieldElement::one();
|
||||
let i = constants::SQRT_M1;
|
||||
let two = &one + &one; // 2 is nonsquare mod p.
|
||||
let four = &two + &two; // 4 is square mod p.
|
||||
|
||||
// 0/0 should return (1, 0) since u is 0
|
||||
let (choice, sqrt) = FieldElement::sqrt_ratio_i(&zero, &zero);
|
||||
assert_eq!(choice.unwrap_u8(), 1);
|
||||
assert_eq!(sqrt, zero);
|
||||
assert_eq!(sqrt.is_negative().unwrap_u8(), 0);
|
||||
|
||||
// 1/0 should return (0, 0) since v is 0, u is nonzero
|
||||
let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &zero);
|
||||
assert_eq!(choice.unwrap_u8(), 0);
|
||||
assert_eq!(sqrt, zero);
|
||||
assert_eq!(sqrt.is_negative().unwrap_u8(), 0);
|
||||
|
||||
// 2/1 is nonsquare, so we expect (0, sqrt(i*2))
|
||||
let (choice, sqrt) = FieldElement::sqrt_ratio_i(&two, &one);
|
||||
assert_eq!(choice.unwrap_u8(), 0);
|
||||
assert_eq!(sqrt.square(), &two * &i);
|
||||
assert_eq!(sqrt.is_negative().unwrap_u8(), 0);
|
||||
|
||||
// 4/1 is square, so we expect (1, sqrt(4))
|
||||
let (choice, sqrt) = FieldElement::sqrt_ratio_i(&four, &one);
|
||||
assert_eq!(choice.unwrap_u8(), 1);
|
||||
assert_eq!(sqrt.square(), four);
|
||||
assert_eq!(sqrt.is_negative().unwrap_u8(), 0);
|
||||
|
||||
// 1/4 is square, so we expect (1, 1/sqrt(4))
|
||||
let (choice, sqrt) = FieldElement::sqrt_ratio_i(&one, &four);
|
||||
assert_eq!(choice.unwrap_u8(), 1);
|
||||
assert_eq!(&sqrt.square() * &four, one);
|
||||
assert_eq!(sqrt.is_negative().unwrap_u8(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_p58_vs_ap58_constant() {
|
||||
let a = FieldElement::from_bytes(&A_BYTES);
|
||||
|
|
@ -399,17 +398,6 @@ mod test {
|
|||
assert_eq!(ap58, a.pow_p58());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chi_on_square_and_nonsquare() {
|
||||
let a = FieldElement::from_bytes(&A_BYTES);
|
||||
// a is square
|
||||
assert_eq!(a.chi(), FieldElement::one());
|
||||
let mut two_bytes = [0u8; 32]; two_bytes[0] = 2;
|
||||
let two = FieldElement::from_bytes(&two_bytes);
|
||||
// 2 is nonsquare
|
||||
assert_eq!(two.chi(), FieldElement::minus_one());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equality() {
|
||||
let a = FieldElement::from_bytes(&A_BYTES);
|
||||
|
|
|
|||
|
|
@ -44,12 +44,7 @@ extern crate packed_simd;
|
|||
extern crate rand;
|
||||
extern crate clear_on_drop;
|
||||
extern crate byteorder;
|
||||
|
||||
// The `Digest` trait is implemented using `generic_array`, so we need it
|
||||
// too. Hopefully we can eliminate `generic_array` from `Digest` once const
|
||||
// generics land.
|
||||
extern crate digest;
|
||||
extern crate generic_array;
|
||||
pub extern crate digest;
|
||||
|
||||
// Used for traits related to constant-time code.
|
||||
extern crate subtle;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
//!
|
||||
//! Scalar multiplication on `MontgomeryPoint`s is provided by the `*`
|
||||
//! operator, which implements the Montgomery ladder.
|
||||
//!
|
||||
//!
|
||||
//! # Edwards Conversion
|
||||
//!
|
||||
//! The \\(2\\)-to-\\(1\\) map from the Edwards model to the Montgomery
|
||||
|
|
@ -51,16 +51,15 @@
|
|||
use core::ops::{Mul, MulAssign};
|
||||
|
||||
use constants::APLUS2_OVER_FOUR;
|
||||
use edwards::{CompressedEdwardsY, EdwardsPoint};
|
||||
use field::FieldElement;
|
||||
use edwards::{EdwardsPoint, CompressedEdwardsY};
|
||||
use scalar::Scalar;
|
||||
|
||||
use traits::Identity;
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySwappable;
|
||||
use subtle::ConstantTimeEq;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
|
||||
/// Curve25519 or its twist.
|
||||
|
|
@ -141,7 +140,7 @@ impl MontgomeryPoint {
|
|||
/// \\( \mathbb P(\mathbb F\_p) \\), which we identify with the Kummer
|
||||
/// line of the Montgomery curve.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct ProjectivePoint{
|
||||
struct ProjectivePoint {
|
||||
pub U: FieldElement,
|
||||
pub W: FieldElement,
|
||||
}
|
||||
|
|
@ -161,10 +160,16 @@ impl Default for ProjectivePoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for ProjectivePoint {
|
||||
fn conditional_assign(&mut self, that: &ProjectivePoint, choice: Choice) {
|
||||
self.U.conditional_assign(&that.U, choice);
|
||||
self.W.conditional_assign(&that.W, choice);
|
||||
impl ConditionallySelectable for ProjectivePoint {
|
||||
fn conditional_select(
|
||||
a: &ProjectivePoint,
|
||||
b: &ProjectivePoint,
|
||||
choice: Choice,
|
||||
) -> ProjectivePoint {
|
||||
ProjectivePoint {
|
||||
U: FieldElement::conditional_select(&a.U, &b.U, choice),
|
||||
W: FieldElement::conditional_select(&a.W, &b.W, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +201,7 @@ impl ProjectivePoint {
|
|||
/// (U\_Q : W\_Q) \gets u(P + Q).
|
||||
/// $$
|
||||
fn differential_add_and_double(
|
||||
P: &mut ProjectivePoint,
|
||||
P: &mut ProjectivePoint,
|
||||
Q: &mut ProjectivePoint,
|
||||
affine_PmQ: &FieldElement,
|
||||
) {
|
||||
|
|
@ -249,19 +254,22 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a MontgomeryPoint {
|
|||
// Algorithm 8 of Costello-Smith 2017
|
||||
let affine_u = FieldElement::from_bytes(&self.0);
|
||||
let mut x0 = ProjectivePoint::identity();
|
||||
let mut x1 = ProjectivePoint{ U: affine_u, W: FieldElement::one() };
|
||||
let mut x1 = ProjectivePoint {
|
||||
U: affine_u,
|
||||
W: FieldElement::one(),
|
||||
};
|
||||
|
||||
let bits: [i8; 256] = scalar.bits();
|
||||
|
||||
for i in (0..255).rev() {
|
||||
let choice: u8 = (bits[i+1] ^ bits[i]) as u8;
|
||||
let choice: u8 = (bits[i + 1] ^ bits[i]) as u8;
|
||||
|
||||
debug_assert!(choice == 0 || choice == 1);
|
||||
|
||||
x0.conditional_swap(&mut x1, choice.into());
|
||||
ProjectivePoint::conditional_swap(&mut x0, &mut x1, choice.into());
|
||||
differential_add_and_double(&mut x0, &mut x1, &affine_u);
|
||||
}
|
||||
x0.conditional_swap(&mut x1, Choice::from(bits[0] as u8));
|
||||
ProjectivePoint::conditional_swap(&mut x0, &mut x1, Choice::from(bits[0] as u8));
|
||||
|
||||
x0.to_affine()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,28 +157,28 @@
|
|||
//! [ristretto_main]:
|
||||
//! https://ristretto.group/
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::fmt::Debug;
|
||||
use core::ops::{Add, Sub, Neg};
|
||||
use core::iter::Sum;
|
||||
use core::ops::{Add, Neg, Sub};
|
||||
use core::ops::{AddAssign, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::iter::Sum;
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use rand::{Rng, CryptoRng};
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
use digest::generic_array::typenum::U64;
|
||||
use digest::Digest;
|
||||
use generic_array::typenum::U64;
|
||||
|
||||
use constants;
|
||||
use field::FieldElement;
|
||||
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::ConstantTimeEq;
|
||||
use subtle::Choice;
|
||||
|
||||
use edwards::EdwardsPoint;
|
||||
use edwards::EdwardsBasepointTable;
|
||||
use edwards::EdwardsPoint;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use prelude::*;
|
||||
|
|
@ -577,44 +577,32 @@ impl RistrettoPoint {
|
|||
pub(crate) fn elligator_ristretto_flavor(r_0: &FieldElement) -> RistrettoPoint {
|
||||
let (i, d) = (&constants::SQRT_M1, &constants::EDWARDS_D);
|
||||
let one = FieldElement::one();
|
||||
let one_minus_d_sq = &one - &d.square();
|
||||
let d_minus_one_sq = (d - &one).square();
|
||||
|
||||
let r = i * &r_0.square();
|
||||
|
||||
// D = (dr -a)(ar-d) = -(dr+1)(r+d)
|
||||
let D = -&( &(&(d * &r) + &one) * &(&r + d) );
|
||||
// N = a(d-a)(d+a)(r+1) = -(r+1)(d^2 -1)
|
||||
let d_sq = d.square();
|
||||
let N = -&( &(&d_sq - &one) * &(&r + &one) );
|
||||
|
||||
let mut s = FieldElement::zero();
|
||||
let N_s = &(&r + &one) * &one_minus_d_sq;
|
||||
let mut c = -&one;
|
||||
let D = &(&c - &(d * &r)) * &(&r + d);
|
||||
|
||||
let (N_over_D_is_square, maybe_s) = FieldElement::sqrt_ratio(&N, &D);
|
||||
// s = sqrt(N/D) if N/D is square
|
||||
s.conditional_assign(&maybe_s, N_over_D_is_square);
|
||||
let (Ns_D_is_sq, mut s) = FieldElement::sqrt_ratio_i(&N_s, &D);
|
||||
let mut s_prime = &s * r_0;
|
||||
let s_prime_is_pos = !s_prime.is_negative();
|
||||
s_prime.conditional_negate(s_prime_is_pos);
|
||||
|
||||
// XXX how exactly do we reuse the computation of sqrt(N/D) to find sqrt(rN/D) ?
|
||||
let (rN_over_D_is_square, mut maybe_s) = FieldElement::sqrt_ratio(&(&r*&N), &D);
|
||||
maybe_s.negate();
|
||||
|
||||
// s = -sqrt(rN/D) if rN/D is square (should happen exactly when N/D is nonsquare)
|
||||
debug_assert_eq!((N_over_D_is_square ^ rN_over_D_is_square).unwrap_u8(), 1u8);
|
||||
s.conditional_assign(&maybe_s, rN_over_D_is_square);
|
||||
c.conditional_assign(&r, rN_over_D_is_square);
|
||||
|
||||
// T = (c * (r - one) * (d-one).square()) - D;
|
||||
let T = &(&c * &(&(&r - &one) * &((d - &one).square()))) - &D;
|
||||
s.conditional_assign(&s_prime, !Ns_D_is_sq);
|
||||
c.conditional_assign(&r, !Ns_D_is_sq);
|
||||
|
||||
let N_t = &(&(&c * &(&r - &one)) * &d_minus_one_sq) - &D;
|
||||
let s_sq = s.square();
|
||||
let P = CompletedPoint{
|
||||
|
||||
// The conversion from W_i is exactly the conversion from P1xP1.
|
||||
RistrettoPoint(CompletedPoint{
|
||||
X: &(&s + &s) * &D,
|
||||
Z: &T * &constants::SQRT_AD_MINUS_ONE,
|
||||
Z: &N_t * &constants::SQRT_AD_MINUS_ONE,
|
||||
Y: &FieldElement::one() - &s_sq,
|
||||
T: &FieldElement::one() + &s_sq,
|
||||
};
|
||||
|
||||
// Convert to extended and return.
|
||||
RistrettoPoint(P.to_extended())
|
||||
}.to_extended())
|
||||
}
|
||||
|
||||
/// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG.
|
||||
|
|
@ -870,7 +858,7 @@ define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint
|
|||
#[cfg(feature = "alloc")]
|
||||
impl MultiscalarMul for RistrettoPoint {
|
||||
type Point = RistrettoPoint;
|
||||
|
||||
|
||||
fn multiscalar_mul<I, J>(scalars: I, points: J) -> RistrettoPoint
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -888,7 +876,7 @@ impl MultiscalarMul for RistrettoPoint {
|
|||
#[cfg(feature = "alloc")]
|
||||
impl VartimeMultiscalarMul for RistrettoPoint {
|
||||
type Point = RistrettoPoint;
|
||||
|
||||
|
||||
fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<RistrettoPoint>
|
||||
where
|
||||
I: IntoIterator,
|
||||
|
|
@ -961,11 +949,11 @@ impl RistrettoBasepointTable {
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constant-time conditional assignment
|
||||
// Constant-time conditional selection
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl ConditionallyAssignable for RistrettoPoint {
|
||||
/// Conditionally assign `other` to `self`, if `choice == Choice(1)`.
|
||||
impl ConditionallySelectable for RistrettoPoint {
|
||||
/// Conditionally select between `self` and `other`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
|
@ -973,7 +961,7 @@ impl ConditionallyAssignable for RistrettoPoint {
|
|||
/// # extern crate subtle;
|
||||
/// # extern crate curve25519_dalek;
|
||||
/// #
|
||||
/// use subtle::ConditionallyAssignable;
|
||||
/// use subtle::ConditionallySelectable;
|
||||
/// use subtle::Choice;
|
||||
/// #
|
||||
/// # use curve25519_dalek::traits::Identity;
|
||||
|
|
@ -986,17 +974,18 @@ impl ConditionallyAssignable for RistrettoPoint {
|
|||
///
|
||||
/// let mut P = A;
|
||||
///
|
||||
/// P.conditional_assign(&B, Choice::from(0));
|
||||
/// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(0));
|
||||
/// assert_eq!(P, A);
|
||||
/// P.conditional_assign(&B, Choice::from(1));
|
||||
/// P = RistrettoPoint::conditional_select(&A, &B, Choice::from(1));
|
||||
/// assert_eq!(P, B);
|
||||
/// # }
|
||||
/// ```
|
||||
fn conditional_assign(&mut self, other: &RistrettoPoint, choice: Choice) {
|
||||
self.0.X.conditional_assign(&other.0.X, choice);
|
||||
self.0.Y.conditional_assign(&other.0.Y, choice);
|
||||
self.0.Z.conditional_assign(&other.0.Z, choice);
|
||||
self.0.T.conditional_assign(&other.0.T, choice);
|
||||
fn conditional_select(
|
||||
a: &RistrettoPoint,
|
||||
b: &RistrettoPoint,
|
||||
choice: Choice,
|
||||
) -> RistrettoPoint {
|
||||
RistrettoPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,10 +80,10 @@
|
|||
//! assert!(a == two);
|
||||
//! ```
|
||||
//!
|
||||
//! There is also a constructor that reduces a \\(512\\)-bit integer,
|
||||
//! There is also a constructor that reduces a \\(512\\)-bit integer,
|
||||
//! [`Scalar::from_bytes_mod_order_wide`](struct.Scalar.html#method.from_bytes_mod_order_wide).
|
||||
//!
|
||||
//! To construct a `Scalar` as the hash of some input data, use
|
||||
//! To construct a `Scalar` as the hash of some input data, use
|
||||
//! [`Scalar::hash_from_bytes`](struct.Scalar.html#method.hash_from_bytes),
|
||||
//! which takes a buffer, or
|
||||
//! [`Scalar::from_hash`](struct.Scalar.html#method.from_hash),
|
||||
|
|
@ -138,26 +138,26 @@
|
|||
//! The resulting `Scalar` has exactly the specified bit pattern,
|
||||
//! **except for the highest bit, which will be set to 0**.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::fmt::Debug;
|
||||
use core::iter::{Product, Sum};
|
||||
use core::ops::Index;
|
||||
use core::ops::Neg;
|
||||
use core::ops::{Add, AddAssign};
|
||||
use core::ops::{Sub, SubAssign};
|
||||
use core::ops::{Mul, MulAssign};
|
||||
use core::ops::{Index};
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::iter::{Product, Sum};
|
||||
use core::borrow::Borrow;
|
||||
use core::ops::{Sub, SubAssign};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use prelude::*;
|
||||
|
||||
use rand::{Rng, CryptoRng};
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
use digest::generic_array::typenum::U64;
|
||||
use digest::Digest;
|
||||
use generic_array::typenum::U64;
|
||||
|
||||
use subtle::Choice;
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConstantTimeEq;
|
||||
|
||||
use backend;
|
||||
|
|
@ -343,11 +343,13 @@ impl<'a> Neg for Scalar {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConditionallyAssignable for Scalar {
|
||||
fn conditional_assign(&mut self, other: &Scalar, choice: Choice) {
|
||||
impl ConditionallySelectable for Scalar {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
self.bytes[i].conditional_assign(&other.bytes[i], choice);
|
||||
bytes[i] = u8::conditional_select(&a.bytes[i], &b.bytes[i], choice);
|
||||
}
|
||||
Scalar { bytes }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -579,14 +581,13 @@ impl Scalar {
|
|||
/// use sha2::Sha512;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut h = Sha512::default();
|
||||
///
|
||||
/// h.input(b"To really appreciate architecture, you may even need to commit a murder.");
|
||||
/// h.input(b"While the programs used for The Manhattan Transcripts are of the most extreme");
|
||||
/// h.input(b"nature, they also parallel the most common formula plot: the archetype of");
|
||||
/// h.input(b"murder. Other phantasms were occasionally used to underline the fact that");
|
||||
/// h.input(b"perhaps all architecture, rather than being about functional standards, is");
|
||||
/// h.input(b"about love and death.");
|
||||
/// let mut h = Sha512::new()
|
||||
/// .chain("To really appreciate architecture, you may even need to commit a murder.")
|
||||
/// .chain("While the programs used for The Manhattan Transcripts are of the most extreme")
|
||||
/// .chain("nature, they also parallel the most common formula plot: the archetype of")
|
||||
/// .chain("murder. Other phantasms were occasionally used to underline the fact that")
|
||||
/// .chain("perhaps all architecture, rather than being about functional standards, is")
|
||||
/// .chain("about love and death.");
|
||||
///
|
||||
/// let s = Scalar::from_hash(h);
|
||||
///
|
||||
|
|
@ -982,7 +983,7 @@ impl Scalar {
|
|||
/// # extern crate curve25519_dalek;
|
||||
/// # extern crate subtle;
|
||||
/// # use curve25519_dalek::scalar::Scalar;
|
||||
/// # use subtle::ConditionallyAssignable;
|
||||
/// # use subtle::ConditionallySelectable;
|
||||
/// # fn main() {
|
||||
/// // 2^255 - 1, since `from_bits` clears the high bit
|
||||
/// let _2_255_minus_1 = Scalar::from_bits([0xff;32]);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
use core::fmt::Debug;
|
||||
|
||||
use subtle::ConditionallyNegatable;
|
||||
use subtle::ConditionallyAssignable;
|
||||
use subtle::ConditionallySelectable;
|
||||
use subtle::ConstantTimeEq;
|
||||
use subtle::Choice;
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ unsafe impl<T> ZeroSafe for LookupTable<T> {}
|
|||
|
||||
impl<T> LookupTable<T>
|
||||
where
|
||||
T: Identity + ConditionallyAssignable + ConditionallyNegatable,
|
||||
T: Identity + ConditionallySelectable + ConditionallyNegatable,
|
||||
{
|
||||
/// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time.
|
||||
pub fn select(&self, x: i8) -> T {
|
||||
|
|
|
|||
Loading…
Reference in a new issue