mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-09 21:10:44 +00:00
Merge branch 'release/2.0.0-alpha.0'
This commit is contained in:
commit
17698df9d4
45 changed files with 12616 additions and 499 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -2,6 +2,20 @@
|
|||
|
||||
Entries are listed in reverse chronological order.
|
||||
|
||||
## 2.0.0-alpha.0
|
||||
|
||||
* Fix a data modeling error in the `serde` feature pointed out by Trevor Perrin
|
||||
which caused points and scalars to be serialized with length fields rather
|
||||
than as fixed-size 32-byte arrays. This is a breaking change, but it fixes
|
||||
compatibility with `serde-json` and ensures that the `serde-bincode` encoding
|
||||
matches the conventional encoding for X/Ed25519.
|
||||
* Update `rand_core` to `0.5`, allowing use with new `rand` versions.
|
||||
* Remove the `build.rs` hack which loaded the entire crate into its own
|
||||
`build.rs` to generate constants, and keep the constants in the source code.
|
||||
|
||||
The only significant change is the data model change to the `serde` feature;
|
||||
besides the `rand_core` version bump, there are no other user-visible changes.
|
||||
|
||||
## 1.2.3
|
||||
|
||||
* Fix an issue identified by a Quarkslab audit (and Jack Grigg), where manually
|
||||
|
|
|
|||
45
Cargo.toml
45
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "curve25519-dalek"
|
||||
version = "1.2.3"
|
||||
version = "2.0.0-alpha.0"
|
||||
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
|
||||
"Henry de Valence <hdevalence@hdevalence.ca>"]
|
||||
readme = "README.md"
|
||||
|
|
@ -16,7 +16,6 @@ exclude = [
|
|||
".gitignore",
|
||||
".travis.yml",
|
||||
]
|
||||
build = "build.rs"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
# Disabled for now since this is borked; tracking https://github.com/rust-lang/docs.rs/issues/302
|
||||
|
|
@ -27,46 +26,30 @@ features = ["nightly", "simd_backend"]
|
|||
travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "master"}
|
||||
|
||||
[dev-dependencies]
|
||||
rand_os = "0.1.0"
|
||||
rand_os = "0.2"
|
||||
sha2 = { version = "0.8", default-features = false }
|
||||
bincode = "1"
|
||||
criterion = "0.2"
|
||||
rand = "0.6"
|
||||
rand = "0.7"
|
||||
|
||||
[[bench]]
|
||||
name = "dalek_benchmarks"
|
||||
harness = false
|
||||
|
||||
# Note: we generate precomputed tables by building the crate twice: once as
|
||||
# part of build.rs, and then once "for real".
|
||||
#
|
||||
# This means that the [dependencies] and [build-dependencies] sections must
|
||||
# match exactly, since the build.rs uses the crate itself as a library.
|
||||
|
||||
[dependencies]
|
||||
rand_core = { version = "0.3.0", default-features = false }
|
||||
rand_core = { version = "0.5", default-features = false }
|
||||
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
|
||||
digest = { version = "0.8", default-features = false }
|
||||
clear_on_drop = "=0.2.3"
|
||||
subtle = { version = "2", default-features = false }
|
||||
serde = { version = "1.0", default-features = false, optional = true }
|
||||
packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
rand_core = { version = "0.3.0", default-features = false }
|
||||
byteorder = { version = "^1.2.3", default-features = false, features = ["i128"] }
|
||||
digest = { version = "0.8", default-features = false }
|
||||
clear_on_drop = "=0.2.3"
|
||||
subtle = { version = "2", default-features = false }
|
||||
serde = { version = "1.0", default-features = false, optional = true }
|
||||
packed_simd = { version = "0.3.0", features = ["into_bits"], optional = true }
|
||||
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
|
||||
packed_simd = { version = "0.3", features = ["into_bits"], optional = true }
|
||||
zeroize = { version = "1", default-features = false }
|
||||
|
||||
[features]
|
||||
nightly = ["subtle/nightly", "clear_on_drop/nightly"]
|
||||
nightly = ["subtle/nightly"]
|
||||
default = ["std", "u64_backend"]
|
||||
std = ["alloc", "subtle/std", "rand_core/std"]
|
||||
alloc = []
|
||||
yolocrypto = []
|
||||
alloc = ["zeroize/alloc"]
|
||||
|
||||
# The u32 backend uses u32s with u64 products.
|
||||
u32_backend = []
|
||||
|
|
@ -74,12 +57,6 @@ u32_backend = []
|
|||
u64_backend = []
|
||||
# The SIMD backend uses parallel formulas, using either AVX2 or AVX512-IFMA.
|
||||
simd_backend = ["nightly", "u64_backend", "packed_simd"]
|
||||
# Old name for the SIMD backend, preserved for compatibility
|
||||
# DEPRECATED: this is now an alias for `simd_backend` and may be removed
|
||||
# in some future release.
|
||||
avx2_backend = ["simd_backend"]
|
||||
|
||||
# Signals that we're in the main build stage. This is off by default,
|
||||
# to signal stage 1 of the build, where build.rs loads the library
|
||||
# into the build script. Then, the build.rs emits the stage2_build
|
||||
# feature before the main-stage compilation.
|
||||
stage2_build = []
|
||||
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2016-2018 Isis Agora Lovecruft, Henry de Valence. All rights reserved.
|
||||
Copyright (c) 2016-2019 Isis Agora Lovecruft, Henry de Valence. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
|
|
|||
|
|
@ -202,5 +202,5 @@ contributions.
|
|||
[docs-external]: https://doc.dalek.rs/curve25519_dalek/
|
||||
[docs-internal]: https://doc-internal.dalek.rs/curve25519_dalek/
|
||||
[criterion]: https://github.com/japaric/criterion.rs
|
||||
[parallel_doc]: https://doc-internal.dalek.rs/curve25519_dalek/backend/avx2/index.html
|
||||
[parallel_doc]: https://doc-internal.dalek.rs/curve25519_dalek/backend/vector/avx2/index.html
|
||||
[subtle_doc]: https://doc.dalek.rs/subtle/
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ static MULTISCALAR_SIZES: [usize; 13] = [1, 2, 4, 8, 16, 32, 64, 128, 256, 384,
|
|||
|
||||
mod edwards_benches {
|
||||
use super::*;
|
||||
use curve25519_dalek::edwards;
|
||||
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
|
||||
fn compress(c: &mut Criterion) {
|
||||
|
|
@ -47,7 +47,7 @@ mod edwards_benches {
|
|||
let B = &constants::ED25519_BASEPOINT_POINT;
|
||||
let s = Scalar::from(897987897u64).invert();
|
||||
c.bench_function("Constant-time variable-base scalar mul", move |b| {
|
||||
b.iter(|| B * &s)
|
||||
b.iter(|| B * s)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ mod edwards_benches {
|
|||
|
||||
mod multiscalar_benches {
|
||||
use super::*;
|
||||
use curve25519_dalek::edwards;
|
||||
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
use curve25519_dalek::edwards::VartimeEdwardsPrecomputation;
|
||||
use curve25519_dalek::traits::MultiscalarMul;
|
||||
|
|
|
|||
131
build.rs
131
build.rs
|
|
@ -1,131 +0,0 @@
|
|||
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
|
||||
#![cfg_attr(feature = "nightly", feature(doc_cfg))]
|
||||
#![cfg_attr(feature = "simd_backend", feature(stdsimd))]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
extern crate alloc;
|
||||
extern crate byteorder;
|
||||
extern crate clear_on_drop;
|
||||
extern crate core;
|
||||
extern crate digest;
|
||||
extern crate rand_core;
|
||||
extern crate subtle;
|
||||
|
||||
#[cfg(all(feature = "nightly", feature = "packed_simd"))]
|
||||
extern crate packed_simd;
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
// Replicate lib.rs in the build.rs, since we're effectively building the whole crate twice.
|
||||
//
|
||||
// This should be fixed up by refactoring our code to seperate the "minimal" parts from the rest.
|
||||
//
|
||||
// For instance, this shouldn't exist here at all, but it does.
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
// Macros come first!
|
||||
#[path = "src/macros.rs"]
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// Public modules
|
||||
|
||||
#[path = "src/constants.rs"]
|
||||
mod constants;
|
||||
#[path = "src/edwards.rs"]
|
||||
mod edwards;
|
||||
#[path = "src/montgomery.rs"]
|
||||
mod montgomery;
|
||||
#[path = "src/ristretto.rs"]
|
||||
mod ristretto;
|
||||
#[path = "src/scalar.rs"]
|
||||
mod scalar;
|
||||
#[path = "src/traits.rs"]
|
||||
mod traits;
|
||||
|
||||
// Internal modules
|
||||
|
||||
#[path = "src/backend/mod.rs"]
|
||||
mod backend;
|
||||
#[path = "src/field.rs"]
|
||||
mod field;
|
||||
#[path = "src/prelude.rs"]
|
||||
mod prelude;
|
||||
#[path = "src/window.rs"]
|
||||
mod window;
|
||||
|
||||
use edwards::EdwardsBasepointTable;
|
||||
|
||||
fn main() {
|
||||
// Enable the "stage2_build" feature in the main build stage
|
||||
println!("cargo:rustc-cfg=feature=\"stage2_build\"\n");
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join("basepoint_table.rs");
|
||||
let mut f = File::create(&dest_path).unwrap();
|
||||
|
||||
// Generate a table of precomputed multiples of the basepoint
|
||||
let table = EdwardsBasepointTable::create(&constants::ED25519_BASEPOINT_POINT);
|
||||
|
||||
f.write_all(
|
||||
format!(
|
||||
"\n
|
||||
#[cfg(feature = \"u32_backend\")]
|
||||
use backend::serial::u32::field::FieldElement2625;
|
||||
|
||||
#[cfg(feature = \"u64_backend\")]
|
||||
use backend::serial::u64::field::FieldElement51;
|
||||
|
||||
use edwards::EdwardsBasepointTable;
|
||||
|
||||
use backend::serial::curve_models::AffineNielsPoint;
|
||||
|
||||
use window::LookupTable;
|
||||
|
||||
/// Table containing precomputed multiples of the Ed25519 basepoint \\\\(B = (x, 4/5)\\\\).
|
||||
pub const ED25519_BASEPOINT_TABLE: EdwardsBasepointTable = ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN;
|
||||
|
||||
/// Inner constant, used to avoid filling the docs with precomputed points.
|
||||
#[doc(hidden)]
|
||||
pub const ED25519_BASEPOINT_TABLE_INNER_DOC_HIDDEN: EdwardsBasepointTable = {:?};
|
||||
\n\n",
|
||||
&table
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Now generate AFFINE_ODD_MULTIPLES_OF_BASEPOINT
|
||||
// if we are going to build the serial scalar_mul backend
|
||||
#[cfg(not(all(
|
||||
feature = "simd_backend",
|
||||
any(target_feature = "avx2", target_feature = "avx512ifma")
|
||||
)))]
|
||||
{
|
||||
use backend::serial::curve_models::AffineNielsPoint;
|
||||
use window::NafLookupTable8;
|
||||
|
||||
let B = &constants::ED25519_BASEPOINT_POINT;
|
||||
let odd_multiples = NafLookupTable8::<AffineNielsPoint>::from(B);
|
||||
|
||||
f.write_all(
|
||||
format!(
|
||||
"\n
|
||||
use window::NafLookupTable8;
|
||||
/// Odd multiples of the basepoint `[B, 3B, 5B, 7B, 9B, 11B, 13B, 15B, ..., 127B]`.
|
||||
pub(crate) const AFFINE_ODD_MULTIPLES_OF_BASEPOINT: NafLookupTable8<AffineNielsPoint> = {:?};
|
||||
\n\n",
|
||||
&odd_multiples
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -128,6 +128,8 @@ use core::ops::{Add, Neg, Sub};
|
|||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use constants;
|
||||
|
||||
use edwards::EdwardsPoint;
|
||||
|
|
@ -182,6 +184,14 @@ pub struct AffineNielsPoint {
|
|||
pub xy2d: FieldElement,
|
||||
}
|
||||
|
||||
impl Zeroize for AffineNielsPoint {
|
||||
fn zeroize(&mut self) {
|
||||
self.y_plus_x.zeroize();
|
||||
self.y_minus_x.zeroize();
|
||||
self.xy2d.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
/// A pre-computed point on the \\( \mathbb P\^3 \\) model for the
|
||||
/// curve, represented as \\((Y+X, Y-X, Z, 2dXY)\\) in "Niels coordinates".
|
||||
///
|
||||
|
|
@ -195,6 +205,15 @@ pub struct ProjectiveNielsPoint {
|
|||
pub T2d: FieldElement,
|
||||
}
|
||||
|
||||
impl Zeroize for ProjectiveNielsPoint {
|
||||
fn zeroize(&mut self) {
|
||||
self.Y_plus_X.zeroize();
|
||||
self.Y_minus_X.zeroize();
|
||||
self.Z.zeroize();
|
||||
self.T2d.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
pub mod variable_base;
|
||||
|
||||
#[cfg(feature = "stage2_build")]
|
||||
pub mod vartime_double_base;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
|
|
|
|||
|
|
@ -94,19 +94,16 @@ impl VartimeMultiscalarMul for Pippenger {
|
|||
// Collect optimized scalars and points in buffers for repeated access
|
||||
// (scanning the whole set per digit position).
|
||||
let scalars = scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_2w(w));
|
||||
|
||||
let points = points
|
||||
.into_iter()
|
||||
.map(|p| p.map(|P| P.to_projective_niels()));
|
||||
|
||||
let scalars_points = scalars.zip(points).map(|(s,maybe_p)| maybe_p.map(|p| (s,p) ) )
|
||||
.collect::<Option<Vec<_>>>();
|
||||
let scalars_points = match scalars_points {
|
||||
Some(sp) => sp,
|
||||
None => return None,
|
||||
};
|
||||
let scalars_points = scalars
|
||||
.zip(points)
|
||||
.map(|(s, maybe_p)| maybe_p.map(|p| (s, p)))
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
// Prepare 2^w/2 buckets.
|
||||
// buckets[i] corresponds to a multiplication factor (i+1).
|
||||
|
|
@ -160,8 +157,7 @@ impl VartimeMultiscalarMul for Pippenger {
|
|||
|
||||
Some(
|
||||
columns
|
||||
.fold(hi_column, |total, p| total.mul_by_pow_2(w as u32) + p)
|
||||
.into(),
|
||||
.fold(hi_column, |total, p| total.mul_by_pow_2(w as u32) + p),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,14 +67,10 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus {
|
|||
.map(|c| c.borrow().non_adjacent_form(5))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dynamic_lookup_tables = match dynamic_points
|
||||
let dynamic_lookup_tables = dynamic_points
|
||||
.into_iter()
|
||||
.map(|P_opt| P_opt.map(|P| NafLookupTable5::<ProjectiveNielsPoint>::from(&P)))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
{
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
let sp = self.static_lookup_tables.len();
|
||||
let dp = dynamic_lookup_tables.len();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -106,7 +106,7 @@ impl MultiscalarMul for Straus {
|
|||
J: IntoIterator,
|
||||
J::Item: Borrow<EdwardsPoint>,
|
||||
{
|
||||
use clear_on_drop::ClearOnDrop;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use backend::serial::curve_models::ProjectiveNielsPoint;
|
||||
use window::LookupTable;
|
||||
|
|
@ -119,12 +119,12 @@ impl MultiscalarMul for Straus {
|
|||
|
||||
// This puts the scalar digits into a heap-allocated Vec.
|
||||
// To ensure that these are erased, pass ownership of the Vec into a
|
||||
// ClearOnDrop wrapper.
|
||||
// Zeroizing wrapper.
|
||||
let scalar_digits_vec: Vec<_> = scalars
|
||||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
let scalar_digits = ClearOnDrop::new(scalar_digits_vec);
|
||||
let scalar_digits = Zeroizing::new(scalar_digits_vec);
|
||||
|
||||
let mut Q = EdwardsPoint::identity();
|
||||
for j in (0..64).rev() {
|
||||
|
|
@ -137,6 +137,7 @@ impl MultiscalarMul for Straus {
|
|||
Q = (&Q + &R_i).to_extended();
|
||||
}
|
||||
}
|
||||
|
||||
Q
|
||||
}
|
||||
}
|
||||
|
|
@ -168,14 +169,10 @@ impl VartimeMultiscalarMul for Straus {
|
|||
.map(|c| c.borrow().non_adjacent_form(5))
|
||||
.collect();
|
||||
|
||||
let lookup_tables = match points
|
||||
let lookup_tables = points
|
||||
.into_iter()
|
||||
.map(|P_opt| P_opt.map(|P| NafLookupTable5::<ProjectiveNielsPoint>::from(&P)))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
{
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
let mut r = ProjectivePoint::identity();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; coding: utf-8; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -24,6 +24,8 @@ use core::ops::{Sub, SubAssign};
|
|||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// A `FieldElement2625` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
|
|
@ -55,6 +57,12 @@ impl Debug for FieldElement2625 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Zeroize for FieldElement2625 {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> AddAssign<&'b FieldElement2625> for FieldElement2625 {
|
||||
fn add_assign(&mut self, _rhs: &'b FieldElement2625) {
|
||||
for i in 0..10 {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
use core::fmt::Debug;
|
||||
use core::ops::{Index, IndexMut};
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use constants;
|
||||
|
||||
/// The `Scalar29` struct represents an element in ℤ/lℤ as 9 29-bit limbs
|
||||
|
|
@ -25,6 +27,12 @@ impl Debug for Scalar29 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Zeroize for Scalar29 {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Scalar29 {
|
||||
type Output = u32;
|
||||
fn index(&self, _index: usize) -> &u32 {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; coding: utf-8; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -20,6 +20,8 @@ use core::ops::{Sub, SubAssign};
|
|||
use subtle::Choice;
|
||||
use subtle::ConditionallySelectable;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// A `FieldElement51` represents an element of the field
|
||||
/// \\( \mathbb Z / (2\^{255} - 19)\\).
|
||||
///
|
||||
|
|
@ -44,6 +46,12 @@ impl Debug for FieldElement51 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Zeroize for FieldElement51 {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> AddAssign<&'b FieldElement51> for FieldElement51 {
|
||||
fn add_assign(&mut self, _rhs: &'b FieldElement51) {
|
||||
for i in 0..5 {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
use core::fmt::Debug;
|
||||
use core::ops::{Index, IndexMut};
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use constants;
|
||||
|
||||
/// The `Scalar52` struct represents an element in
|
||||
|
|
@ -27,6 +29,12 @@ impl Debug for Scalar52 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Zeroize for Scalar52 {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for Scalar52 {
|
||||
type Output = u64;
|
||||
fn index(&self, _index: usize) -> &u64 {
|
||||
|
|
@ -240,7 +248,7 @@ impl Scalar52 {
|
|||
(sum >> 52, w)
|
||||
}
|
||||
|
||||
// note: l3 is zero, so its multiplies can be skipped
|
||||
// note: l[3] is zero, so its multiples can be skipped
|
||||
let l = &constants::L;
|
||||
|
||||
// the first half computes the Montgomery adjustment factor n, and begins adding n*l to make limbs divisible by R
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; coding: utf-8; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -41,6 +41,7 @@ const D_LANES64: u8 = 0b11_00_00_00;
|
|||
|
||||
use core::ops::{Add, Mul, Neg};
|
||||
use packed_simd::{i32x8, u32x8, u64x4, IntoBits};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use backend::vector::avx2::constants::{P_TIMES_16_HI, P_TIMES_16_LO, P_TIMES_2_HI, P_TIMES_2_LO};
|
||||
use backend::serial::u64::field::FieldElement51;
|
||||
|
|
@ -449,7 +450,7 @@ impl FieldElement2625x4 {
|
|||
// hi (c(x3), c(y3), c(x2), c(y2), c(z3), c(w3), c(z2), c(w2))
|
||||
// -> (c(x1), c(y1), c(x2), c(y2), c(z1), c(w1), c(z2), c(w2))
|
||||
//
|
||||
// which is exactly the vector of carryins for
|
||||
// which is exactly the vector of carryins for
|
||||
//
|
||||
// ( x2, y2, x3, y3, z2, w2, z3, w3).
|
||||
//
|
||||
|
|
@ -462,7 +463,7 @@ impl FieldElement2625x4 {
|
|||
|
||||
let mut v = self.0;
|
||||
|
||||
let c10 = rotated_carryout(v[0]);
|
||||
let c10 = rotated_carryout(v[0]);
|
||||
v[0] = (v[0] & masks) + combine(u32x8::splat(0), c10);
|
||||
|
||||
let c32 = rotated_carryout(v[1]);
|
||||
|
|
@ -873,6 +874,11 @@ impl<'a, 'b> Mul<&'b FieldElement2625x4> for &'a FieldElement2625x4 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Zeroize for FieldElement2625x4 {
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
|
|
|||
|
|
@ -1,24 +1,15 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
|
||||
// Conditionally include the AVX2 notes if:
|
||||
// - we're on nightly (so we can include docs at all)
|
||||
// - we're in stage 2 of the build.
|
||||
// The latter point prevents a really silly and annoying problem,
|
||||
// where the location of ".." is different depending on whether we're
|
||||
// building the crate for real, or whether we're in build.rs
|
||||
// generating the lookup tables (in which case we're relative to the
|
||||
// location of build.rs, not lib.rs, so the markdown file appears
|
||||
// missing).
|
||||
#![cfg_attr(
|
||||
all(feature = "nightly", feature = "stage2_build"),
|
||||
feature = "nightly",
|
||||
doc(include = "../../../../docs/avx2-notes.md")
|
||||
)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2018 Henry de Valence
|
||||
// Copyright (c) 2018-2019 Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2018 Henry de Valence
|
||||
// Copyright (c) 2018-2019 Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; coding: utf-8; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2018 Henry de Valence
|
||||
// Copyright (c) 2018-2019 Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2018 Henry de Valence
|
||||
// Copyright (c) 2018-2019 Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
|
||||
#![cfg_attr(
|
||||
all(feature = "nightly", feature = "stage2_build"),
|
||||
feature = "nightly",
|
||||
doc(include = "../../../../docs/ifma-notes.md")
|
||||
)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,16 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
|
||||
// - Henry de Valence <hdevalence@hdevalence.ca>
|
||||
|
||||
// Conditionally include the notes if:
|
||||
// - we're on nightly (so we can include docs at all)
|
||||
// - we're in stage 2 of the build.
|
||||
// The latter point prevents a really silly and annoying problem,
|
||||
// where the location of ".." is different depending on whether we're
|
||||
// building the crate for real, or whether we're in build.rs
|
||||
// generating the lookup tables (in which case we're relative to the
|
||||
// location of build.rs, not lib.rs, so the markdown file appears
|
||||
// missing).
|
||||
// Conditionally include the notes if we're on nightly (so we can include docs at all).
|
||||
#![cfg_attr(
|
||||
all(feature = "nightly", feature = "stage2_build"),
|
||||
feature = "nightly",
|
||||
doc(include = "../../../docs/parallel-formulas.md")
|
||||
)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@ impl VartimeMultiscalarMul for Pippenger {
|
|||
.into_iter()
|
||||
.map(|p| p.map(|P| CachedPoint::from(ExtendedPoint::from(P))));
|
||||
|
||||
let scalars_points = scalars.zip(points).map(|(s,maybe_p)| maybe_p.map(|p| (s,p) ) )
|
||||
.collect::<Option<Vec<_>>>();
|
||||
let scalars_points = match scalars_points {
|
||||
Some(sp) => sp,
|
||||
None => return None,
|
||||
};
|
||||
let scalars_points = scalars
|
||||
.zip(points)
|
||||
.map(|(s, maybe_p)| maybe_p.map(|p| (s, p)))
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
// Prepare 2^w/2 buckets.
|
||||
// buckets[i] corresponds to a multiplication factor (i+1).
|
||||
|
|
|
|||
|
|
@ -66,14 +66,10 @@ impl VartimePrecomputedMultiscalarMul for VartimePrecomputedStraus {
|
|||
.map(|c| c.borrow().non_adjacent_form(5))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let dynamic_lookup_tables = match dynamic_points
|
||||
let dynamic_lookup_tables = dynamic_points
|
||||
.into_iter()
|
||||
.map(|P_opt| P_opt.map(|P| NafLookupTable5::<CachedPoint>::from(&P)))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
{
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
let sp = self.static_lookup_tables.len();
|
||||
let dp = dynamic_lookup_tables.len();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use core::borrow::Borrow;
|
||||
|
||||
use clear_on_drop::ClearOnDrop;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use backend::vector::{CachedPoint, ExtendedPoint};
|
||||
use edwards::EdwardsPoint;
|
||||
|
|
@ -54,8 +54,8 @@ impl MultiscalarMul for Straus {
|
|||
.into_iter()
|
||||
.map(|s| s.borrow().to_radix_16())
|
||||
.collect();
|
||||
// Pass ownership to a ClearOnDrop wrapper
|
||||
let scalar_digits = ClearOnDrop::new(scalar_digits_vec);
|
||||
// Pass ownership to a `Zeroizing` wrapper
|
||||
let scalar_digits = Zeroizing::new(scalar_digits_vec);
|
||||
|
||||
let mut Q = ExtendedPoint::identity();
|
||||
for j in (0..64).rev() {
|
||||
|
|
@ -83,14 +83,10 @@ impl VartimeMultiscalarMul for Straus {
|
|||
.into_iter()
|
||||
.map(|c| c.borrow().non_adjacent_form(5))
|
||||
.collect();
|
||||
let lookup_tables: Vec<_> = match points
|
||||
let lookup_tables: Vec<_> = points
|
||||
.into_iter()
|
||||
.map(|P_opt| P_opt.map(|P| NafLookupTable5::<CachedPoint>::from(&P)))
|
||||
.collect::<Option<Vec<_>>>()
|
||||
{
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
let mut Q = ExtendedPoint::identity();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -83,16 +83,8 @@ pub const BASEPOINT_ORDER: Scalar = Scalar{
|
|||
],
|
||||
};
|
||||
|
||||
// Precomputed basepoint table is generated into a file by build.rs
|
||||
|
||||
#[cfg(feature = "stage2_build")]
|
||||
include!(concat!(env!("OUT_DIR"), "/basepoint_table.rs"));
|
||||
|
||||
#[cfg(feature = "stage2_build")]
|
||||
use ristretto::RistrettoBasepointTable;
|
||||
|
||||
/// The Ristretto basepoint, as a `RistrettoBasepointTable` for scalar multiplication.
|
||||
#[cfg(feature = "stage2_build")]
|
||||
pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable
|
||||
= RistrettoBasepointTable(ED25519_BASEPOINT_TABLE);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -195,7 +195,7 @@ impl CompressedEdwardsY {
|
|||
let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7);
|
||||
X.conditional_negate(compressed_sign_bit);
|
||||
|
||||
Some(EdwardsPoint{ X: X, Y: Y, Z: Z, T: &X * &Y })
|
||||
Some(EdwardsPoint{ X, Y, Z, T: &X * &Y })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +217,12 @@ impl Serialize for EdwardsPoint {
|
|||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_bytes(self.compress().as_bytes())
|
||||
use serde::ser::SerializeTuple;
|
||||
let mut tup = serializer.serialize_tuple(32)?;
|
||||
for byte in self.compress().as_bytes().iter() {
|
||||
tup.serialize_element(byte)?;
|
||||
}
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +231,12 @@ impl Serialize for CompressedEdwardsY {
|
|||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_bytes(self.as_bytes())
|
||||
use serde::ser::SerializeTuple;
|
||||
let mut tup = serializer.serialize_tuple(32)?;
|
||||
for byte in self.as_bytes().iter() {
|
||||
tup.serialize_element(byte)?;
|
||||
}
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,22 +254,21 @@ impl<'de> Deserialize<'de> for EdwardsPoint {
|
|||
formatter.write_str("a valid point in Edwards y + sign format")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<EdwardsPoint, E>
|
||||
where E: serde::de::Error
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<EdwardsPoint, A::Error>
|
||||
where A: serde::de::SeqAccess<'de>
|
||||
{
|
||||
if v.len() == 32 {
|
||||
let mut arr32 = [0u8; 32];
|
||||
arr32[0..32].copy_from_slice(v);
|
||||
CompressedEdwardsY(arr32)
|
||||
.decompress()
|
||||
.ok_or(serde::de::Error::custom("decompression failed"))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(v.len(), &self))
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = seq.next_element()?
|
||||
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
|
||||
}
|
||||
CompressedEdwardsY(bytes)
|
||||
.decompress()
|
||||
.ok_or(serde::de::Error::custom("decompression failed"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(EdwardsPointVisitor)
|
||||
deserializer.deserialize_tuple(32, EdwardsPointVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -277,20 +286,19 @@ impl<'de> Deserialize<'de> for CompressedEdwardsY {
|
|||
formatter.write_str("32 bytes of data")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<CompressedEdwardsY, E>
|
||||
where E: serde::de::Error
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<CompressedEdwardsY, A::Error>
|
||||
where A: serde::de::SeqAccess<'de>
|
||||
{
|
||||
if v.len() == 32 {
|
||||
let mut arr32 = [0u8; 32];
|
||||
arr32[0..32].copy_from_slice(v);
|
||||
Ok(CompressedEdwardsY(arr32))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(v.len(), &self))
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = seq.next_element()?
|
||||
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
|
||||
}
|
||||
Ok(CompressedEdwardsY(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(CompressedEdwardsYVisitor)
|
||||
deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -449,7 +457,7 @@ impl EdwardsPoint {
|
|||
AffineNielsPoint{
|
||||
y_plus_x: &y + &x,
|
||||
y_minus_x: &y - &x,
|
||||
xy2d: xy2d
|
||||
xy2d
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -726,7 +734,6 @@ impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation {
|
|||
|
||||
impl EdwardsPoint {
|
||||
/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint.
|
||||
#[cfg(feature = "stage2_build")]
|
||||
pub fn vartime_double_scalar_mul_basepoint(
|
||||
a: &Scalar,
|
||||
A: &EdwardsPoint,
|
||||
|
|
@ -810,7 +817,7 @@ impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar {
|
|||
/// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by
|
||||
/// computing the multiple \\(aB\\) of this basepoint \\(B\\).
|
||||
fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint {
|
||||
basepoint_table * &self
|
||||
basepoint_table * self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -908,7 +915,7 @@ impl EdwardsPoint {
|
|||
/// assert_eq!((P+Q).is_torsion_free(), false);
|
||||
/// ```
|
||||
pub fn is_torsion_free(&self) -> bool {
|
||||
(self * &constants::BASEPOINT_ORDER).is_identity()
|
||||
(self * constants::BASEPOINT_ORDER).is_identity()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -937,7 +944,7 @@ impl Debug for EdwardsBasepointTable {
|
|||
// Tests
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#[cfg(all(test, feature = "stage2_build"))]
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use field::FieldElement;
|
||||
use scalar::Scalar;
|
||||
|
|
@ -1181,7 +1188,7 @@ mod test {
|
|||
|
||||
// Test that sum works on owning iterators
|
||||
let s = Scalar::from(2u64);
|
||||
let mapped = vec.iter().map(|x| x * &s);
|
||||
let mapped = vec.iter().map(|x| x * s);
|
||||
let sum: EdwardsPoint = mapped.sum();
|
||||
|
||||
assert_eq!(sum, &P1 * &s + &P2 * &s);
|
||||
|
|
@ -1204,10 +1211,10 @@ mod test {
|
|||
#[test]
|
||||
fn is_small_order() {
|
||||
// The basepoint has large prime order
|
||||
assert!(constants::ED25519_BASEPOINT_POINT.is_small_order() == false);
|
||||
assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order());
|
||||
// constants::EIGHT_TORSION has all points of small order.
|
||||
for torsion_point in &constants::EIGHT_TORSION {
|
||||
assert!(torsion_point.is_small_order() == true);
|
||||
assert!(torsion_point.is_small_order());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1219,8 +1226,8 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn is_identity() {
|
||||
assert!( EdwardsPoint::identity().is_identity() == true);
|
||||
assert!(constants::ED25519_BASEPOINT_POINT.is_identity() == false);
|
||||
assert!( EdwardsPoint::identity().is_identity());
|
||||
assert!(!constants::ED25519_BASEPOINT_POINT.is_identity());
|
||||
}
|
||||
|
||||
/// Rust's debug builds have overflow and underflow trapping,
|
||||
|
|
@ -1411,10 +1418,18 @@ mod test {
|
|||
let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap();
|
||||
assert_eq!(encoded, enc_compressed);
|
||||
|
||||
// Check that the encoding is 32 bytes exactly
|
||||
assert_eq!(encoded.len(), 32);
|
||||
|
||||
let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap();
|
||||
let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap();
|
||||
|
||||
assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT);
|
||||
assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED);
|
||||
|
||||
// Check that the encoding itself matches the usual one
|
||||
let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes();
|
||||
let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap();
|
||||
assert_eq!(bp, constants::ED25519_BASEPOINT_POINT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -42,11 +42,11 @@ extern crate std;
|
|||
extern crate packed_simd;
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate clear_on_drop;
|
||||
pub extern crate digest;
|
||||
extern crate rand_core;
|
||||
#[cfg(all(test, feature = "stage2_build"))]
|
||||
#[cfg(test)]
|
||||
extern crate rand_os;
|
||||
extern crate zeroize;
|
||||
|
||||
// Used for traits related to constant-time code.
|
||||
extern crate subtle;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -64,6 +64,7 @@ use subtle::ConstantTimeEq;
|
|||
/// Holds the \\(u\\)-coordinate of a point on the Montgomery form of
|
||||
/// Curve25519 or its twist.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct MontgomeryPoint(pub [u8; 32]);
|
||||
|
||||
/// Equality of `MontgomeryPoint`s is defined mod p.
|
||||
|
|
@ -104,6 +105,11 @@ impl MontgomeryPoint {
|
|||
/// Attempt to convert to an `EdwardsPoint`, using the supplied
|
||||
/// choice of sign for the `EdwardsPoint`.
|
||||
///
|
||||
/// # Inputs
|
||||
///
|
||||
/// * `sign`: a `u8` donating the desired sign of the resulting
|
||||
/// `EdwardsPoint`. `0` denotes positive and `1` negative.
|
||||
///
|
||||
/// # Return
|
||||
///
|
||||
/// * `Some(EdwardsPoint)` if `self` is the \\(u\\)-coordinate of a
|
||||
|
|
@ -299,7 +305,7 @@ impl<'a, 'b> Mul<&'b MontgomeryPoint> for &'a Scalar {
|
|||
// Tests
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#[cfg(all(test, feature = "stage2_build"))]
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use constants;
|
||||
use super::*;
|
||||
|
|
@ -307,6 +313,22 @@ mod test {
|
|||
#[cfg(feature = "rand")]
|
||||
use rand_os::OsRng;
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_basepoint_roundtrip() {
|
||||
use bincode;
|
||||
|
||||
let encoded = bincode::serialize(&constants::X25519_BASEPOINT).unwrap();
|
||||
let decoded: MontgomeryPoint = bincode::deserialize(&encoded).unwrap();
|
||||
|
||||
assert_eq!(encoded.len(), 32);
|
||||
assert_eq!(decoded, constants::X25519_BASEPOINT);
|
||||
|
||||
let raw_bytes = constants::X25519_BASEPOINT.as_bytes();
|
||||
let bp: MontgomeryPoint = bincode::deserialize(raw_bytes).unwrap();
|
||||
assert_eq!(bp, constants::X25519_BASEPOINT);
|
||||
}
|
||||
|
||||
/// Test Montgomery -> Edwards on the X/Ed25519 basepoint
|
||||
#[test]
|
||||
fn basepoint_montgomery_to_edwards() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -297,9 +297,9 @@ impl CompressedRistretto {
|
|||
let t = &x * &y;
|
||||
|
||||
if ok.unwrap_u8() == 0u8 || t.is_negative().unwrap_u8() == 1u8 || y.is_zero().unwrap_u8() == 1u8 {
|
||||
return None;
|
||||
None
|
||||
} else {
|
||||
return Some(RistrettoPoint(EdwardsPoint{X: x, Y: y, Z: one, T: t}));
|
||||
Some(RistrettoPoint(EdwardsPoint{X: x, Y: y, Z: one, T: t}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,7 +334,12 @@ impl Serialize for RistrettoPoint {
|
|||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_bytes(self.compress().as_bytes())
|
||||
use serde::ser::SerializeTuple;
|
||||
let mut tup = serializer.serialize_tuple(32)?;
|
||||
for byte in self.compress().as_bytes().iter() {
|
||||
tup.serialize_element(byte)?;
|
||||
}
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,7 +348,12 @@ impl Serialize for CompressedRistretto {
|
|||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_bytes(self.as_bytes())
|
||||
use serde::ser::SerializeTuple;
|
||||
let mut tup = serializer.serialize_tuple(32)?;
|
||||
for byte in self.as_bytes().iter() {
|
||||
tup.serialize_element(byte)?;
|
||||
}
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -361,22 +371,21 @@ impl<'de> Deserialize<'de> for RistrettoPoint {
|
|||
formatter.write_str("a valid point in Ristretto format")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<RistrettoPoint, E>
|
||||
where E: serde::de::Error
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<RistrettoPoint, A::Error>
|
||||
where A: serde::de::SeqAccess<'de>
|
||||
{
|
||||
if v.len() == 32 {
|
||||
let mut arr32 = [0u8; 32];
|
||||
arr32[0..32].copy_from_slice(v);
|
||||
CompressedRistretto(arr32)
|
||||
.decompress()
|
||||
.ok_or(serde::de::Error::custom("decompression failed"))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(v.len(), &self))
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = seq.next_element()?
|
||||
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
|
||||
}
|
||||
CompressedRistretto(bytes)
|
||||
.decompress()
|
||||
.ok_or(serde::de::Error::custom("decompression failed"))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(RistrettoPointVisitor)
|
||||
deserializer.deserialize_tuple(32, RistrettoPointVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -394,20 +403,19 @@ impl<'de> Deserialize<'de> for CompressedRistretto {
|
|||
formatter.write_str("32 bytes of data")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<CompressedRistretto, E>
|
||||
where E: serde::de::Error
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<CompressedRistretto, A::Error>
|
||||
where A: serde::de::SeqAccess<'de>
|
||||
{
|
||||
if v.len() == 32 {
|
||||
let mut arr32 = [0u8; 32];
|
||||
arr32[0..32].copy_from_slice(v);
|
||||
Ok(CompressedRistretto(arr32))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(v.len(), &self))
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = seq.next_element()?
|
||||
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
|
||||
}
|
||||
Ok(CompressedRistretto(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(CompressedRistrettoVisitor)
|
||||
deserializer.deserialize_tuple(32, CompressedRistrettoVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -529,11 +537,11 @@ impl RistrettoPoint {
|
|||
let eg = &e * &g;
|
||||
let fh = &f * &h;
|
||||
|
||||
BatchCompressState{ e: e, f: f, g: g, h: h, eg: eg, fh: fh }
|
||||
BatchCompressState{ e, f, g, h, eg, fh }
|
||||
}
|
||||
}
|
||||
|
||||
let states: Vec<BatchCompressState> = points.into_iter().map(|P| BatchCompressState::from(P)).collect();
|
||||
let states: Vec<BatchCompressState> = points.into_iter().map(BatchCompressState::from).collect();
|
||||
|
||||
let mut invs: Vec<FieldElement> = states.iter().map(|state| state.efgh()).collect();
|
||||
|
||||
|
|
@ -847,7 +855,7 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoPoint {
|
|||
type Output = RistrettoPoint;
|
||||
/// Scalar multiplication: compute `scalar * self`.
|
||||
fn mul(self, scalar: &'b Scalar) -> RistrettoPoint {
|
||||
RistrettoPoint(&self.0 * scalar)
|
||||
RistrettoPoint(self.0 * scalar)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -856,7 +864,7 @@ impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar {
|
|||
|
||||
/// Scalar multiplication: compute `self * scalar`.
|
||||
fn mul(self, point: &'b RistrettoPoint) -> RistrettoPoint {
|
||||
RistrettoPoint(self * &point.0)
|
||||
RistrettoPoint(self * point.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -902,7 +910,7 @@ impl VartimeMultiscalarMul for RistrettoPoint {
|
|||
{
|
||||
let extended_points = points.into_iter().map(|opt_P| opt_P.map(|P| P.borrow().0));
|
||||
|
||||
EdwardsPoint::optional_multiscalar_mul(scalars, extended_points).map(|P| RistrettoPoint(P))
|
||||
EdwardsPoint::optional_multiscalar_mul(scalars, extended_points).map(RistrettoPoint)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -948,14 +956,13 @@ impl VartimePrecomputedMultiscalarMul for VartimeRistrettoPrecomputation {
|
|||
dynamic_scalars,
|
||||
dynamic_points.into_iter().map(|P_opt| P_opt.map(|P| P.0)),
|
||||
)
|
||||
.map(|P_ed| RistrettoPoint(P_ed))
|
||||
.map(RistrettoPoint)
|
||||
}
|
||||
}
|
||||
|
||||
impl RistrettoPoint {
|
||||
/// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the
|
||||
/// Ristretto basepoint.
|
||||
#[cfg(feature = "stage2_build")]
|
||||
pub fn vartime_double_scalar_mul_basepoint(
|
||||
a: &Scalar,
|
||||
A: &RistrettoPoint,
|
||||
|
|
@ -1073,7 +1080,7 @@ impl Debug for RistrettoPoint {
|
|||
// Tests
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
#[cfg(all(test, feature = "stage2_build"))]
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[cfg(feature = "rand")]
|
||||
use rand_os::OsRng;
|
||||
|
|
@ -1081,7 +1088,7 @@ mod test {
|
|||
use scalar::Scalar;
|
||||
use constants;
|
||||
use edwards::CompressedEdwardsY;
|
||||
use traits::{Identity, ValidityCheck};
|
||||
use traits::{Identity};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
|
@ -1093,11 +1100,19 @@ mod test {
|
|||
let enc_compressed = bincode::serialize(&constants::RISTRETTO_BASEPOINT_COMPRESSED).unwrap();
|
||||
assert_eq!(encoded, enc_compressed);
|
||||
|
||||
// Check that the encoding is 32 bytes exactly
|
||||
assert_eq!(encoded.len(), 32);
|
||||
|
||||
let dec_uncompressed: RistrettoPoint = bincode::deserialize(&encoded).unwrap();
|
||||
let dec_compressed: CompressedRistretto = bincode::deserialize(&encoded).unwrap();
|
||||
|
||||
assert_eq!(dec_uncompressed, constants::RISTRETTO_BASEPOINT_POINT);
|
||||
assert_eq!(dec_compressed, constants::RISTRETTO_BASEPOINT_COMPRESSED);
|
||||
|
||||
// Check that the encoding itself matches the usual one
|
||||
let raw_bytes = constants::RISTRETTO_BASEPOINT_COMPRESSED.as_bytes();
|
||||
let bp: RistrettoPoint = bincode::deserialize(raw_bytes).unwrap();
|
||||
assert_eq!(bp, constants::RISTRETTO_BASEPOINT_POINT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1136,7 +1151,7 @@ mod test {
|
|||
|
||||
// Test that sum works on owning iterators
|
||||
let s = Scalar::from(2u64);
|
||||
let mapped = vec.iter().map(|x| x * &s);
|
||||
let mapped = vec.iter().map(|x| x * s);
|
||||
let sum: RistrettoPoint = mapped.sum();
|
||||
|
||||
assert_eq!(sum, &P1 * &s + &P2 * &s);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// Portions Copyright 2017 Brian Smith
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
|
|
@ -202,7 +202,7 @@ impl Scalar {
|
|||
/// modulo the group order \\( \ell \\).
|
||||
pub fn from_bytes_mod_order(bytes: [u8; 32]) -> Scalar {
|
||||
// Temporarily allow s_unreduced.bytes > 2^255 ...
|
||||
let s_unreduced = Scalar{bytes: bytes};
|
||||
let s_unreduced = Scalar{bytes};
|
||||
|
||||
// Then reduce mod the group order and return the reduced representative.
|
||||
let s = s_unreduced.reduce();
|
||||
|
|
@ -242,7 +242,7 @@ impl Scalar {
|
|||
/// require specific bit-patterns when performing scalar
|
||||
/// multiplication.
|
||||
pub fn from_bits(bytes: [u8; 32]) -> Scalar {
|
||||
let mut s = Scalar{bytes: bytes};
|
||||
let mut s = Scalar{bytes};
|
||||
// Ensure that s < 2^255 by masking the high bit
|
||||
s.bytes[31] &= 0b0111_1111;
|
||||
|
||||
|
|
@ -354,7 +354,7 @@ impl<'a> Neg for &'a Scalar {
|
|||
fn neg(self) -> Scalar {
|
||||
let self_R = UnpackedScalar::mul_internal(&self.unpack(), &constants::R);
|
||||
let self_mod_l = UnpackedScalar::montgomery_reduce(&self_R);
|
||||
UnpackedScalar::sub(&UnpackedScalar::zero(), &self_mod_l).pack()
|
||||
UnpackedScalar::sub(&UnpackedScalar::zero(), &self_mod_l).pack()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +385,12 @@ impl Serialize for Scalar {
|
|||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
serializer.serialize_bytes(self.reduce().as_bytes())
|
||||
use serde::ser::SerializeTuple;
|
||||
let mut tup = serializer.serialize_tuple(32)?;
|
||||
for byte in self.as_bytes().iter() {
|
||||
tup.serialize_element(byte)?;
|
||||
}
|
||||
tup.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -400,32 +405,25 @@ impl<'de> Deserialize<'de> for Scalar {
|
|||
type Value = Scalar;
|
||||
|
||||
fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||
formatter.write_str("a canonically-encoded 32-byte scalar value")
|
||||
formatter.write_str("a valid point in Edwards y + sign format")
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Scalar, E>
|
||||
where E: serde::de::Error
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Scalar, A::Error>
|
||||
where A: serde::de::SeqAccess<'de>
|
||||
{
|
||||
if v.len() == 32 {
|
||||
let mut bytes = [0u8;32];
|
||||
bytes.copy_from_slice(v);
|
||||
|
||||
static ERRMSG: &'static str = "encoding was not canonical";
|
||||
|
||||
Scalar::from_canonical_bytes(bytes)
|
||||
.ok_or(
|
||||
serde::de::Error::invalid_value(
|
||||
serde::de::Unexpected::Bytes(v),
|
||||
&ERRMSG,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(v.len(), &self))
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = seq.next_element()?
|
||||
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
|
||||
}
|
||||
Scalar::from_canonical_bytes(bytes)
|
||||
.ok_or(serde::de::Error::custom(
|
||||
&"scalar was not canonically encoded"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_bytes(ScalarVisitor)
|
||||
deserializer.deserialize_tuple(32, ScalarVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -760,18 +758,15 @@ impl Scalar {
|
|||
// externally, but there's no corresponding distinction for
|
||||
// field elements.
|
||||
|
||||
use clear_on_drop::ClearOnDrop;
|
||||
use clear_on_drop::clear::ZeroSafe;
|
||||
// Mark UnpackedScalars as zeroable.
|
||||
unsafe impl ZeroSafe for UnpackedScalar {}
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
let n = inputs.len();
|
||||
let one: UnpackedScalar = Scalar::one().unpack().to_montgomery();
|
||||
|
||||
// Wrap the scratch storage in a ClearOnDrop to wipe it when
|
||||
// Place scratch storage in a Zeroizing wrapper to wipe it when
|
||||
// we pass out of scope.
|
||||
let scratch_vec = vec![one; n];
|
||||
let mut scratch = ClearOnDrop::new(scratch_vec);
|
||||
let mut scratch = Zeroizing::new(scratch_vec);
|
||||
|
||||
// Keep an accumulator of all of the previous products
|
||||
let mut acc = Scalar::one().unpack().to_montgomery();
|
||||
|
|
@ -799,7 +794,7 @@ impl Scalar {
|
|||
|
||||
// Pass through the vector backwards to compute the inverses
|
||||
// in place
|
||||
for (input, scratch) in inputs.iter_mut().rev().zip(scratch.into_iter().rev()) {
|
||||
for (input, scratch) in inputs.iter_mut().rev().zip(scratch.iter().rev()) {
|
||||
let tmp = UnpackedScalar::montgomery_mul(&acc, &input.unpack());
|
||||
*input = UnpackedScalar::montgomery_mul(&acc, &scratch).pack();
|
||||
acc = tmp;
|
||||
|
|
@ -1649,9 +1644,18 @@ mod test {
|
|||
#[cfg(feature = "serde")]
|
||||
fn serde_bincode_scalar_roundtrip() {
|
||||
use bincode;
|
||||
let output = bincode::serialize(&X).unwrap();
|
||||
let parsed: Scalar = bincode::deserialize(&output).unwrap();
|
||||
let encoded = bincode::serialize(&X).unwrap();
|
||||
let parsed: Scalar = bincode::deserialize(&encoded).unwrap();
|
||||
assert_eq!(parsed, X);
|
||||
|
||||
// Check that the encoding is 32 bytes exactly
|
||||
assert_eq!(encoded.len(), 32);
|
||||
|
||||
// Check that the encoding itself matches the usual one
|
||||
assert_eq!(
|
||||
X,
|
||||
bincode::deserialize(X.as_bytes()).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// -*- mode: rust; -*-
|
||||
//
|
||||
// This file is part of curve25519-dalek.
|
||||
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
|
||||
// Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
|
||||
// See LICENSE for licensing information.
|
||||
//
|
||||
// Authors:
|
||||
|
|
@ -25,6 +25,8 @@ use edwards::EdwardsPoint;
|
|||
use backend::serial::curve_models::ProjectiveNielsPoint;
|
||||
use backend::serial::curve_models::AffineNielsPoint;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// A lookup table of precomputed multiples of a point \\(P\\), used to
|
||||
/// compute \\( xP \\) for \\( -8 \leq x \leq 8 \\).
|
||||
///
|
||||
|
|
@ -40,23 +42,6 @@ use backend::serial::curve_models::AffineNielsPoint;
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct LookupTable<T>(pub(crate) [T; 8]);
|
||||
|
||||
use clear_on_drop::clear::ZeroSafe;
|
||||
|
||||
/// This type isn't actually zeroable (all zero bytes are not valid
|
||||
/// points), but we want to be able to use `clear_on_drop` to erase slices
|
||||
/// of `LookupTable`.
|
||||
///
|
||||
/// Since the `ZeroSafe` trait is only used by `clear_on_drop`, the only
|
||||
/// situation where this would be a problem is if code attempted to use
|
||||
/// a `ClearOnDrop` to erase a `LookupTable` and then used the table
|
||||
/// afterwards.
|
||||
///
|
||||
/// Normally this is not a problem, since the table's storage is usually
|
||||
/// dropped too.
|
||||
///
|
||||
/// XXX is this a good compromise?
|
||||
unsafe impl<T> ZeroSafe for LookupTable<T> {}
|
||||
|
||||
impl<T> LookupTable<T>
|
||||
where
|
||||
T: Identity + ConditionallySelectable + ConditionallyNegatable,
|
||||
|
|
@ -120,6 +105,15 @@ impl<'a> From<&'a EdwardsPoint> for LookupTable<AffineNielsPoint> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Zeroize for LookupTable<T>
|
||||
where
|
||||
T: Copy + Default + Zeroize
|
||||
{
|
||||
fn zeroize(&mut self) {
|
||||
self.0.zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds odd multiples 1A, 3A, ..., 15A of a point A.
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct NafLookupTable5<T>(pub(crate) [T; 8]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue