From 13c615832cc343a55266ef8224452e82bd837fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 2 Oct 2020 04:09:49 +0300 Subject: [PATCH 01/20] add weierstrass crate --- Cargo.lock | 16 + Cargo.toml | 1 + weierstrass/Cargo.toml | 12 + weierstrass/src/affine.rs | 173 ++++++++++ weierstrass/src/field.rs | 425 ++++++++++++++++++++++++ weierstrass/src/gost_test256.rs | 48 +++ weierstrass/src/lib.rs | 83 +++++ weierstrass/src/main.rs | 117 +++++++ weierstrass/src/projective.rs | 561 ++++++++++++++++++++++++++++++++ weierstrass/src/scalar.rs | 525 ++++++++++++++++++++++++++++++ weierstrass/src/utils.rs | 26 ++ 11 files changed, 1987 insertions(+) create mode 100644 weierstrass/Cargo.toml create mode 100644 weierstrass/src/affine.rs create mode 100644 weierstrass/src/field.rs create mode 100644 weierstrass/src/gost_test256.rs create mode 100644 weierstrass/src/lib.rs create mode 100644 weierstrass/src/main.rs create mode 100644 weierstrass/src/projective.rs create mode 100644 weierstrass/src/scalar.rs create mode 100644 weierstrass/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 06c037800..24e246642 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,11 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "biguint-literal" +version = "0.1.0" +source = "git+https://github.com/RustCrypto/utils?branch=biguint#f7b73ea9042a8f34728e92bb369cfcf9278b4979" + [[package]] name = "bit-set" version = "0.5.2" @@ -1017,6 +1022,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weierstrass" +version = "0.1.0" +dependencies = [ + "biguint-literal", + "generic-array", + "hex-literal", + "rand_core", + "subtle", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index e68cd2da6..e78afda2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,5 @@ members = [ "k256", "p256", "p384", + "weierstrass", ] diff --git a/weierstrass/Cargo.toml b/weierstrass/Cargo.toml new file mode 100644 index 000000000..37d737274 --- /dev/null +++ b/weierstrass/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "weierstrass" +version = "0.1.0" +authors = ["RustCrypto Developers"] +edition = "2018" + +[dependencies] +generic-array = "0.14" +subtle = "2" +rand_core = "0.5" +biguint-literal = { git = "https://github.com/RustCrypto/utils", branch = "biguint" } +hex-literal = "0.3" diff --git a/weierstrass/src/affine.rs b/weierstrass/src/affine.rs new file mode 100644 index 000000000..2533f76af --- /dev/null +++ b/weierstrass/src/affine.rs @@ -0,0 +1,173 @@ +use core::ops::{Mul, Neg}; +use generic_array::{ArrayLength, typenum::U1}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; +use core::ops::Add; + +use crate::{ + WeirstrassCurve, Word, + Words, WordsLen, + WideWordsLen, + WordsBytesLen, + WordsP1Len, +}; +use crate::scalar::Scalar; +use crate::projective::ProjectivePoint; +use crate::field::FieldElement; + +#[derive(Clone, Copy)] +pub struct AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + pub x: FieldElement, + pub y: FieldElement, + pub infinity: Choice, +} + +impl AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + /// Returns the base point + pub fn generator() -> Self { + Self { + x: C::GENERATOR_X, + y: C::GENERATOR_Y, + infinity: Choice::from(0), + } + } + + /// Returns the identity of the group: the point at infinity. + pub fn identity() -> Self { + Self { + x: FieldElement::zero(), + y: FieldElement::zero(), + infinity: Choice::from(1), + } + } + + /// Is this point the identity point? + pub fn is_identity(&self) -> Choice { + self.infinity + } +} + +impl ConditionallySelectable for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + AffinePoint { + x: FieldElement::conditional_select(&a.x, &b.x, choice), + y: FieldElement::conditional_select(&a.y, &b.y, choice), + infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice), + } + } +} + +impl ConstantTimeEq for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn ct_eq(&self, other: &Self) -> Choice { + self.x.ct_eq(&other.x) + & self.y.ct_eq(&other.y) + & self.infinity.ct_eq(&other.infinity) + } +} + +impl PartialEq for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() + } +} + +impl Eq for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{} + +impl Mul> for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn mul(self, scalar: Scalar) -> Self { + (ProjectivePoint::from(self) * scalar).to_affine() + } +} + +impl Neg for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn neg(self) -> Self::Output { + AffinePoint { + x: self.x, + y: -self.y, + infinity: self.infinity, + } + } +} + +#[cfg(feature = "zeroize")] +impl Zeroize for AffinePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn zeroize(&mut self) { + self.x.zeroize(); + self.y.zeroize(); + } +} diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs new file mode 100644 index 000000000..bc794db6d --- /dev/null +++ b/weierstrass/src/field.rs @@ -0,0 +1,425 @@ +use core::{fmt, mem}; +use core::convert::TryInto; +use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg}; +use generic_array::ArrayLength; +use generic_array::typenum::{U1, Unsigned}; +use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; +use rand_core::{RngCore, CryptoRng}; + +use crate::{ + WeirstrassCurve, Word, WordWidth, + Words, WordsLen, + WideWords, WideWordsLen, + WordsBytes, WordsBytesLen, + WordsP1, WordsP1Len, + random_word +}; +use crate::utils::{adc, sbb, mac}; + +#[derive(Default, Debug, Copy, Clone)] +pub struct FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + pub words: Words, +} + +impl FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + + pub fn zero() -> Self { + Self { + words: Default::default(), + } + } + + /// Returns the multiplicative identity. + pub fn one() -> Self { + C::R + } + + /// Returns a uniformly-random element within the field. + pub fn generate(mut rng: impl CryptoRng + RngCore) -> Self { + // We reduce a random value with a double length, which results in a + // negligible bias from the uniform distribution. + let mut t = WideWords::::default(); + t.iter_mut().for_each(|wt| *wt = random_word(&mut rng)); + FieldElement::montgomery_reduce(t) + } + + /// Attempts to parse the given byte array as an SEC1-encoded field element. + /// + /// Returns None if the byte array does not contain a big-endian integer in the range + /// [0, p). + pub fn from_bytes(bytes: &WordsBytes) -> CtOption { + let mut words = Words::::default(); + let m = mem::size_of::(); + let iter = words.iter_mut().zip(bytes.chunks_exact(m).rev()); + for (w, chunk) in iter { + *w = Word::from_be_bytes(chunk.try_into().unwrap()); + } + + let mut borrow = Word::default(); + for (&w, &wm) in words.iter().zip(C::MODULUS_P.iter()) { + borrow = sbb(w, wm, borrow).1; + } + let is_some = (borrow as u8) & 1; + + // Convert w to Montgomery form: w * R^2 * R^-1 mod p = wR mod p + CtOption::new(Self { words }.mul(C::R2), Choice::from(is_some)) + } + + /// Returns the SEC1 encoding of this field element. + pub fn to_bytes(&self) -> WordsBytes { + // Convert from Montgomery form to canonical form + let mut w = WideWords::::default(); + let n = self.words.len(); + w[..n].copy_from_slice(&self.words); + let t = Self::montgomery_reduce(w); + + let m = mem::size_of::(); + let mut buf = WordsBytes::::default(); + let iter = buf.chunks_exact_mut(m).rev().zip(t.words.iter()); + for (chunk, wt) in iter { + chunk.copy_from_slice(&wt.to_be_bytes()); + } + buf + } + + /// Determine if this `FieldElement` is zero. + pub fn is_zero(&self) -> Choice { + self.ct_eq(&FieldElement::zero()) + } + + /// Returns self + rhs mod p + pub fn add(&self, rhs: &Self) -> Self { + // Last bit of p is usually set, so addition can result in five words. + let mut t: WordsP1 = Default::default(); + let mut carry = Word::default(); + let pairs = self.words.iter().zip(rhs.words.iter()); + for (wt, (&wb, &wa)) in t.iter_mut().zip(pairs) { + let t = adc(wa, wb, carry); + *wt = t.0; + carry = t.1; + } + *t.last_mut().unwrap() = carry; + // Attempt to subtract the MODULUS_P, to ensure the result is in the field. + Self::sub_inner(t, Self { words: C::MODULUS_P }) + } + + /// Returns 2*self. + pub fn double(&self) -> Self { + self.add(self) + } + + /// Returns self - rhs mod p + pub fn subtract(&self, rhs: &Self) -> Self { + let mut t: WordsP1 = Default::default(); + let n = self.words.len(); + t[..n].copy_from_slice(&self.words); + Self::sub_inner(t, *rhs) + } + + fn sub_inner(a: WordsP1, mut b: Self) -> Self { + let mut borrow = Word::default(); + for (wb, wa) in b.words.iter_mut().zip(a.iter()) { + let t = sbb(*wa, *wb, borrow); + *wb = t.0; + borrow = t.1; + } + let (_, borrow) = sbb(a[a.len() - 1], 0, borrow); + + // If underflow occurred on the final word, borrow = 0xfff...fff, otherwise + // borrow = 0x000...000. Thus, we use it as a mask to conditionally add the + // MODULUS_P. + let mut carry = Word::default(); + for (wb, &wm) in b.words.iter_mut().zip(C::MODULUS_P.iter()) { + let t = adc(*wb, wm & borrow, carry); + *wb = t.0; + carry = t.1; + } + b + } + + /// Montgomery Reduction + fn montgomery_reduce(v: WideWords) -> Self { + // `WideWords` length is always multiple of 2 + let n = v.len() / 2; + let mut r = WordsP1::::default(); + r[..n].copy_from_slice(&v[..n]); + for i in 0..n { + let u = r[0].wrapping_mul(C::PT); + let (_, mut carry) = mac(r[0], u, C::MODULUS_P[0], 0); + for j in 1..n { + let t = mac(r[j], u, C::MODULUS_P[j], carry); + r[j - 1] = t.0; + carry = t.1; + } + let t = adc(v[i + n], r[n], carry); + r[n - 1] = t.0; + r[n] = t.1; + } + Self::sub_inner(r, Self { words: C::MODULUS_P }) + } + + /// Returns self * rhs mod p + pub fn mul(&self, rhs: &Self) -> Self { + let mut w = WideWords::::default(); + let n = rhs.words.len(); + + // Schoolbook multiplication. + for i in 0..n { + let mut carry = Word::default(); + for j in 0..n { + let t = mac(w[i + j], self.words[i], rhs.words[j], carry); + w[i + j] = t.0; + carry = t.1; + } + w[i + n] = carry; + } + + Self::montgomery_reduce(w) + } + + /// Returns self * self mod p + pub fn square(&self) -> Self { + self.mul(self) + } + + /// Returns `self^by mod p`, where `by` is a little-endian integer exponent. + /// + /// **This operation is variable time with respect to the exponent.** + /// If the exponent is fixed, this operation is effectively constant time. + pub fn pow_vartime(&self, by: &Words) -> Self { + let mut res = Self::one(); + for e in by.iter().rev() { + for i in (0..WordWidth::USIZE).rev() { + res = res.square(); + if ((*e >> i) & 1) == 1 { + res = res.mul(*self); + } + } + } + res + } + + /// Returns the multiplicative inverse of self, if self is non-zero. + pub fn invert(&self) -> CtOption { + // We need to find b such that b * a ≡ 1 mod p. As we are in a prime + // field, we can apply Fermat's Little Theorem: + // + // a^p ≡ a mod p + // a^(p-1) ≡ 1 mod p + // a^(p-2) * a ≡ 1 mod p + // + // Thus inversion can be implemented with a single exponentiation. + let inverse = self.pow_vartime(&C::MODULUS_P_M2); + CtOption::new(inverse, !self.is_zero()) + } + + /// Returns the square root of self mod p, or `None` if no square root exists. + pub fn sqrt(&self) -> CtOption { + todo!(); + } +} + +impl fmt::UpperHex for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for word in self.words.iter().rev() { + write!(f, "{:016X}", word)?; + } + Ok(()) + } +} + +impl ConditionallySelectable for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let mut res = Self::zero(); + let pairs = a.words.iter().zip(b.words.iter()); + for (vr, (va, vb)) in res.words.iter_mut().zip(pairs) { + *vr = Word::conditional_select(va, vb, choice); + } + res + } +} + +impl ConstantTimeEq for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn ct_eq(&self, other: &Self) -> Choice { + let mut res = 1u8.into(); + for (a, b) in self.words.iter().zip(other.words.iter()) { + res &= a.ct_eq(b); + } + res + } +} + +impl PartialEq for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() + } +} + +impl Add> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn add(self, other: Self) -> Self { + FieldElement::add(&self, &other) + } +} + +impl AddAssign> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn add_assign(&mut self, other: Self) { + *self = FieldElement::add(self, &other); + } +} + +impl Sub> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn sub(self, other: Self) -> Self { + FieldElement::subtract(&self, &other) + } +} + +impl SubAssign> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn sub_assign(&mut self, other: Self) { + *self = FieldElement::subtract(self, &other); + } +} + + +impl Mul> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn mul(self, other: Self) -> Self { + FieldElement::mul(&self, &other) + } +} + +impl MulAssign> for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn mul_assign(&mut self, other: Self) { + *self = FieldElement::mul(self, &other); + } +} + +impl Neg for FieldElement + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn neg(self) -> Self { + FieldElement::zero() - self + } +} + +#[cfg(feature = "zeroize")] +impl Zeroize for FieldElement { + fn zeroize(&mut self) { + self.words.zeroize(); + } +} diff --git a/weierstrass/src/gost_test256.rs b/weierstrass/src/gost_test256.rs new file mode 100644 index 000000000..5a74de7cf --- /dev/null +++ b/weierstrass/src/gost_test256.rs @@ -0,0 +1,48 @@ +use generic_array::typenum::U256; +use crate::{WeirstrassCurve, Word, Words, WordsP1}; +use crate::field::FieldElement; +use biguint_literal::hex_biguint; + +#[derive(Copy, Default, Debug, Clone)] +pub struct GostTest256; + +impl WeirstrassCurve for GostTest256 { + type Bits = U256; + + const A: FieldElement = FieldElement { words: hex_biguint!(" + 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC983 + ") }; + const B: FieldElement = FieldElement { words: hex_biguint!(" + 58DF983A171CD5AE20391ABE272C66AD004469B4541A2542807BBFA323A3952A + ") }; + const MODULUS_P: Words = hex_biguint!(" + 8000000000000000000000000000000000000000000000000000000000000431 + "); + const MODULUS_P_M2: Words = hex_biguint!(" + 800000000000000000000000000000000000000000000000000000000000042f + "); + const MODULUS_Q: Words = hex_biguint!(" + 8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3 + "); + const MODULUS_Q_M2: Words = hex_biguint!(" + 8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B1 + "); + const GENERATOR_X: FieldElement = FieldElement { words: hex_biguint!(" + 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36D + ") }; + const GENERATOR_Y: FieldElement = FieldElement { words: hex_biguint!(" + 03F66B354AA3DAA467617A63E4B6DDE67CE5090AF69BF9AE9AF45A5A471125F5 + ") }; + const R: FieldElement = FieldElement { words: hex_biguint!(" + 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBCF + ") }; + const R2: FieldElement = FieldElement { words: hex_biguint!(" + 0000000000000000000000000000000000000000000000000000000000464584 + ") }; + const MU: WordsP1 = hex_biguint!(" + 0000000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFABC05D79DB5A27AACE98C0F9B14CC2941 + "); + + #[cfg(target_pointer_width = "64")] + const PT: Word = 0xdbf9_51d5_883b_2b2f; +} \ No newline at end of file diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs new file mode 100644 index 000000000..dc3a71383 --- /dev/null +++ b/weierstrass/src/lib.rs @@ -0,0 +1,83 @@ +use generic_array::{ArrayLength, GenericArray}; +use generic_array::typenum::{ + self, + U1, U4, U8, + Unsigned, + operator_aliases::{Sum, Quot}, +}; +use rand_core::{RngCore, CryptoRng}; +use core::ops::{Div, Add}; + +mod affine; +mod field; +mod scalar; +mod projective; +mod utils; + +mod gost_test256; + +pub use affine::AffinePoint; +pub use field::FieldElement; +pub use scalar::Scalar; +pub use projective::ProjectivePoint; +pub use gost_test256::GostTest256; + +// TODO: add cfgs for other word sizes +type Word = u64; +type DoubleWord = u128; +type WordWidth = typenum::U64; +/// Divisor for getting number of words in the wider buffer, it's equal +/// to `Quot`, but to simplify trait bounds we use an explicit +/// value +type WideWordsDiv = typenum::U32; +fn random_word(mut rng: impl CryptoRng + RngCore) -> Word { + rng.next_u64() +} + +type WordsLen = Quot<::Bits, WordWidth>; +type Words = GenericArray>; +type WordsBytesLen = Quot<::Bits, U8>; +type WordsBytes = GenericArray>; + +type WordsP1Len = Sum, U1>; +type WordsP1 = GenericArray>; + +type WideWordsLen = Quot<::Bits, WideWordsDiv>; +type WideWords = GenericArray>; + +pub trait WeirstrassCurve + where + Self: Sized + Copy + Default, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Bits: Unsigned + Div + Div + Div + Div; + + const A: FieldElement; + const B: FieldElement; + const MODULUS_P: Words; + /// p - 2 + const MODULUS_P_M2: Words; + const MODULUS_Q: Words; + /// q - 2 + const MODULUS_Q_M2: Words; + + // we can't define GENERATOR, bacause `Choice` does not + // support const construction + const GENERATOR_X: FieldElement; + const GENERATOR_Y: FieldElement; + /// R = 2^Bits mod p + const R: FieldElement; + /// R2 = 2^(2*Bits) mod p + const R2: FieldElement; + + /// P*PT (mod 2^WORD_WIDTH) == -1 + const PT: Word; + + /// MU = floor(2^512 / n) + const MU: WordsP1; +} + diff --git a/weierstrass/src/main.rs b/weierstrass/src/main.rs new file mode 100644 index 000000000..6f9a6dea5 --- /dev/null +++ b/weierstrass/src/main.rs @@ -0,0 +1,117 @@ +use weierstrass; +use hex_literal::hex; +use generic_array::GenericArray; + +use weierstrass::{GostTest256, AffinePoint, FieldElement}; + +type Scalar = weierstrass::Scalar; +type ProjectivePoint = weierstrass::ProjectivePoint; + +fn main() { + let _p: [u8; 32] = hex!(" + 8000000000000000000000000000000000000000000000000000000000000431 + "); + let e = hex!(" + 2DFBC1B372D89A1188C09C52E0EEC61FCE52032AB1022E8E67ECE6672B043EE5 + "); + let d = hex!(" + 7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28 + "); + let k = hex!(" + 77105C9B20BCD3122823C8CF6FCC7B956DE33814E95B7FE64FED924594DCEAB3 + "); + + let k = Scalar::from_bytes_reduced(GenericArray::from_slice(&k)); + let d = Scalar::from_bytes_reduced(GenericArray::from_slice(&d)); + let e = Scalar::from_bytes_reduced(GenericArray::from_slice(&e)); + + println!("k {:X}", k); + + let p = ProjectivePoint::generator(); + + println!("x before {:X}", &p.x); + println!("y before {:X}", &p.y); + println!("z before {:X}", &p.z); + + let p = p * k; + + println!("x raw {:X}", &p.x); + println!("y raw {:X}", &p.y); + println!("z raw {:X}", &p.z); + + let p = p.to_affine(); + + println!("x raw2 {:X}", &p.x); + println!("y raw2 {:X}", &p.y); + + print_hex("x ", &p.x.to_bytes()); + print_hex("y ", &p.y.to_bytes()); + + let r = Scalar::from_bytes_reduced(&p.x.to_bytes()); + + println!("r {:X}", r); + + let rd = r*d; + println!("rd {:X}", rd); + let ke = k*e; + println!("ke {:X}", ke); + + let calc_s = rd + ke; + + println!("calc s {:X}", calc_s); + + + + println!("verification"); + + let r = hex!(" + 41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493 + "); + let s = hex!(" + 01456C64BA4642A1653C235A98A60249BCD6D3F746B631DF928014F6C5BF9C40 + "); + let xq = hex!(" + 7F2B49E270DB6D90D8595BEC458B50C58585BA1D4E9B788F6689DBD8E56FD80B + "); + let yq = hex!(" + 26F1B489D6701DD185C8413A977B3CBBAF64D1C593D26627DFFB101A87FF77DA + "); + + let r = Scalar::from_repr(*GenericArray::from_slice(&r)).unwrap(); + let s = Scalar::from_repr(*GenericArray::from_slice(&s)).unwrap(); + + println!("r {:X}", r); + println!("s {:X}", s); + + let v = e.invert().unwrap(); + println!("v {:X}", v); + + let z1 = s*v; + let z2 = -r*v; + println!("z1 {:X}", z1); + println!("z2 {:X}", z2); + + let q = AffinePoint { + x: FieldElement::from_bytes(GenericArray::from_slice(&xq)).unwrap(), + y: FieldElement::from_bytes(GenericArray::from_slice(&yq)).unwrap(), + infinity: subtle::Choice::from(0), + }; + + let c = ProjectivePoint::generator()*z1 + ProjectivePoint::from(q)*z2; + let c = c.to_affine(); + + print_hex("xc ", &c.x.to_bytes()); + print_hex("yc ", &c.y.to_bytes()); + + let r = Scalar::from_bytes_reduced(&c.x.to_bytes()); + println!("r: {:X}", r); +} + + +fn print_hex(s: &str, buf: &[u8]) { + print!("{}", s); + for b in buf { + print!("{:02X}", b); + } + println!(); +} diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs new file mode 100644 index 000000000..a694c6cac --- /dev/null +++ b/weierstrass/src/projective.rs @@ -0,0 +1,561 @@ +use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use core::iter::Sum; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; +use generic_array::{ArrayLength, typenum::{U1, Unsigned}}; + +use crate::{ + WeirstrassCurve, Word, WordWidth, + Words, WordsLen, + WideWordsLen, + WordsBytesLen, + WordsP1Len, +}; +use crate::field::FieldElement; +use crate::affine::AffinePoint; +use crate::scalar::Scalar; + + +#[derive(Clone, Copy, Debug)] +pub struct ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + pub x: FieldElement, + pub y: FieldElement, + pub z: FieldElement, +} + +impl From> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn from(p: AffinePoint) -> Self { + let projective = ProjectivePoint { + x: p.x, + y: p.y, + z: FieldElement::one(), + }; + Self::conditional_select(&projective, &Self::identity(), p.infinity) + } +} + +impl ConditionallySelectable for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + ProjectivePoint { + 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), + } + } +} + +impl ConstantTimeEq for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn ct_eq(&self, other: &Self) -> Choice { + self.to_affine().ct_eq(&other.to_affine()) + } +} + +impl PartialEq for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() + } +} + +impl Eq for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{} + +impl ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + /// Returns the additive identity of P-256, also known as the "neutral element" or + /// "point at infinity". + pub fn identity() -> Self { + Self { + x: FieldElement::zero(), + y: FieldElement::one(), + z: FieldElement::zero(), + } + } + + /// Returns the base point of P-256. + pub fn generator() -> Self { + AffinePoint::generator().into() + } + + /// Returns the affine representation of this point, or `None` if it is the identity. + pub fn to_affine(&self) -> AffinePoint { + self.z + .invert() + .map(|zinv| AffinePoint { + x: self.x * zinv, + y: self.y * zinv, + infinity: Choice::from(0), + }) + .unwrap_or_else(AffinePoint::identity) + } + + /// Returns `-self`. + fn neg(&self) -> Self { + ProjectivePoint { + x: self.x, + y: self.y.neg(), + z: self.z, + } + } + + /// Returns `self + other`. + fn add(&self, other: &Self) -> Self { + // We implement the complete addition formula from Renes-Costello-Batina 2015 + // (https://eprint.iacr.org/2015/1060 Algorithm 1). The comments after each line + // indicate which algorithm steps are being performed. + let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; + let &ProjectivePoint { x: x2, y: y2, z: z2 } = other; + + let b3 = C::B + C::B + C::B; + let a1 = C::A; + + let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); + let (mut x3, mut y3, mut z3); + + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 + + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 + + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = x1 + z1; // 9 + + t5 = x2 + z2; // 10 + t4 = t4 * t5; // 11 + t5 = t0 + t2; // 12 + + t4 = t4 - t5; // 13 + t5 = y1 + z1; // 14 + x3 = y2 + z2; // 15 + + t5 = t5 * x3; // 16 + x3 = t1 + t2; // 17 + t5 = t5 - x3; // 18 + + z3 = a1 * t4; // 19 + x3 = b3 * t2; // 20 + z3 = x3 + z3; // 21 + + x3 = t1 - z3; // 22 + z3 = t1 + z3; // 23 + y3 = x3 * z3; // 24 + + t1 = t0 + t0; // 25 + t1 = t1 + t0; // 26 + t2 = a1 * t2; // 27 + + t4 = b3 * t4; // 28 + t1 = t1 + t2; // 29 + t2 = t0 - t2; // 30 + + t2 = a1 * t2; // 31 + t4 = t4 + t2; // 32 + t0 = t1 * t4; // 33 + + y3 = y3 + t0; // 34 + t0 = t5 * t4; // 35 + x3 = t3 * x3; // 36 + + x3 = x3 - t0; // 37 + t0 = t3 * t1; // 38 + z3 = t5 * z3; // 39 + + z3 = z3 + t0; // 40 + + ProjectivePoint { x: x3, y: y3, z: z3 } + } + + /// Returns `self + other`. + fn add_mixed(&self, other: &AffinePoint) -> Self { + // We implement the complete mixed addition formula from Renes-Costello-Batina + // 2015 (Algorithm 2). The comments after each line indicate which algorithm steps + // are being performed. + let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; + let &AffinePoint { x: x2, y: y2, .. } = other; + + let b3 = C::B + C::B + C::B; + let a1 = C::A; + + let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); + let (mut x3, mut y3, mut z3); + + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = x2 * z1; // 8 + t4 = t4 + x1; // 9 + + t5 = y2 * z1; // 10 + t5 = t5 + y1; // 11 + z3 = a1 * t4; // 12 + + x3 = b3 * z1; // 13 + z3 = x3 + z3; // 14 + x3 = t1 - z3; // 15 + + z3 = t1 + z3; // 16 + y3 = x3 * z3; // 17 + t1 = t0 + t0; // 18 + + t1 = t1 + t0; // 19 + t2 = a1 * z1; // 20 + t4 = b3 * t4; // 21 + + t1 = t1 + t2; // 22 + t2 = t0 - t2; // 23 + t2 = a1 * t2; // 24 + + t4 = t4 + t2; // 25 + t0 = t1 * t4; // 26 + y3 = y3 + t0; // 27 + + t0 = t5 * t4; // 28 + x3 = t3 * x3; // 29 + x3 = x3 - t0; // 30 + + t0 = t3 * t1; // 31 + z3 = t5 * z3; // 32 + z3 = z3 + t0; // 33 + + ProjectivePoint { x: x3, y: y3, z: z3 } + } + + /// Doubles this point. + pub fn double(&self) -> Self { + // We implement the complete doubling formula from Renes-Costello-Batina 2015 + // (https://eprint.iacr.org/2015/1060 Algorithm 3). The comments after each line + // indicate which algorithm steps are being performed. + let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; + + let b3 = C::B + C::B + C::B; + let a1 = C::A; + + let (mut t0, t1, mut t2, mut t3); + let (mut x3, mut y3, mut z3); + + t0 = x1 * x1; // 1 + t1 = y1 * y1; // 2 + t2 = z1 * z1; // 3 + + t3 = x1 * y1; // 4 + t3 = t3 + t3; // 5 + z3 = x1 * z1; // 6 + + z3 = z3 + z3; // 7 + x3 = a1 * z3; // 8 + y3 = b3 * t2; // 9 + + y3 = x3 + y3; // 10 + x3 = t1 - y3; // 11 + y3 = t1 + y3; // 12 + + y3 = x3 * y3; // 13 + x3 = t3 * x3; // 14 + z3 = b3 * z3; // 15 + + t2 = a1 * t2; // 16 + t3 = t0 - t2; // 17 + t3 = a1 * t3; // 18 + + t3 = t3 + z3; // 19 + z3 = t0 + t0; // 20 + t0 = z3 + t0; // 21 + + t0 = t0 + t2; // 22 + t0 = t0 * t3; // 23 + y3 = y3 + t0; // 24 + + t2 = y1 * z1; // 25 + t2 = t2 + t2; // 26 + t0 = t2 * t3; // 27 + + x3 = x3 - t0; // 28 + z3 = t2 * t1; // 29 + z3 = z3 + z3; // 30 + + z3 = z3 + z3; // 31 + + ProjectivePoint { x: x3, y: y3, z: z3 } + } + + /// Returns `self - other`. + fn sub(&self, other: &Self) -> Self { + self.add(&other.neg()) + } + + /// Returns `self - other`. + fn sub_mixed(&self, other: &AffinePoint) -> Self { + self.add_mixed(&other.neg()) + } + + /// Returns `[k] self`. + fn mul(&self, k: &Scalar) -> Self { + let mut ret = ProjectivePoint::identity(); + + for word in k.words.iter().rev() { + for i in (0..WordWidth::USIZE).rev() { + ret = ret.double(); + let choice = ((word >> i) & (1 as Word)) as u8; + ret.conditional_assign(&(ret + *self), Choice::from(choice)); + } + } + + ret + } +} + +impl Default for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn default() -> Self { + Self::identity() + } +} + +impl Add for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn add(self, other: Self) -> Self { + ProjectivePoint::add(&self, &other) + } +} + +impl AddAssign for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn add_assign(&mut self, rhs: Self) { + *self = ProjectivePoint::add(self, &rhs); + } +} + +impl Add> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn add(self, other: AffinePoint) -> Self { + ProjectivePoint::add_mixed(&self, &other) + } +} + +impl AddAssign> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn add_assign(&mut self, rhs: AffinePoint) { + *self = ProjectivePoint::add_mixed(self, &rhs); + } +} + +impl Sum for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn sum>(iter: I) -> Self { + iter.fold(ProjectivePoint::identity(), |a, b| a + b) + } +} + +impl Sub for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn sub(self, other: Self) -> Self { + ProjectivePoint::sub(&self, &other) + } +} + +impl SubAssign for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn sub_assign(&mut self, rhs: Self) { + *self = ProjectivePoint::sub(self, &rhs); + } +} + +impl Sub> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn sub(self, other: AffinePoint) -> Self { + ProjectivePoint::sub_mixed(&self, &other) + } +} + +impl SubAssign> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn sub_assign(&mut self, rhs: AffinePoint) { + *self = ProjectivePoint::sub_mixed(self, &rhs); + } +} + +impl Mul> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn mul(self, other: Scalar) -> Self { + ProjectivePoint::mul(&self, &other) + } +} + +impl MulAssign> for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn mul_assign(&mut self, rhs: Scalar) { + *self = ProjectivePoint::mul(self, &rhs); + } +} + +impl Neg for ProjectivePoint + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + fn neg(self) -> Self { + ProjectivePoint::neg(&self) + } +} diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs new file mode 100644 index 000000000..5ec0604df --- /dev/null +++ b/weierstrass/src/scalar.rs @@ -0,0 +1,525 @@ +use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg}; +use core::{fmt, mem}; +use core::convert::TryInto; +use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; +use generic_array::ArrayLength; +use generic_array::typenum::{U1, Unsigned}; + +use super::{ + WeirstrassCurve, Word, WordWidth, Words, WordsLen, + WideWordsLen, WideWords, + WordsBytesLen, WordsBytes, + WordsP1Len, WordsP1, +}; +use crate::utils::{adc, sbb, mac}; + +#[derive(Default, Copy, Clone, Debug)] +pub struct Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + pub(crate) words: Words, +} + +impl Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + /// Returns the zero scalar. + pub fn zero() -> Self { + Self::default() + } + + /// Returns the multiplicative identity. + pub fn one() -> Self { + let mut t = Self::default(); + t.words[0] = 1; + t + } + + /// Parses the given byte array as a scalar. + /// + /// Subtracts the modulus when the byte array is larger than the modulus. + pub fn from_bytes_reduced(bytes: &WordsBytes) -> Self { + let mut words = WordsP1::::default(); + let m = mem::size_of::(); + let iter = words.iter_mut().zip(bytes.chunks_exact(m).rev()); + for (w, chunk) in iter { + *w = Word::from_be_bytes(chunk.try_into().unwrap()); + } + Self::sub_inner(words, Self { words: C::MODULUS_Q }) + } + + /// Returns the SEC1 encoding of this scalar. + fn to_bytes(&self) -> WordsBytes { + let mut buf = WordsBytes::::default(); + let m = mem::size_of::(); + let iter = buf.chunks_exact_mut(m).zip(self.words.iter().rev()); + for (chunk, w) in iter { + chunk.copy_from_slice(&w.to_be_bytes()); + } + buf + } + + /// Determine if this `Scalar` is zero. + pub fn is_zero(&self) -> Choice { + self.ct_eq(&Scalar::zero()) + } + + /// Returns self + rhs mod n + pub fn add(&self, rhs: &Self) -> Self { + // Last bit of p is usually set, so addition can result in five words. + let mut t: WordsP1 = Default::default(); + let mut carry = Word::default(); + let pairs = self.words.iter().zip(rhs.words.iter()); + for (wt, (&wb, &wa)) in t.iter_mut().zip(pairs) { + let t = adc(wa, wb, carry); + *wt = t.0; + carry = t.1; + } + *t.last_mut().unwrap() = carry; + // Attempt to subtract the MODULUS_Q, to ensure the result is in the field. + Self::sub_inner(t, Self { words: C::MODULUS_Q }) + } + + /// Returns 2*self. + pub fn double(&self) -> Self { + self.add(self) + } + + /// Returns self - rhs mod n + pub fn subtract(&self, rhs: &Self) -> Self { + let mut t: WordsP1 = Default::default(); + let n = self.words.len(); + t[..n].copy_from_slice(&self.words); + Self::sub_inner(t, *rhs) + } + + fn sub_inner(a: WordsP1, mut b: Self) -> Self { + let mut borrow = Word::default(); + for (wb, wa) in b.words.iter_mut().zip(a.iter()) { + let t = sbb(*wa, *wb, borrow); + *wb = t.0; + borrow = t.1; + } + let (_, borrow) = sbb(a[a.len() - 1], 0, borrow); + + // If underflow occurred on the final word, borrow = 0xfff...fff, otherwise + // borrow = 0x000...000. Thus, we use it as a mask to conditionally add the + // MODULUS_Q. + let mut carry = Word::default(); + for (wb, &wm) in b.words.iter_mut().zip(C::MODULUS_Q.iter()) { + let t = adc(*wb, wm & borrow, carry); + *wb = t.0; + carry = t.1; + } + b + } + + /// Barrett Reduction + /// + /// The general algorithm is: + /// ```text + /// p = n = order of group + /// b = 2^64 = 64bit machine word + /// k = 4 + /// a \in [0, 2^512] + /// mu := floor(b^{2k} / p) + /// q1 := floor(a / b^{k - 1}) + /// q2 := q1 * mu + /// q3 := <- floor(a / b^{k - 1}) + /// r1 := a mod b^{k + 1} + /// r2 := q3 * m mod b^{k + 1} + /// r := r1 - r2 + /// + /// if r < 0: r := r + b^{k + 1} + /// while r >= p: do r := r - p (at most twice) + /// ``` + /// + /// References: + /// - Handbook of Applied Cryptography, Chapter 14 + /// Algorithm 14.42 + /// http://cacr.uwaterloo.ca/hac/about/chap14.pdf + #[inline] + #[allow(clippy::too_many_arguments)] + fn barrett_reduce(a: WideWords) -> Self { + // `WideWords` length is always multiple of 2 + let k = a.len() / 2; + let mut q1 = WordsP1::::default(); + q1.copy_from_slice(&a[k-1..]); + + let mut q3 = WordsP1::::default(); + let n = q3.len(); + // Schoolbook multiplication + take last `n` words + for i in 0..n { + let (_, mut carry) = mac(q3[0], q1[i], C::MU[0], 0); + for j in 1..n { + let t = mac(q3[j], q1[i], C::MU[j], carry); + q3[j - 1] = t.0; + carry = t.1; + } + q3[n - 1] = carry; + } + + let mut r1 = WordsP1::::default(); + r1.copy_from_slice(&a[..k+1]); + + let mut r2 = WordsP1::::default(); + // Schoolbook multiplication + take first `n` words + for i in 0..n { + let mut carry = Word::default(); + for j in 0..(n - i) { + let wm = C::MODULUS_Q.get(j).cloned().unwrap_or(0); + let t = mac(r2[i + j], q3[i], wm, carry); + r2[i + j] = t.0; + carry = t.1; + } + } + + // If underflow occurred on the final word - don't care (= add b^{k+1}). + let mut borrow = Word::default(); + for (w1, &w2) in r1.iter_mut().zip(r2.iter()) { + let t = sbb(*w1, w2, borrow); + *w1 = t.0; + borrow = t.1; + } + let mut r = r1; + + fn sub_mod_if_necessary(r: &mut WordsP1) + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, + { + let mut borrow = Word::default(); + let n = r.len(); + for (wr, &wm) in r.iter_mut().zip(C::MODULUS_Q.iter()) { + let t = sbb(*wr, wm, borrow); + *wr = t.0; + borrow = t.1; + } + let t = sbb(r[n - 1], 0, borrow); + r[n - 1] = t.0; + borrow = t.1; + + // If underflow occurred on the final limb, borrow = 0xfff...fff, + // otherwise borrow = 0x000...000. Thus, we use it as a mask to + // conditionally add the modulus. + let mut carry = Word::default(); + for (wr, &wm) in r.iter_mut().zip(C::MODULUS_Q.iter()) { + let t = adc(*wr, wm & borrow, carry); + *wr = t.0; + carry = t.1; + } + r[n - 1] = adc(r[n - 1], 0, carry).0; + } + + // Result is in range (0, 3*n - 1), + // and 90% of the time, no subtraction will be needed. + sub_mod_if_necessary::(&mut r); + sub_mod_if_necessary::(&mut r); + + let mut res = Self::default(); + res.words.copy_from_slice(&r[..k]); + res + } + + /// Returns self * rhs mod n + pub fn mul(&self, rhs: &Self) -> Self { + let mut w = WideWords::::default(); + let n = rhs.words.len(); + + // Schoolbook multiplication. + for i in 0..n { + let mut carry = Word::default(); + for j in 0..n { + let t = mac(w[i + j], self.words[i], rhs.words[j], carry); + w[i + j] = t.0; + carry = t.1; + } + w[i + n] = carry; + } + Self::barrett_reduce(w) + } + + /// Returns self * self mod p + pub fn square(&self) -> Self { + self.mul(self) + } + + /// Returns `self^by`, where `by` is a little-endian integer exponent. + /// + /// **This operation is variable time with respect to the exponent.** + /// If the exponent is fixed, this operation is effectively constant time. + pub fn pow_vartime(&self, by: &Words) -> Self { + let mut res = Self::one(); + let n = WordWidth::USIZE; + for e in by.iter().rev() { + for i in (0..n).rev() { + res = res.square(); + if ((*e >> i) & 1) == 1 { + res *= *self; + } + } + } + res + } + + /// Returns the multiplicative inverse of self, if self is non-zero + pub fn invert(&self) -> CtOption { + // We need to find b such that b * a ≡ 1 mod p. As we are in a prime + // field, we can apply Fermat's Little Theorem: + // + // a^p ≡ a mod p + // a^(p-1) ≡ 1 mod p + // a^(p-2) * a ≡ 1 mod p + // + // Thus inversion can be implemented with a single exponentiation. + // + // This is `n - 2`, so the top right two digits are `4f` instead of `51`. + let inverse = self.pow_vartime(&C::MODULUS_Q_M2); + CtOption::new(inverse, !self.is_zero()) + } + + /// Is integer representing equivalence class odd + pub fn is_odd(&self) -> Choice { + ((self.words[0] & 1) as u8).into() + } + + /// Is integer representing equivalence class even + pub fn is_even(&self) -> Choice { + !self.is_odd() + } + + fn shr1(&mut self) { + todo!(); + } + + /// Faster inversion using Stein's algorithm + pub fn invert_vartime(&self) -> CtOption { + // https://link.springer.com/article/10.1007/s13389-016-0135-4 + todo!(); + } + + pub fn from_repr(bytes: WordsBytes) -> Option { + let mut words = Words::::default(); + let n = mem::size_of::(); + let iter = words.iter_mut().rev().zip(bytes.chunks_exact(n)); + for (wm, chunk) in iter { + *wm = Word::from_be_bytes(chunk.try_into().unwrap()); + } + + // If w is in the range [0, n) then w - n will overflow, resulting + // in a borrow value of 2^64 - 1. + let mut borrow = Word::default(); + for (&w, &wm) in words.iter().zip(C::MODULUS_Q.iter()) { + borrow = sbb(w, wm, borrow).1; + } + let is_some = (borrow as u8) & 1; + + CtOption::new(Self { words }, Choice::from(is_some)).into() + } +} + + +impl fmt::UpperHex for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for word in self.words.iter().rev() { + write!(f, "{:016X}", word)?; + } + Ok(()) + } +} + +impl ConditionallySelectable for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let mut res = Self::zero(); + let pairs = a.words.iter().zip(b.words.iter()); + for (vr, (va, vb)) in res.words.iter_mut().zip(pairs) { + *vr = Word::conditional_select(va, vb, choice); + } + res + } +} + +impl ConstantTimeEq for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn ct_eq(&self, other: &Self) -> Choice { + let mut res = 1u8.into(); + for (a, b) in self.words.iter().zip(other.words.iter()) { + res &= a.ct_eq(b); + } + res + } +} + +impl PartialEq for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() + } +} + +impl Add> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn add(self, other: Self) -> Self { + Scalar::add(&self, &other) + } +} + +impl AddAssign> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn add_assign(&mut self, other: Self) { + *self = Scalar::add(self, &other); + } +} + +impl Sub> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn sub(self, other: Self) -> Self { + Scalar::subtract(&self, &other) + } +} + +impl SubAssign> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn sub_assign(&mut self, other: Self) { + *self = Scalar::subtract(self, &other); + } +} + + +impl Mul> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn mul(self, other: Self) -> Self { + Scalar::mul(&self, &other) + } +} + +impl MulAssign> for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn mul_assign(&mut self, other: Self) { + *self = Scalar::mul(self, &other); + } +} + +impl Neg for Scalar + where + C: WeirstrassCurve, + WordsLen: ArrayLength + Add, + WideWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn neg(self) -> Self { + Scalar::zero() - self + } +} + +#[cfg(feature = "zeroize")] +impl Zeroize for Scalar { + fn zeroize(&mut self) { + self.words.zeroize(); + } +} diff --git a/weierstrass/src/utils.rs b/weierstrass/src/utils.rs new file mode 100644 index 000000000..9ccefce7c --- /dev/null +++ b/weierstrass/src/utils.rs @@ -0,0 +1,26 @@ +use generic_array::typenum::Unsigned; +use crate::{DoubleWord, Word, WordWidth}; + +/// Computes `a + b + carry`, returning the result along with the new carry. +#[inline(always)] +pub(crate) const fn adc(a: Word, b: Word, carry: Word) -> (Word, Word) { + let ret = (a as DoubleWord) + (b as DoubleWord) + (carry as DoubleWord); + (ret as Word, (ret >> WordWidth::USIZE) as Word) +} + +/// Computes `a - (b + borrow)`, returning the result along with the new borrow. +#[inline(always)] +pub(crate) const fn sbb(a: Word, b: Word, borrow: Word) -> (Word, Word) { + let (a, b) = (a as DoubleWord, b as DoubleWord); + let t = (borrow >> (WordWidth::USIZE - 1)) as DoubleWord; + let ret = a.wrapping_sub(b + t); + (ret as Word, (ret >> WordWidth::USIZE) as Word) +} + +/// Computes `a + (b * c) + carry`, returning the result along with the new carry. +#[inline(always)] +pub(crate) const fn mac(a: Word, b: Word, c: Word, carry: Word) -> (Word, Word) { + let (a, b, c) = (a as DoubleWord, b as DoubleWord, c as DoubleWord); + let ret = a + b * c + (carry as DoubleWord); + (ret as Word, (ret >> 64) as Word) +} From 6a3306627777f5d0dadad81ab9aa7aee413deee3 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Fri, 2 Oct 2020 06:49:09 +0300 Subject: [PATCH 02/20] Update weierstrass/src/utils.rs Co-authored-by: Roman Proskuryakov --- weierstrass/src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weierstrass/src/utils.rs b/weierstrass/src/utils.rs index 9ccefce7c..5f7dd9aaf 100644 --- a/weierstrass/src/utils.rs +++ b/weierstrass/src/utils.rs @@ -22,5 +22,5 @@ pub(crate) const fn sbb(a: Word, b: Word, borrow: Word) -> (Word, Word) { pub(crate) const fn mac(a: Word, b: Word, c: Word, carry: Word) -> (Word, Word) { let (a, b, c) = (a as DoubleWord, b as DoubleWord, c as DoubleWord); let ret = a + b * c + (carry as DoubleWord); - (ret as Word, (ret >> 64) as Word) + (ret as Word, (ret >> WordWidth::USIZE) as Word) } From 17062bc8b21f74eddfe7afb679a17c9b7ec7c9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 2 Oct 2020 06:52:09 +0300 Subject: [PATCH 03/20] add newline --- weierstrass/src/gost_test256.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weierstrass/src/gost_test256.rs b/weierstrass/src/gost_test256.rs index 5a74de7cf..7960d616a 100644 --- a/weierstrass/src/gost_test256.rs +++ b/weierstrass/src/gost_test256.rs @@ -45,4 +45,4 @@ impl WeirstrassCurve for GostTest256 { #[cfg(target_pointer_width = "64")] const PT: Word = 0xdbf9_51d5_883b_2b2f; -} \ No newline at end of file +} From fa52a519b4d0b326cbf48a23fdf19deeeea8c560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 2 Oct 2020 06:56:20 +0300 Subject: [PATCH 04/20] minor doc changes --- weierstrass/src/field.rs | 2 +- weierstrass/src/scalar.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs index bc794db6d..e9dbf5d75 100644 --- a/weierstrass/src/field.rs +++ b/weierstrass/src/field.rs @@ -38,7 +38,7 @@ impl FieldElement WordsBytesLen: ArrayLength, Words: Copy, { - + /// Returns the zero element (additive identity). pub fn zero() -> Self { Self { words: Default::default(), diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 5ec0604df..d9ee49c9e 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -35,7 +35,7 @@ impl Scalar WordsBytesLen: ArrayLength, Words: Copy, { - /// Returns the zero scalar. + /// Returns the zero scalar (additive identity). pub fn zero() -> Self { Self::default() } From 586d3ce439a252e78b37d4366bc134dc12898d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Thu, 15 Oct 2020 14:01:13 +0300 Subject: [PATCH 05/20] remove GOST test, add a=-3 special case --- weierstrass/src/gost_test256.rs | 48 ---- weierstrass/src/lib.rs | 30 ++- weierstrass/src/main.rs | 117 --------- weierstrass/src/projective.rs | 423 ++++++++++++++++++++++---------- weierstrass/src/scalar.rs | 8 +- 5 files changed, 311 insertions(+), 315 deletions(-) delete mode 100644 weierstrass/src/gost_test256.rs delete mode 100644 weierstrass/src/main.rs diff --git a/weierstrass/src/gost_test256.rs b/weierstrass/src/gost_test256.rs deleted file mode 100644 index 7960d616a..000000000 --- a/weierstrass/src/gost_test256.rs +++ /dev/null @@ -1,48 +0,0 @@ -use generic_array::typenum::U256; -use crate::{WeirstrassCurve, Word, Words, WordsP1}; -use crate::field::FieldElement; -use biguint_literal::hex_biguint; - -#[derive(Copy, Default, Debug, Clone)] -pub struct GostTest256; - -impl WeirstrassCurve for GostTest256 { - type Bits = U256; - - const A: FieldElement = FieldElement { words: hex_biguint!(" - 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC983 - ") }; - const B: FieldElement = FieldElement { words: hex_biguint!(" - 58DF983A171CD5AE20391ABE272C66AD004469B4541A2542807BBFA323A3952A - ") }; - const MODULUS_P: Words = hex_biguint!(" - 8000000000000000000000000000000000000000000000000000000000000431 - "); - const MODULUS_P_M2: Words = hex_biguint!(" - 800000000000000000000000000000000000000000000000000000000000042f - "); - const MODULUS_Q: Words = hex_biguint!(" - 8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3 - "); - const MODULUS_Q_M2: Words = hex_biguint!(" - 8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B1 - "); - const GENERATOR_X: FieldElement = FieldElement { words: hex_biguint!(" - 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36D - ") }; - const GENERATOR_Y: FieldElement = FieldElement { words: hex_biguint!(" - 03F66B354AA3DAA467617A63E4B6DDE67CE5090AF69BF9AE9AF45A5A471125F5 - ") }; - const R: FieldElement = FieldElement { words: hex_biguint!(" - 7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBCF - ") }; - const R2: FieldElement = FieldElement { words: hex_biguint!(" - 0000000000000000000000000000000000000000000000000000000000464584 - ") }; - const MU: WordsP1 = hex_biguint!(" - 0000000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFABC05D79DB5A27AACE98C0F9B14CC2941 - "); - - #[cfg(target_pointer_width = "64")] - const PT: Word = 0xdbf9_51d5_883b_2b2f; -} diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index dc3a71383..b2c018103 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -1,3 +1,4 @@ +pub use {generic_array, subtle}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ self, @@ -14,16 +15,13 @@ mod scalar; mod projective; mod utils; -mod gost_test256; - pub use affine::AffinePoint; pub use field::FieldElement; pub use scalar::Scalar; pub use projective::ProjectivePoint; -pub use gost_test256::GostTest256; // TODO: add cfgs for other word sizes -type Word = u64; +pub type Word = u64; type DoubleWord = u128; type WordWidth = typenum::U64; /// Divisor for getting number of words in the wider buffer, it's equal @@ -34,16 +32,16 @@ fn random_word(mut rng: impl CryptoRng + RngCore) -> Word { rng.next_u64() } -type WordsLen = Quot<::Bits, WordWidth>; -type Words = GenericArray>; -type WordsBytesLen = Quot<::Bits, U8>; -type WordsBytes = GenericArray>; +pub type WordsLen = Quot<::Bits, WordWidth>; +pub type Words = GenericArray>; +pub type WordsBytesLen = Quot<::Bits, U8>; +pub type WordsBytes = GenericArray>; -type WordsP1Len = Sum, U1>; -type WordsP1 = GenericArray>; +pub type WordsP1Len = Sum, U1>; +pub type WordsP1 = GenericArray>; -type WideWordsLen = Quot<::Bits, WideWordsDiv>; -type WideWords = GenericArray>; +pub type WideWordsLen = Quot<::Bits, WideWordsDiv>; +pub type WideWords = GenericArray>; pub trait WeirstrassCurve where @@ -57,10 +55,12 @@ pub trait WeirstrassCurve type Bits: Unsigned + Div + Div + Div + Div; const A: FieldElement; + const A_IS_MINUS_3: bool; const B: FieldElement; const MODULUS_P: Words; /// p - 2 const MODULUS_P_M2: Words; + const MODULUS_Q: Words; /// q - 2 const MODULUS_Q_M2: Words; @@ -74,10 +74,8 @@ pub trait WeirstrassCurve /// R2 = 2^(2*Bits) mod p const R2: FieldElement; + /// MU = floor(2^512 / q) + const MU: WordsP1; /// P*PT (mod 2^WORD_WIDTH) == -1 const PT: Word; - - /// MU = floor(2^512 / n) - const MU: WordsP1; } - diff --git a/weierstrass/src/main.rs b/weierstrass/src/main.rs deleted file mode 100644 index 6f9a6dea5..000000000 --- a/weierstrass/src/main.rs +++ /dev/null @@ -1,117 +0,0 @@ -use weierstrass; -use hex_literal::hex; -use generic_array::GenericArray; - -use weierstrass::{GostTest256, AffinePoint, FieldElement}; - -type Scalar = weierstrass::Scalar; -type ProjectivePoint = weierstrass::ProjectivePoint; - -fn main() { - let _p: [u8; 32] = hex!(" - 8000000000000000000000000000000000000000000000000000000000000431 - "); - let e = hex!(" - 2DFBC1B372D89A1188C09C52E0EEC61FCE52032AB1022E8E67ECE6672B043EE5 - "); - let d = hex!(" - 7A929ADE789BB9BE10ED359DD39A72C11B60961F49397EEE1D19CE9891EC3B28 - "); - let k = hex!(" - 77105C9B20BCD3122823C8CF6FCC7B956DE33814E95B7FE64FED924594DCEAB3 - "); - - let k = Scalar::from_bytes_reduced(GenericArray::from_slice(&k)); - let d = Scalar::from_bytes_reduced(GenericArray::from_slice(&d)); - let e = Scalar::from_bytes_reduced(GenericArray::from_slice(&e)); - - println!("k {:X}", k); - - let p = ProjectivePoint::generator(); - - println!("x before {:X}", &p.x); - println!("y before {:X}", &p.y); - println!("z before {:X}", &p.z); - - let p = p * k; - - println!("x raw {:X}", &p.x); - println!("y raw {:X}", &p.y); - println!("z raw {:X}", &p.z); - - let p = p.to_affine(); - - println!("x raw2 {:X}", &p.x); - println!("y raw2 {:X}", &p.y); - - print_hex("x ", &p.x.to_bytes()); - print_hex("y ", &p.y.to_bytes()); - - let r = Scalar::from_bytes_reduced(&p.x.to_bytes()); - - println!("r {:X}", r); - - let rd = r*d; - println!("rd {:X}", rd); - let ke = k*e; - println!("ke {:X}", ke); - - let calc_s = rd + ke; - - println!("calc s {:X}", calc_s); - - - - println!("verification"); - - let r = hex!(" - 41AA28D2F1AB148280CD9ED56FEDA41974053554A42767B83AD043FD39DC0493 - "); - let s = hex!(" - 01456C64BA4642A1653C235A98A60249BCD6D3F746B631DF928014F6C5BF9C40 - "); - let xq = hex!(" - 7F2B49E270DB6D90D8595BEC458B50C58585BA1D4E9B788F6689DBD8E56FD80B - "); - let yq = hex!(" - 26F1B489D6701DD185C8413A977B3CBBAF64D1C593D26627DFFB101A87FF77DA - "); - - let r = Scalar::from_repr(*GenericArray::from_slice(&r)).unwrap(); - let s = Scalar::from_repr(*GenericArray::from_slice(&s)).unwrap(); - - println!("r {:X}", r); - println!("s {:X}", s); - - let v = e.invert().unwrap(); - println!("v {:X}", v); - - let z1 = s*v; - let z2 = -r*v; - println!("z1 {:X}", z1); - println!("z2 {:X}", z2); - - let q = AffinePoint { - x: FieldElement::from_bytes(GenericArray::from_slice(&xq)).unwrap(), - y: FieldElement::from_bytes(GenericArray::from_slice(&yq)).unwrap(), - infinity: subtle::Choice::from(0), - }; - - let c = ProjectivePoint::generator()*z1 + ProjectivePoint::from(q)*z2; - let c = c.to_affine(); - - print_hex("xc ", &c.x.to_bytes()); - print_hex("yc ", &c.y.to_bytes()); - - let r = Scalar::from_bytes_reduced(&c.x.to_bytes()); - println!("r: {:X}", r); -} - - -fn print_hex(s: &str, buf: &[u8]) { - print!("{}", s); - for b in buf { - print!("{:02X}", b); - } - println!(); -} diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index a694c6cac..6ce64bf5a 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -153,190 +153,353 @@ impl ProjectivePoint /// Returns `self + other`. fn add(&self, other: &Self) -> Self { // We implement the complete addition formula from Renes-Costello-Batina 2015 - // (https://eprint.iacr.org/2015/1060 Algorithm 1). The comments after each line + // (https://eprint.iacr.org/2015/1060). The comments after each line // indicate which algorithm steps are being performed. let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; let &ProjectivePoint { x: x2, y: y2, z: z2 } = other; + let b1 = C::B; let b3 = C::B + C::B + C::B; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); let (mut x3, mut y3, mut z3); - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t2 = z1 * z2; // 3 + if C::A_IS_MINUS_3 { + // Algorithm 4 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 - t3 = x1 + y1; // 4 - t4 = x2 + y2; // 5 - t3 = t3 * t4; // 6 + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 - t4 = t0 + t1; // 7 - t3 = t3 - t4; // 8 - t4 = x1 + z1; // 9 + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = y1 + z1; // 9 - t5 = x2 + z2; // 10 - t4 = t4 * t5; // 11 - t5 = t0 + t2; // 12 + x3 = y2 + z2; // 10 + t4 = t4 * x3; // 11 + x3 = t1 + t2; // 12 - t4 = t4 - t5; // 13 - t5 = y1 + z1; // 14 - x3 = y2 + z2; // 15 + t4 = t4 - x3; // 13 + x3 = x1 + z1; // 14 + y3 = x2 + z2; // 15 - t5 = t5 * x3; // 16 - x3 = t1 + t2; // 17 - t5 = t5 - x3; // 18 + x3 = x3 * y3; // 16 + y3 = t0 + t2; // 17 + y3 = x3 - y3; // 18 - z3 = a1 * t4; // 19 - x3 = b3 * t2; // 20 - z3 = x3 + z3; // 21 + z3 = b1 * t2; // 19 + x3 = y3 - z3; // 20 + z3 = x3 + x3; // 21 - x3 = t1 - z3; // 22 - z3 = t1 + z3; // 23 - y3 = x3 * z3; // 24 + x3 = x3 + z3; // 22 + z3 = t1 - x3; // 23 + x3 = t1 + x3; // 24 - t1 = t0 + t0; // 25 - t1 = t1 + t0; // 26 - t2 = a1 * t2; // 27 + y3 = b1 * y3; // 25 + t1 = t2 + t2; // 26 + t2 = t1 + t2; // 27 - t4 = b3 * t4; // 28 - t1 = t1 + t2; // 29 - t2 = t0 - t2; // 30 + y3 = y3 - t2; // 28 + y3 = y3 - t0; // 29 + t1 = y3 + y3; // 30 - t2 = a1 * t2; // 31 - t4 = t4 + t2; // 32 - t0 = t1 * t4; // 33 + y3 = t1 + y3; // 31 + t1 = t0 + t0; // 32 + t0 = t1 + t0; // 33 - y3 = y3 + t0; // 34 - t0 = t5 * t4; // 35 - x3 = t3 * x3; // 36 + t0 = t0 - t2; // 34 + t1 = t4 * y3; // 35 + t2 = t0 * y3; // 36 - x3 = x3 - t0; // 37 - t0 = t3 * t1; // 38 - z3 = t5 * z3; // 39 + y3 = x3 * z3; // 37 + y3 = y3 + t2; // 38 + x3 = t3 * x3; // 39 - z3 = z3 + t0; // 40 + x3 = x3 - t1; // 40 + z3 = t4 * z3; // 41 + t1 = t3 * t0; // 42 + z3 = z3 + t1; // 43 + } else { + // Algorithm 1 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 + + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 + + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = x1 + z1; // 9 + + t5 = x2 + z2; // 10 + t4 = t4 * t5; // 11 + t5 = t0 + t2; // 12 + + t4 = t4 - t5; // 13 + t5 = y1 + z1; // 14 + x3 = y2 + z2; // 15 + + t5 = t5 * x3; // 16 + x3 = t1 + t2; // 17 + t5 = t5 - x3; // 18 + + z3 = a1 * t4; // 19 + x3 = b3 * t2; // 20 + z3 = x3 + z3; // 21 + + x3 = t1 - z3; // 22 + z3 = t1 + z3; // 23 + y3 = x3 * z3; // 24 + + t1 = t0 + t0; // 25 + t1 = t1 + t0; // 26 + t2 = a1 * t2; // 27 + + t4 = b3 * t4; // 28 + t1 = t1 + t2; // 29 + t2 = t0 - t2; // 30 + + t2 = a1 * t2; // 31 + t4 = t4 + t2; // 32 + t0 = t1 * t4; // 33 + + y3 = y3 + t0; // 34 + t0 = t5 * t4; // 35 + x3 = t3 * x3; // 36 + + x3 = x3 - t0; // 37 + t0 = t3 * t1; // 38 + z3 = t5 * z3; // 39 + + z3 = z3 + t0; // 40 + } ProjectivePoint { x: x3, y: y3, z: z3 } } /// Returns `self + other`. fn add_mixed(&self, other: &AffinePoint) -> Self { // We implement the complete mixed addition formula from Renes-Costello-Batina - // 2015 (Algorithm 2). The comments after each line indicate which algorithm steps + // 2015. The comments after each line indicate which algorithm steps // are being performed. let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; let &AffinePoint { x: x2, y: y2, .. } = other; + let b1 = C::B; let b3 = C::B + C::B + C::B; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); let (mut x3, mut y3, mut z3); - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t3 = x2 + y2; // 3 - - t4 = x1 + y1; // 4 - t3 = t3 * t4; // 5 - t4 = t0 + t1; // 6 - - t3 = t3 - t4; // 7 - t4 = x2 * z1; // 8 - t4 = t4 + x1; // 9 - - t5 = y2 * z1; // 10 - t5 = t5 + y1; // 11 - z3 = a1 * t4; // 12 - - x3 = b3 * z1; // 13 - z3 = x3 + z3; // 14 - x3 = t1 - z3; // 15 - - z3 = t1 + z3; // 16 - y3 = x3 * z3; // 17 - t1 = t0 + t0; // 18 - - t1 = t1 + t0; // 19 - t2 = a1 * z1; // 20 - t4 = b3 * t4; // 21 - - t1 = t1 + t2; // 22 - t2 = t0 - t2; // 23 - t2 = a1 * t2; // 24 - - t4 = t4 + t2; // 25 - t0 = t1 * t4; // 26 - y3 = y3 + t0; // 27 - - t0 = t5 * t4; // 28 - x3 = t3 * x3; // 29 - x3 = x3 - t0; // 30 - - t0 = t3 * t1; // 31 - z3 = t5 * z3; // 32 - z3 = z3 + t0; // 33 - + if C::A_IS_MINUS_3 { + // Algorithm 5 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = y2 * z1; // 8 + t4 = t4 + y1; // 9 + + y3 = x2 * z1; // 10 + y3 = y3 + x1; // 11 + z3 = b1 * z1; // 12 + + x3 = y3 - z3; // 13 + z3 = x3 + x3; // 14 + x3 = x3 + z3; // 15 + + z3 = t1 - x3; // 16 + x3 = t1 + x3; // 17 + y3 = b1 * y3; // 18 + + t1 = z1 + z1; // 19 + t2 = t1 + z1; // 20 + y3 = y3 - t2; // 21 + + y3 = y3 - t0; // 22 + t1 = y3 + y3; // 23 + y3 = t1 + y3; // 24 + + t1 = t0 + t0; // 25 + t0 = t1 + t0; // 26 + t0 = t0 - t2; // 27 + + t1 = t4 * y3; // 28 + t2 = t0 * y3; // 29 + y3 = x3 * z3; // 30 + + y3 = y3 + t2; // 31 + x3 = t3 * x3; // 32 + x3 = x3 - t1; // 33 + + z3 = t4 * z3; // 34 + t1 = t3 * t0; // 35 + z3 = z3 + t1; // 36 + } else { + // Algorithm 2 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = x2 * z1; // 8 + t4 = t4 + x1; // 9 + + t5 = y2 * z1; // 10 + t5 = t5 + y1; // 11 + z3 = a1 * t4; // 12 + + x3 = b3 * z1; // 13 + z3 = x3 + z3; // 14 + x3 = t1 - z3; // 15 + + z3 = t1 + z3; // 16 + y3 = x3 * z3; // 17 + t1 = t0 + t0; // 18 + + t1 = t1 + t0; // 19 + t2 = a1 * z1; // 20 + t4 = b3 * t4; // 21 + + t1 = t1 + t2; // 22 + t2 = t0 - t2; // 23 + t2 = a1 * t2; // 24 + + t4 = t4 + t2; // 25 + t0 = t1 * t4; // 26 + y3 = y3 + t0; // 27 + + t0 = t5 * t4; // 28 + x3 = t3 * x3; // 29 + x3 = x3 - t0; // 30 + + t0 = t3 * t1; // 31 + z3 = t5 * z3; // 32 + z3 = z3 + t0; // 33 + } ProjectivePoint { x: x3, y: y3, z: z3 } } /// Doubles this point. pub fn double(&self) -> Self { // We implement the complete doubling formula from Renes-Costello-Batina 2015 - // (https://eprint.iacr.org/2015/1060 Algorithm 3). The comments after each line + // (https://eprint.iacr.org/2015/1060). The comments after each line // indicate which algorithm steps are being performed. let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; + let b1 = C::B; let b3 = C::B + C::B + C::B; let a1 = C::A; let (mut t0, t1, mut t2, mut t3); let (mut x3, mut y3, mut z3); - - t0 = x1 * x1; // 1 - t1 = y1 * y1; // 2 - t2 = z1 * z1; // 3 - - t3 = x1 * y1; // 4 - t3 = t3 + t3; // 5 - z3 = x1 * z1; // 6 - - z3 = z3 + z3; // 7 - x3 = a1 * z3; // 8 - y3 = b3 * t2; // 9 - - y3 = x3 + y3; // 10 - x3 = t1 - y3; // 11 - y3 = t1 + y3; // 12 - - y3 = x3 * y3; // 13 - x3 = t3 * x3; // 14 - z3 = b3 * z3; // 15 - - t2 = a1 * t2; // 16 - t3 = t0 - t2; // 17 - t3 = a1 * t3; // 18 - - t3 = t3 + z3; // 19 - z3 = t0 + t0; // 20 - t0 = z3 + t0; // 21 - - t0 = t0 + t2; // 22 - t0 = t0 * t3; // 23 - y3 = y3 + t0; // 24 - - t2 = y1 * z1; // 25 - t2 = t2 + t2; // 26 - t0 = t2 * t3; // 27 - - x3 = x3 - t0; // 28 - z3 = t2 * t1; // 29 - z3 = z3 + z3; // 30 - - z3 = z3 + z3; // 31 - + if C::A_IS_MINUS_3 { + // Algorithm 6 + t0 = x1 * x1; // 1 + t1 = y1 * y1; // 2 + t2 = z1 * z1; // 3 + + t3 = x1 * y1; // 4 + t3 = t3 + t3; // 5 + z3 = x1 * z1; // 6 + + z3 = z3 + z3; // 7 + y3 = b1 * t2; // 8 + y3 = y3 - z3; // 9 + + x3 = y3 + y3; // 10 + y3 = x3 + y3; // 11 + x3 = t1 - y3; // 12 + + y3 = t1 + y3; // 13 + y3 = x3 * y3; // 14 + x3 = x3 * t3; // 15 + + t3 = t2 + t2; // 16 + t2 = t2 + t3; // 17 + z3 = b1 * z3; // 18 + + z3 = z3 - t2; // 19 + z3 = z3 - t0; // 20 + t3 = z3 + z3; // 21 + + z3 = z3 + t3; // 22 + t3 = t0 + t0; // 23 + t0 = t3 + t0; // 24 + + t0 = t0 - t2; // 25 + t0 = t0 * z3; // 26 + y3 = y3 + t0; // 27 + + t0 = y1 * z1; // 28 + t0 = t0 + t0; // 29 + z3 = t0 * z3; // 30 + + x3 = x3 - z3; // 31 + z3 = t0 * t1; // 32 + z3 = z3 + z3; // 33 + + z3 = z3 + z3; // 34 + } else { + // Algorithm 3 + t0 = x1 * x1; // 1 + t1 = y1 * y1; // 2 + t2 = z1 * z1; // 3 + + t3 = x1 * y1; // 4 + t3 = t3 + t3; // 5 + z3 = x1 * z1; // 6 + + z3 = z3 + z3; // 7 + x3 = a1 * z3; // 8 + y3 = b3 * t2; // 9 + + y3 = x3 + y3; // 10 + x3 = t1 - y3; // 11 + y3 = t1 + y3; // 12 + + y3 = x3 * y3; // 13 + x3 = t3 * x3; // 14 + z3 = b3 * z3; // 15 + + t2 = a1 * t2; // 16 + t3 = t0 - t2; // 17 + t3 = a1 * t3; // 18 + + t3 = t3 + z3; // 19 + z3 = t0 + t0; // 20 + t0 = z3 + t0; // 21 + + t0 = t0 + t2; // 22 + t0 = t0 * t3; // 23 + y3 = y3 + t0; // 24 + + t2 = y1 * z1; // 25 + t2 = t2 + t2; // 26 + t0 = t2 * t3; // 27 + + x3 = x3 - t0; // 28 + z3 = t2 * t1; // 29 + z3 = z3 + z3; // 30 + + z3 = z3 + z3; // 31 + } ProjectivePoint { x: x3, y: y3, z: z3 } } diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index d9ee49c9e..aa64d04c3 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -61,7 +61,7 @@ impl Scalar } /// Returns the SEC1 encoding of this scalar. - fn to_bytes(&self) -> WordsBytes { + pub fn to_bytes(&self) -> WordsBytes { let mut buf = WordsBytes::::default(); let m = mem::size_of::(); let iter = buf.chunks_exact_mut(m).zip(self.words.iter().rev()); @@ -304,9 +304,9 @@ impl Scalar !self.is_odd() } - fn shr1(&mut self) { - todo!(); - } + // fn shr1(&mut self) { + // todo!(); + // } /// Faster inversion using Stein's algorithm pub fn invert_vartime(&self) -> CtOption { From ead80f467d804953e9d5647cf00f642039d2c6af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Thu, 15 Oct 2020 14:14:13 +0300 Subject: [PATCH 06/20] require subtle v2.3 --- weierstrass/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weierstrass/Cargo.toml b/weierstrass/Cargo.toml index 37d737274..de36b39b8 100644 --- a/weierstrass/Cargo.toml +++ b/weierstrass/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] generic-array = "0.14" -subtle = "2" +subtle = "2.3" rand_core = "0.5" biguint-literal = { git = "https://github.com/RustCrypto/utils", branch = "biguint" } hex-literal = "0.3" From a9775b13cbc91aaddc0f4fede8a450b7e3e22c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Thu, 15 Oct 2020 20:19:01 +0300 Subject: [PATCH 07/20] add double aliases --- weierstrass/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index b2c018103..7cd7d129d 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -36,6 +36,8 @@ pub type WordsLen = Quot<::Bits, WordWidth>; pub type Words = GenericArray>; pub type WordsBytesLen = Quot<::Bits, U8>; pub type WordsBytes = GenericArray>; +pub type DoubleWordsBytesLen = Quot<::Bits, U4>; +pub type DoubleWordsBytes = GenericArray>; pub type WordsP1Len = Sum, U1>; pub type WordsP1 = GenericArray>; From ec2de6255d57a6f9d48a4dd5d1194278042eff13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 17:57:31 +0300 Subject: [PATCH 08/20] fix support of curves with small q --- weierstrass/src/lib.rs | 3 +++ weierstrass/src/scalar.rs | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 7cd7d129d..97d8d7fea 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -66,6 +66,9 @@ pub trait WeirstrassCurve const MODULUS_Q: Words; /// q - 2 const MODULUS_Q_M2: Words; + /// floor(q/m), where `m` is a biggest representable number with given + /// number of bits (i.e. `0xFFFF...FFFF`) + const MODULUS_Q_REDUCE_N: usize; // we can't define GENERATOR, bacause `Choice` does not // support const construction diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index aa64d04c3..2a62e6145 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -13,7 +13,7 @@ use super::{ }; use crate::utils::{adc, sbb, mac}; -#[derive(Default, Copy, Clone, Debug)] +#[derive(Default, Copy, Clone, Debug, Eq)] pub struct Scalar where C: WeirstrassCurve, @@ -57,7 +57,12 @@ impl Scalar for (w, chunk) in iter { *w = Word::from_be_bytes(chunk.try_into().unwrap()); } - Self::sub_inner(words, Self { words: C::MODULUS_Q }) + let modulus = Self { words: C::MODULUS_Q }; + let mut res = Self::sub_inner(words, modulus); + for _ in 1..C::MODULUS_Q_REDUCE_N { + res -= modulus; + } + res } /// Returns the SEC1 encoding of this scalar. From 9a7009608584fcf1d7b2df54f980ed489ffb4631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 19:59:17 +0300 Subject: [PATCH 09/20] add support for curves with a=0 --- weierstrass/src/lib.rs | 8 +- weierstrass/src/projective.rs | 668 ++++++++++++++++++++-------------- 2 files changed, 401 insertions(+), 275 deletions(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 97d8d7fea..4df20027a 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -45,6 +45,12 @@ pub type WordsP1 = GenericArray>; pub type WideWordsLen = Quot<::Bits, WideWordsDiv>; pub type WideWords = GenericArray>; +pub enum CurveKind { + General, + Minus3, + Zero, +} + pub trait WeirstrassCurve where Self: Sized + Copy + Default, @@ -57,8 +63,8 @@ pub trait WeirstrassCurve type Bits: Unsigned + Div + Div + Div + Div; const A: FieldElement; - const A_IS_MINUS_3: bool; const B: FieldElement; + const CURVE_KIND: CurveKind; const MODULUS_P: Words; /// p - 2 const MODULUS_P_M2: Words; diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 6ce64bf5a..9dbd8da46 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -4,7 +4,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use generic_array::{ArrayLength, typenum::{U1, Unsigned}}; use crate::{ - WeirstrassCurve, Word, WordWidth, + WeirstrassCurve, CurveKind, + Word, WordWidth, Words, WordsLen, WideWordsLen, WordsBytesLen, @@ -165,120 +166,170 @@ impl ProjectivePoint let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); let (mut x3, mut y3, mut z3); - if C::A_IS_MINUS_3 { - // Algorithm 4 - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t2 = z1 * z2; // 3 - t3 = x1 + y1; // 4 - t4 = x2 + y2; // 5 - t3 = t3 * t4; // 6 + match C::CURVE_KIND { + CurveKind::General => { + // Algorithm 1 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 - t4 = t0 + t1; // 7 - t3 = t3 - t4; // 8 - t4 = y1 + z1; // 9 + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 - x3 = y2 + z2; // 10 - t4 = t4 * x3; // 11 - x3 = t1 + t2; // 12 + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = x1 + z1; // 9 - t4 = t4 - x3; // 13 - x3 = x1 + z1; // 14 - y3 = x2 + z2; // 15 + t5 = x2 + z2; // 10 + t4 = t4 * t5; // 11 + t5 = t0 + t2; // 12 - x3 = x3 * y3; // 16 - y3 = t0 + t2; // 17 - y3 = x3 - y3; // 18 + t4 = t4 - t5; // 13 + t5 = y1 + z1; // 14 + x3 = y2 + z2; // 15 - z3 = b1 * t2; // 19 - x3 = y3 - z3; // 20 - z3 = x3 + x3; // 21 + t5 = t5 * x3; // 16 + x3 = t1 + t2; // 17 + t5 = t5 - x3; // 18 - x3 = x3 + z3; // 22 - z3 = t1 - x3; // 23 - x3 = t1 + x3; // 24 + z3 = a1 * t4; // 19 + x3 = b3 * t2; // 20 + z3 = x3 + z3; // 21 - y3 = b1 * y3; // 25 - t1 = t2 + t2; // 26 - t2 = t1 + t2; // 27 + x3 = t1 - z3; // 22 + z3 = t1 + z3; // 23 + y3 = x3 * z3; // 24 - y3 = y3 - t2; // 28 - y3 = y3 - t0; // 29 - t1 = y3 + y3; // 30 + t1 = t0 + t0; // 25 + t1 = t1 + t0; // 26 + t2 = a1 * t2; // 27 - y3 = t1 + y3; // 31 - t1 = t0 + t0; // 32 - t0 = t1 + t0; // 33 + t4 = b3 * t4; // 28 + t1 = t1 + t2; // 29 + t2 = t0 - t2; // 30 - t0 = t0 - t2; // 34 - t1 = t4 * y3; // 35 - t2 = t0 * y3; // 36 + t2 = a1 * t2; // 31 + t4 = t4 + t2; // 32 + t0 = t1 * t4; // 33 - y3 = x3 * z3; // 37 - y3 = y3 + t2; // 38 - x3 = t3 * x3; // 39 + y3 = y3 + t0; // 34 + t0 = t5 * t4; // 35 + x3 = t3 * x3; // 36 - x3 = x3 - t1; // 40 - z3 = t4 * z3; // 41 - t1 = t3 * t0; // 42 + x3 = x3 - t0; // 37 + t0 = t3 * t1; // 38 + z3 = t5 * z3; // 39 - z3 = z3 + t1; // 43 - } else { - // Algorithm 1 - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t2 = z1 * z2; // 3 + z3 = z3 + t0; // 40 + } + CurveKind::Minus3 => { + // Algorithm 4 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 + + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 - t3 = x1 + y1; // 4 - t4 = x2 + y2; // 5 - t3 = t3 * t4; // 6 + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = y1 + z1; // 9 - t4 = t0 + t1; // 7 - t3 = t3 - t4; // 8 - t4 = x1 + z1; // 9 + x3 = y2 + z2; // 10 + t4 = t4 * x3; // 11 + x3 = t1 + t2; // 12 - t5 = x2 + z2; // 10 - t4 = t4 * t5; // 11 - t5 = t0 + t2; // 12 + t4 = t4 - x3; // 13 + x3 = x1 + z1; // 14 + y3 = x2 + z2; // 15 - t4 = t4 - t5; // 13 - t5 = y1 + z1; // 14 - x3 = y2 + z2; // 15 + x3 = x3 * y3; // 16 + y3 = t0 + t2; // 17 + y3 = x3 - y3; // 18 - t5 = t5 * x3; // 16 - x3 = t1 + t2; // 17 - t5 = t5 - x3; // 18 + z3 = b1 * t2; // 19 + x3 = y3 - z3; // 20 + z3 = x3 + x3; // 21 - z3 = a1 * t4; // 19 - x3 = b3 * t2; // 20 - z3 = x3 + z3; // 21 + x3 = x3 + z3; // 22 + z3 = t1 - x3; // 23 + x3 = t1 + x3; // 24 - x3 = t1 - z3; // 22 - z3 = t1 + z3; // 23 - y3 = x3 * z3; // 24 + y3 = b1 * y3; // 25 + t1 = t2 + t2; // 26 + t2 = t1 + t2; // 27 - t1 = t0 + t0; // 25 - t1 = t1 + t0; // 26 - t2 = a1 * t2; // 27 + y3 = y3 - t2; // 28 + y3 = y3 - t0; // 29 + t1 = y3 + y3; // 30 - t4 = b3 * t4; // 28 - t1 = t1 + t2; // 29 - t2 = t0 - t2; // 30 - - t2 = a1 * t2; // 31 - t4 = t4 + t2; // 32 - t0 = t1 * t4; // 33 + y3 = t1 + y3; // 31 + t1 = t0 + t0; // 32 + t0 = t1 + t0; // 33 - y3 = y3 + t0; // 34 - t0 = t5 * t4; // 35 - x3 = t3 * x3; // 36 + t0 = t0 - t2; // 34 + t1 = t4 * y3; // 35 + t2 = t0 * y3; // 36 - x3 = x3 - t0; // 37 - t0 = t3 * t1; // 38 - z3 = t5 * z3; // 39 + y3 = x3 * z3; // 37 + y3 = y3 + t2; // 38 + x3 = t3 * x3; // 39 - z3 = z3 + t0; // 40 + x3 = x3 - t1; // 40 + z3 = t4 * z3; // 41 + t1 = t3 * t0; // 42 + + z3 = z3 + t1; // 43 + } + CurveKind::Zero => { + // Algorithm 7 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t2 = z1 * z2; // 3 + + t3 = x1 + y1; // 4 + t4 = x2 + y2; // 5 + t3 = t3 * t4; // 6 + + t4 = t0 + t1; // 7 + t3 = t3 - t4; // 8 + t4 = y1 + z1; // 9 + + x3 = y2 + z2; // 10 + t4 = t4 * x3; // 11 + x3 = t1 + t2; // 12 + + t4 = t4 - x3; // 13 + x3 = x1 + z1; // 14 + y3 = x2 + z2; // 15 + + x3 = x3 * y3; // 16 + y3 = t0 + t2; // 17 + y3 = x3 - y3; // 18 + + x3 = t0 + t0; // 19 + t0 = x3 + t0; // 20 + t2 = b3 * t2; // 21 + + z3 = t1 + t2; // 22 + t1 = t1 - t2; // 23 + y3 = b3 * y3; // 24 + + x3 = t4 * y3; // 25 + t2 = t3 * t1; // 26 + x3 = t2 - x3; // 27 + + y3 = y3 * t0; // 28 + t1 = t1 * z3; // 29 + y3 = t1 + y3; // 30 + + t0 = t0 * t3; // 31 + z3 = z3 * t4; // 32 + z3 = z3 + t0; // 33 + } } ProjectivePoint { x: x3, y: y3, z: z3 } } @@ -298,100 +349,140 @@ impl ProjectivePoint let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); let (mut x3, mut y3, mut z3); - if C::A_IS_MINUS_3 { - // Algorithm 5 - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t3 = x2 + y2; // 3 - - t4 = x1 + y1; // 4 - t3 = t3 * t4; // 5 - t4 = t0 + t1; // 6 - - t3 = t3 - t4; // 7 - t4 = y2 * z1; // 8 - t4 = t4 + y1; // 9 - - y3 = x2 * z1; // 10 - y3 = y3 + x1; // 11 - z3 = b1 * z1; // 12 - - x3 = y3 - z3; // 13 - z3 = x3 + x3; // 14 - x3 = x3 + z3; // 15 - - z3 = t1 - x3; // 16 - x3 = t1 + x3; // 17 - y3 = b1 * y3; // 18 - - t1 = z1 + z1; // 19 - t2 = t1 + z1; // 20 - y3 = y3 - t2; // 21 - - y3 = y3 - t0; // 22 - t1 = y3 + y3; // 23 - y3 = t1 + y3; // 24 - - t1 = t0 + t0; // 25 - t0 = t1 + t0; // 26 - t0 = t0 - t2; // 27 - - t1 = t4 * y3; // 28 - t2 = t0 * y3; // 29 - y3 = x3 * z3; // 30 - - y3 = y3 + t2; // 31 - x3 = t3 * x3; // 32 - x3 = x3 - t1; // 33 - - z3 = t4 * z3; // 34 - t1 = t3 * t0; // 35 - z3 = z3 + t1; // 36 - } else { - // Algorithm 2 - t0 = x1 * x2; // 1 - t1 = y1 * y2; // 2 - t3 = x2 + y2; // 3 - - t4 = x1 + y1; // 4 - t3 = t3 * t4; // 5 - t4 = t0 + t1; // 6 - - t3 = t3 - t4; // 7 - t4 = x2 * z1; // 8 - t4 = t4 + x1; // 9 - - t5 = y2 * z1; // 10 - t5 = t5 + y1; // 11 - z3 = a1 * t4; // 12 - - x3 = b3 * z1; // 13 - z3 = x3 + z3; // 14 - x3 = t1 - z3; // 15 - - z3 = t1 + z3; // 16 - y3 = x3 * z3; // 17 - t1 = t0 + t0; // 18 - - t1 = t1 + t0; // 19 - t2 = a1 * z1; // 20 - t4 = b3 * t4; // 21 - - t1 = t1 + t2; // 22 - t2 = t0 - t2; // 23 - t2 = a1 * t2; // 24 - - t4 = t4 + t2; // 25 - t0 = t1 * t4; // 26 - y3 = y3 + t0; // 27 - - t0 = t5 * t4; // 28 - x3 = t3 * x3; // 29 - x3 = x3 - t0; // 30 - - t0 = t3 * t1; // 31 - z3 = t5 * z3; // 32 - z3 = z3 + t0; // 33 + match C::CURVE_KIND { + CurveKind::General => { + // Algorithm 2 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = x2 * z1; // 8 + t4 = t4 + x1; // 9 + + t5 = y2 * z1; // 10 + t5 = t5 + y1; // 11 + z3 = a1 * t4; // 12 + + x3 = b3 * z1; // 13 + z3 = x3 + z3; // 14 + x3 = t1 - z3; // 15 + + z3 = t1 + z3; // 16 + y3 = x3 * z3; // 17 + t1 = t0 + t0; // 18 + + t1 = t1 + t0; // 19 + t2 = a1 * z1; // 20 + t4 = b3 * t4; // 21 + + t1 = t1 + t2; // 22 + t2 = t0 - t2; // 23 + t2 = a1 * t2; // 24 + + t4 = t4 + t2; // 25 + t0 = t1 * t4; // 26 + y3 = y3 + t0; // 27 + + t0 = t5 * t4; // 28 + x3 = t3 * x3; // 29 + x3 = x3 - t0; // 30 + + t0 = t3 * t1; // 31 + z3 = t5 * z3; // 32 + z3 = z3 + t0; // 33 + } + CurveKind::Minus3 => { + // Algorithm 5 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = y2 * z1; // 8 + t4 = t4 + y1; // 9 + + y3 = x2 * z1; // 10 + y3 = y3 + x1; // 11 + z3 = b1 * z1; // 12 + + x3 = y3 - z3; // 13 + z3 = x3 + x3; // 14 + x3 = x3 + z3; // 15 + + z3 = t1 - x3; // 16 + x3 = t1 + x3; // 17 + y3 = b1 * y3; // 18 + + t1 = z1 + z1; // 19 + t2 = t1 + z1; // 20 + y3 = y3 - t2; // 21 + + y3 = y3 - t0; // 22 + t1 = y3 + y3; // 23 + y3 = t1 + y3; // 24 + + t1 = t0 + t0; // 25 + t0 = t1 + t0; // 26 + t0 = t0 - t2; // 27 + + t1 = t4 * y3; // 28 + t2 = t0 * y3; // 29 + y3 = x3 * z3; // 30 + + y3 = y3 + t2; // 31 + x3 = t3 * x3; // 32 + x3 = x3 - t1; // 33 + + z3 = t4 * z3; // 34 + t1 = t3 * t0; // 35 + z3 = z3 + t1; // 36 + } + CurveKind::Zero => { + // Algorithm 8 + t0 = x1 * x2; // 1 + t1 = y1 * y2; // 2 + t3 = x2 + y2; // 3 + + t4 = x1 + y1; // 4 + t3 = t3 * t4; // 5 + t4 = t0 + t1; // 6 + + t3 = t3 - t4; // 7 + t4 = y2 * z1; // 8 + t4 = t4 + y1; // 9 + + y3 = x2 * z1; // 10 + y3 = y3 + x1; // 11 + x3 = t0 + t0; // 12 + + t0 = x3 + t0; // 13 + t2 = b3 * z1; // 14 + z3 = t1 + t2; // 15 + + t1 = t1 - t2; // 16 + y3 = b3 * y3; // 17 + x3 = t4 * y3; // 18 + + t2 = t3 * t1; // 19 + x3 = t2 - x3; // 20 + y3 = y3 * t0; // 21 + + t1 = t1 * z3; // 22 + y3 = t1 + y3; // 23 + t0 = t0 * t3; // 24 + + z3 = z3 * t4; // 25 + z3 = z3 + t0; // 26 + } } ProjectivePoint { x: x3, y: y3, z: z3 } } @@ -407,98 +498,127 @@ impl ProjectivePoint let b3 = C::B + C::B + C::B; let a1 = C::A; - let (mut t0, t1, mut t2, mut t3); + let (mut t0, mut t1, mut t2, mut t3); let (mut x3, mut y3, mut z3); - if C::A_IS_MINUS_3 { - // Algorithm 6 - t0 = x1 * x1; // 1 - t1 = y1 * y1; // 2 - t2 = z1 * z1; // 3 - - t3 = x1 * y1; // 4 - t3 = t3 + t3; // 5 - z3 = x1 * z1; // 6 - - z3 = z3 + z3; // 7 - y3 = b1 * t2; // 8 - y3 = y3 - z3; // 9 - - x3 = y3 + y3; // 10 - y3 = x3 + y3; // 11 - x3 = t1 - y3; // 12 - - y3 = t1 + y3; // 13 - y3 = x3 * y3; // 14 - x3 = x3 * t3; // 15 - - t3 = t2 + t2; // 16 - t2 = t2 + t3; // 17 - z3 = b1 * z3; // 18 - - z3 = z3 - t2; // 19 - z3 = z3 - t0; // 20 - t3 = z3 + z3; // 21 - - z3 = z3 + t3; // 22 - t3 = t0 + t0; // 23 - t0 = t3 + t0; // 24 - - t0 = t0 - t2; // 25 - t0 = t0 * z3; // 26 - y3 = y3 + t0; // 27 - - t0 = y1 * z1; // 28 - t0 = t0 + t0; // 29 - z3 = t0 * z3; // 30 - - x3 = x3 - z3; // 31 - z3 = t0 * t1; // 32 - z3 = z3 + z3; // 33 - - z3 = z3 + z3; // 34 - } else { - // Algorithm 3 - t0 = x1 * x1; // 1 - t1 = y1 * y1; // 2 - t2 = z1 * z1; // 3 - - t3 = x1 * y1; // 4 - t3 = t3 + t3; // 5 - z3 = x1 * z1; // 6 - - z3 = z3 + z3; // 7 - x3 = a1 * z3; // 8 - y3 = b3 * t2; // 9 - - y3 = x3 + y3; // 10 - x3 = t1 - y3; // 11 - y3 = t1 + y3; // 12 - - y3 = x3 * y3; // 13 - x3 = t3 * x3; // 14 - z3 = b3 * z3; // 15 - - t2 = a1 * t2; // 16 - t3 = t0 - t2; // 17 - t3 = a1 * t3; // 18 - - t3 = t3 + z3; // 19 - z3 = t0 + t0; // 20 - t0 = z3 + t0; // 21 - - t0 = t0 + t2; // 22 - t0 = t0 * t3; // 23 - y3 = y3 + t0; // 24 - - t2 = y1 * z1; // 25 - t2 = t2 + t2; // 26 - t0 = t2 * t3; // 27 - - x3 = x3 - t0; // 28 - z3 = t2 * t1; // 29 - z3 = z3 + z3; // 30 - - z3 = z3 + z3; // 31 + match C::CURVE_KIND { + CurveKind::General => { + // Algorithm 3 + t0 = x1 * x1; // 1 + t1 = y1 * y1; // 2 + t2 = z1 * z1; // 3 + + t3 = x1 * y1; // 4 + t3 = t3 + t3; // 5 + z3 = x1 * z1; // 6 + + z3 = z3 + z3; // 7 + x3 = a1 * z3; // 8 + y3 = b3 * t2; // 9 + + y3 = x3 + y3; // 10 + x3 = t1 - y3; // 11 + y3 = t1 + y3; // 12 + + y3 = x3 * y3; // 13 + x3 = t3 * x3; // 14 + z3 = b3 * z3; // 15 + + t2 = a1 * t2; // 16 + t3 = t0 - t2; // 17 + t3 = a1 * t3; // 18 + + t3 = t3 + z3; // 19 + z3 = t0 + t0; // 20 + t0 = z3 + t0; // 21 + + t0 = t0 + t2; // 22 + t0 = t0 * t3; // 23 + y3 = y3 + t0; // 24 + + t2 = y1 * z1; // 25 + t2 = t2 + t2; // 26 + t0 = t2 * t3; // 27 + + x3 = x3 - t0; // 28 + z3 = t2 * t1; // 29 + z3 = z3 + z3; // 30 + + z3 = z3 + z3; // 31 + } + CurveKind::Minus3 => { + // Algorithm 6 + t0 = x1 * x1; // 1 + t1 = y1 * y1; // 2 + t2 = z1 * z1; // 3 + + t3 = x1 * y1; // 4 + t3 = t3 + t3; // 5 + z3 = x1 * z1; // 6 + + z3 = z3 + z3; // 7 + y3 = b1 * t2; // 8 + y3 = y3 - z3; // 9 + + x3 = y3 + y3; // 10 + y3 = x3 + y3; // 11 + x3 = t1 - y3; // 12 + + y3 = t1 + y3; // 13 + y3 = x3 * y3; // 14 + x3 = x3 * t3; // 15 + + t3 = t2 + t2; // 16 + t2 = t2 + t3; // 17 + z3 = b1 * z3; // 18 + + z3 = z3 - t2; // 19 + z3 = z3 - t0; // 20 + t3 = z3 + z3; // 21 + + z3 = z3 + t3; // 22 + t3 = t0 + t0; // 23 + t0 = t3 + t0; // 24 + + t0 = t0 - t2; // 25 + t0 = t0 * z3; // 26 + y3 = y3 + t0; // 27 + + t0 = y1 * z1; // 28 + t0 = t0 + t0; // 29 + z3 = t0 * z3; // 30 + + x3 = x3 - z3; // 31 + z3 = t0 * t1; // 32 + z3 = z3 + z3; // 33 + + z3 = z3 + z3; // 34 + } + CurveKind::Zero => { + // Algorithm 9 + t0 = y1 * y1; // 1 + z3 = t0 + t0; // 2 + z3 = z3 + z3; // 3 + + z3 = z3 + z3; // 4 + t1 = y1 * z1; // 5 + t2 = z1 * z1; // 6 + + t2 = b3 * t2; // 7 + x3 = t2 * z3; // 8 + y3 = t0 + t2; // 9 + + z3 = t1 * z3; // 10 + t1 = t2 + t2; // 11 + t2 = t1 + t2; // 12 + + t0 = t0 - t2; // 13 + y3 = t0 * y3; // 14 + y3 = x3 + y3; // 15 + + t1 = x1 * y1; // 16 + x3 = t0 * t1; // 17 + x3 = x3 + x3; // 18 + } } ProjectivePoint { x: x3, y: y3, z: z3 } } From b1434eca53a7e93a41a5e74f7953f45fbe964309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:01:44 +0300 Subject: [PATCH 10/20] add B3 constant --- weierstrass/src/lib.rs | 2 ++ weierstrass/src/projective.rs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 4df20027a..9c74d00f2 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -64,6 +64,8 @@ pub trait WeirstrassCurve const A: FieldElement; const B: FieldElement; + /// 3*B + const B3: FieldElement; const CURVE_KIND: CurveKind; const MODULUS_P: Words; /// p - 2 diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 9dbd8da46..103dbe0a9 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -160,7 +160,7 @@ impl ProjectivePoint let &ProjectivePoint { x: x2, y: y2, z: z2 } = other; let b1 = C::B; - let b3 = C::B + C::B + C::B; + let b3 = C::B3; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); @@ -343,7 +343,7 @@ impl ProjectivePoint let &AffinePoint { x: x2, y: y2, .. } = other; let b1 = C::B; - let b3 = C::B + C::B + C::B; + let b3 = C::B; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3, mut t4, mut t5); @@ -495,7 +495,7 @@ impl ProjectivePoint let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; let b1 = C::B; - let b3 = C::B + C::B + C::B; + let b3 = C::B3const B: FieldElement;; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3); From c29b429457f36230d839b4fd010fb6bbc88670d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:03:59 +0300 Subject: [PATCH 11/20] fix typo --- weierstrass/src/projective.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 103dbe0a9..8ac2e71e4 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -495,7 +495,7 @@ impl ProjectivePoint let &ProjectivePoint { x: x1, y: y1, z: z1 } = self; let b1 = C::B; - let b3 = C::B3const B: FieldElement;; + let b3 = C::B3; let a1 = C::A; let (mut t0, mut t1, mut t2, mut t3); From 605528b909fd14e0613d6df6058dcbb1d8720f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:18:24 +0300 Subject: [PATCH 12/20] specify curve size in bytes --- weierstrass/src/affine.rs | 42 ++++++++--------- weierstrass/src/field.rs | 68 +++++++++++++-------------- weierstrass/src/lib.rs | 30 ++++++------ weierstrass/src/projective.rs | 86 +++++++++++++++++------------------ weierstrass/src/scalar.rs | 68 +++++++++++++-------------- 5 files changed, 145 insertions(+), 149 deletions(-) diff --git a/weierstrass/src/affine.rs b/weierstrass/src/affine.rs index 2533f76af..50c84b593 100644 --- a/weierstrass/src/affine.rs +++ b/weierstrass/src/affine.rs @@ -1,12 +1,12 @@ -use core::ops::{Mul, Neg}; -use generic_array::{ArrayLength, typenum::U1}; +use core::ops::{Mul, Neg, Shl}; +use generic_array::{ArrayLength, typenum::{B1, U1}}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use core::ops::Add; use crate::{ WeirstrassCurve, Word, Words, WordsLen, - WideWordsLen, + DoubleWordsLen, WordsBytesLen, WordsP1Len, }; @@ -18,8 +18,8 @@ use crate::field::FieldElement; pub struct AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -32,8 +32,8 @@ pub struct AffinePoint impl AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -65,8 +65,8 @@ impl AffinePoint impl ConditionallySelectable for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -83,8 +83,8 @@ impl ConditionallySelectable for AffinePoint impl ConstantTimeEq for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -99,8 +99,8 @@ impl ConstantTimeEq for AffinePoint impl PartialEq for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -113,8 +113,8 @@ impl PartialEq for AffinePoint impl Eq for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -123,8 +123,8 @@ impl Eq for AffinePoint impl Mul> for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -139,8 +139,8 @@ impl Mul> for AffinePoint impl Neg for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -160,8 +160,8 @@ impl Neg for AffinePoint impl Zeroize for AffinePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs index e9dbf5d75..2c3969cc3 100644 --- a/weierstrass/src/field.rs +++ b/weierstrass/src/field.rs @@ -1,15 +1,15 @@ use core::{fmt, mem}; use core::convert::TryInto; -use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg}; +use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; use generic_array::ArrayLength; -use generic_array::typenum::{U1, Unsigned}; +use generic_array::typenum::{B1, U1, Unsigned}; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use rand_core::{RngCore, CryptoRng}; use crate::{ WeirstrassCurve, Word, WordWidth, Words, WordsLen, - WideWords, WideWordsLen, + DoubleWords, DoubleWordsLen, WordsBytes, WordsBytesLen, WordsP1, WordsP1Len, random_word @@ -20,8 +20,8 @@ use crate::utils::{adc, sbb, mac}; pub struct FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -32,8 +32,8 @@ pub struct FieldElement impl FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -54,7 +54,7 @@ impl FieldElement pub fn generate(mut rng: impl CryptoRng + RngCore) -> Self { // We reduce a random value with a double length, which results in a // negligible bias from the uniform distribution. - let mut t = WideWords::::default(); + let mut t = DoubleWords::::default(); t.iter_mut().for_each(|wt| *wt = random_word(&mut rng)); FieldElement::montgomery_reduce(t) } @@ -84,7 +84,7 @@ impl FieldElement /// Returns the SEC1 encoding of this field element. pub fn to_bytes(&self) -> WordsBytes { // Convert from Montgomery form to canonical form - let mut w = WideWords::::default(); + let mut w = DoubleWords::::default(); let n = self.words.len(); w[..n].copy_from_slice(&self.words); let t = Self::montgomery_reduce(w); @@ -154,8 +154,8 @@ impl FieldElement } /// Montgomery Reduction - fn montgomery_reduce(v: WideWords) -> Self { - // `WideWords` length is always multiple of 2 + fn montgomery_reduce(v: DoubleWords) -> Self { + // `DoubleWords` length is always multiple of 2 let n = v.len() / 2; let mut r = WordsP1::::default(); r[..n].copy_from_slice(&v[..n]); @@ -176,7 +176,7 @@ impl FieldElement /// Returns self * rhs mod p pub fn mul(&self, rhs: &Self) -> Self { - let mut w = WideWords::::default(); + let mut w = DoubleWords::::default(); let n = rhs.words.len(); // Schoolbook multiplication. @@ -238,8 +238,8 @@ impl FieldElement impl fmt::UpperHex for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -255,8 +255,8 @@ impl fmt::UpperHex for FieldElement impl ConditionallySelectable for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -274,8 +274,8 @@ impl ConditionallySelectable for FieldElement impl ConstantTimeEq for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -292,8 +292,8 @@ impl ConstantTimeEq for FieldElement impl PartialEq for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -306,8 +306,8 @@ impl PartialEq for FieldElement impl Add> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -323,8 +323,8 @@ impl Add> for FieldElement impl AddAssign> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -338,8 +338,8 @@ impl AddAssign> for FieldElement impl Sub> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -355,8 +355,8 @@ impl Sub> for FieldElement impl SubAssign> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -371,8 +371,8 @@ impl SubAssign> for FieldElement impl Mul> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -388,8 +388,8 @@ impl Mul> for FieldElement impl MulAssign> for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -403,8 +403,8 @@ impl MulAssign> for FieldElement impl Neg for FieldElement where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 9c74d00f2..dc73eec6f 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -2,12 +2,12 @@ pub use {generic_array, subtle}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ self, - U1, U4, U8, + B1, U1, U2, Unsigned, - operator_aliases::{Sum, Quot}, + operator_aliases::{Sum, Quot, Double}, }; use rand_core::{RngCore, CryptoRng}; -use core::ops::{Div, Add}; +use core::ops::{Div, Add, Shl}; mod affine; mod field; @@ -23,27 +23,23 @@ pub use projective::ProjectivePoint; // TODO: add cfgs for other word sizes pub type Word = u64; type DoubleWord = u128; -type WordWidth = typenum::U64; -/// Divisor for getting number of words in the wider buffer, it's equal -/// to `Quot`, but to simplify trait bounds we use an explicit -/// value -type WideWordsDiv = typenum::U32; +type WordWidth = typenum::U8; fn random_word(mut rng: impl CryptoRng + RngCore) -> Word { rng.next_u64() } -pub type WordsLen = Quot<::Bits, WordWidth>; +pub type WordsLen = Quot<::Size, WordWidth>; pub type Words = GenericArray>; -pub type WordsBytesLen = Quot<::Bits, U8>; +pub type WordsBytesLen = ::Size; pub type WordsBytes = GenericArray>; -pub type DoubleWordsBytesLen = Quot<::Bits, U4>; -pub type DoubleWordsBytes = GenericArray>; pub type WordsP1Len = Sum, U1>; pub type WordsP1 = GenericArray>; -pub type WideWordsLen = Quot<::Bits, WideWordsDiv>; -pub type WideWords = GenericArray>; +pub type DoubleWordsLen = Double>; +pub type DoubleWords = GenericArray>; +pub type DoubleWordsBytesLen = Double<::Size>; +pub type DoubleWordsBytes = GenericArray>; pub enum CurveKind { General, @@ -54,13 +50,13 @@ pub enum CurveKind { pub trait WeirstrassCurve where Self: Sized + Copy + Default, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, { - type Bits: Unsigned + Div + Div + Div + Div; + type Size: Unsigned + Div + Div; const A: FieldElement; const B: FieldElement; diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 8ac2e71e4..6ce3647b6 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -1,13 +1,13 @@ -use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign, Shl}; use core::iter::Sum; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -use generic_array::{ArrayLength, typenum::{U1, Unsigned}}; +use generic_array::{ArrayLength, typenum::{B1, U1, Unsigned}}; use crate::{ WeirstrassCurve, CurveKind, Word, WordWidth, Words, WordsLen, - WideWordsLen, + DoubleWordsLen, WordsBytesLen, WordsP1Len, }; @@ -20,8 +20,8 @@ use crate::scalar::Scalar; pub struct ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -34,8 +34,8 @@ pub struct ProjectivePoint impl From> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -53,8 +53,8 @@ impl From> for ProjectivePoint impl ConditionallySelectable for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -71,8 +71,8 @@ impl ConditionallySelectable for ProjectivePoint impl ConstantTimeEq for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -85,8 +85,8 @@ impl ConstantTimeEq for ProjectivePoint impl PartialEq for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -99,8 +99,8 @@ impl PartialEq for ProjectivePoint impl Eq for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -109,8 +109,8 @@ impl Eq for ProjectivePoint impl ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -652,8 +652,8 @@ impl ProjectivePoint impl Default for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -666,8 +666,8 @@ impl Default for ProjectivePoint impl Add for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -682,8 +682,8 @@ impl Add for ProjectivePoint impl AddAssign for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -696,8 +696,8 @@ impl AddAssign for ProjectivePoint impl Add> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -712,8 +712,8 @@ impl Add> for ProjectivePoint impl AddAssign> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -726,8 +726,8 @@ impl AddAssign> for ProjectivePoint impl Sum for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -740,8 +740,8 @@ impl Sum for ProjectivePoint impl Sub for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -756,8 +756,8 @@ impl Sub for ProjectivePoint impl SubAssign for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -770,8 +770,8 @@ impl SubAssign for ProjectivePoint impl Sub> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -786,8 +786,8 @@ impl Sub> for ProjectivePoint impl SubAssign> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -800,8 +800,8 @@ impl SubAssign> for ProjectivePoint impl Mul> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -816,8 +816,8 @@ impl Mul> for ProjectivePoint impl MulAssign> for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -830,8 +830,8 @@ impl MulAssign> for ProjectivePoint impl Neg for ProjectivePoint where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 2a62e6145..a7ff676f1 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -1,13 +1,13 @@ -use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg}; +use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; use core::{fmt, mem}; use core::convert::TryInto; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use generic_array::ArrayLength; -use generic_array::typenum::{U1, Unsigned}; +use generic_array::typenum::{B1, U1, Unsigned}; use super::{ WeirstrassCurve, Word, WordWidth, Words, WordsLen, - WideWordsLen, WideWords, + DoubleWordsLen, DoubleWords, WordsBytesLen, WordsBytes, WordsP1Len, WordsP1, }; @@ -17,8 +17,8 @@ use crate::utils::{adc, sbb, mac}; pub struct Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -29,8 +29,8 @@ pub struct Scalar impl Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -157,8 +157,8 @@ impl Scalar /// http://cacr.uwaterloo.ca/hac/about/chap14.pdf #[inline] #[allow(clippy::too_many_arguments)] - fn barrett_reduce(a: WideWords) -> Self { - // `WideWords` length is always multiple of 2 + fn barrett_reduce(a: DoubleWords) -> Self { + // `DoubleWords` length is always multiple of 2 let k = a.len() / 2; let mut q1 = WordsP1::::default(); q1.copy_from_slice(&a[k-1..]); @@ -203,8 +203,8 @@ impl Scalar fn sub_mod_if_necessary(r: &mut WordsP1) where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -244,7 +244,7 @@ impl Scalar /// Returns self * rhs mod n pub fn mul(&self, rhs: &Self) -> Self { - let mut w = WideWords::::default(); + let mut w = DoubleWords::::default(); let n = rhs.words.len(); // Schoolbook multiplication. @@ -343,8 +343,8 @@ impl Scalar impl fmt::UpperHex for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -360,8 +360,8 @@ impl fmt::UpperHex for Scalar impl ConditionallySelectable for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -379,8 +379,8 @@ impl ConditionallySelectable for Scalar impl ConstantTimeEq for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -397,8 +397,8 @@ impl ConstantTimeEq for Scalar impl PartialEq for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -411,8 +411,8 @@ impl PartialEq for Scalar impl Add> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -428,8 +428,8 @@ impl Add> for Scalar impl AddAssign> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -443,8 +443,8 @@ impl AddAssign> for Scalar impl Sub> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -460,8 +460,8 @@ impl Sub> for Scalar impl SubAssign> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -476,8 +476,8 @@ impl SubAssign> for Scalar impl Mul> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -493,8 +493,8 @@ impl Mul> for Scalar impl MulAssign> for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, @@ -508,8 +508,8 @@ impl MulAssign> for Scalar impl Neg for Scalar where C: WeirstrassCurve, - WordsLen: ArrayLength + Add, - WideWordsLen: ArrayLength, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, WordsBytesLen: ArrayLength, Words: Copy, From c3f89a2a75354ba7f3093e2f9cca2bc60c60679c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:28:46 +0300 Subject: [PATCH 13/20] add #![no_std] --- weierstrass/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index dc73eec6f..982b25e6f 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -1,3 +1,4 @@ +#![no_std] pub use {generic_array, subtle}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ @@ -56,7 +57,7 @@ pub trait WeirstrassCurve WordsBytesLen: ArrayLength, Words: Copy, { - type Size: Unsigned + Div + Div; + type Size: Unsigned + Div + Div + Shl; const A: FieldElement; const B: FieldElement; From 7f8e7bf2ec5c182dc14a7e1bfe7d63eff5bbcb18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:34:35 +0300 Subject: [PATCH 14/20] fix trait name typo --- weierstrass/src/affine.rs | 20 ++++++++--------- weierstrass/src/field.rs | 28 +++++++++++------------ weierstrass/src/lib.rs | 8 +++---- weierstrass/src/projective.rs | 42 +++++++++++++++++------------------ weierstrass/src/scalar.rs | 30 ++++++++++++------------- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/weierstrass/src/affine.rs b/weierstrass/src/affine.rs index 50c84b593..b7758ee1e 100644 --- a/weierstrass/src/affine.rs +++ b/weierstrass/src/affine.rs @@ -4,7 +4,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use core::ops::Add; use crate::{ - WeirstrassCurve, Word, + WeierstrassCurve, Word, Words, WordsLen, DoubleWordsLen, WordsBytesLen, @@ -17,7 +17,7 @@ use crate::field::FieldElement; #[derive(Clone, Copy)] pub struct AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -31,7 +31,7 @@ pub struct AffinePoint impl AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -64,7 +64,7 @@ impl AffinePoint impl ConditionallySelectable for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -82,7 +82,7 @@ impl ConditionallySelectable for AffinePoint impl ConstantTimeEq for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -98,7 +98,7 @@ impl ConstantTimeEq for AffinePoint impl PartialEq for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -112,7 +112,7 @@ impl PartialEq for AffinePoint impl Eq for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -122,7 +122,7 @@ impl Eq for AffinePoint impl Mul> for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -138,7 +138,7 @@ impl Mul> for AffinePoint impl Neg for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -159,7 +159,7 @@ impl Neg for AffinePoint #[cfg(feature = "zeroize")] impl Zeroize for AffinePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs index 2c3969cc3..d7d5f0592 100644 --- a/weierstrass/src/field.rs +++ b/weierstrass/src/field.rs @@ -7,7 +7,7 @@ use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use rand_core::{RngCore, CryptoRng}; use crate::{ - WeirstrassCurve, Word, WordWidth, + WeierstrassCurve, Word, WordWidth, Words, WordsLen, DoubleWords, DoubleWordsLen, WordsBytes, WordsBytesLen, @@ -19,7 +19,7 @@ use crate::utils::{adc, sbb, mac}; #[derive(Default, Debug, Copy, Clone)] pub struct FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -31,7 +31,7 @@ pub struct FieldElement impl FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -237,7 +237,7 @@ impl FieldElement impl fmt::UpperHex for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -254,7 +254,7 @@ impl fmt::UpperHex for FieldElement impl ConditionallySelectable for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -273,7 +273,7 @@ impl ConditionallySelectable for FieldElement impl ConstantTimeEq for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -291,7 +291,7 @@ impl ConstantTimeEq for FieldElement impl PartialEq for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -305,7 +305,7 @@ impl PartialEq for FieldElement impl Add> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -322,7 +322,7 @@ impl Add> for FieldElement impl AddAssign> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -337,7 +337,7 @@ impl AddAssign> for FieldElement impl Sub> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -354,7 +354,7 @@ impl Sub> for FieldElement impl SubAssign> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -370,7 +370,7 @@ impl SubAssign> for FieldElement impl Mul> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -387,7 +387,7 @@ impl Mul> for FieldElement impl MulAssign> for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -402,7 +402,7 @@ impl MulAssign> for FieldElement impl Neg for FieldElement where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 982b25e6f..23f8cb3c4 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -29,9 +29,9 @@ fn random_word(mut rng: impl CryptoRng + RngCore) -> Word { rng.next_u64() } -pub type WordsLen = Quot<::Size, WordWidth>; +pub type WordsLen = Quot<::Size, WordWidth>; pub type Words = GenericArray>; -pub type WordsBytesLen = ::Size; +pub type WordsBytesLen = ::Size; pub type WordsBytes = GenericArray>; pub type WordsP1Len = Sum, U1>; @@ -39,7 +39,7 @@ pub type WordsP1 = GenericArray>; pub type DoubleWordsLen = Double>; pub type DoubleWords = GenericArray>; -pub type DoubleWordsBytesLen = Double<::Size>; +pub type DoubleWordsBytesLen = Double<::Size>; pub type DoubleWordsBytes = GenericArray>; pub enum CurveKind { @@ -48,7 +48,7 @@ pub enum CurveKind { Zero, } -pub trait WeirstrassCurve +pub trait WeierstrassCurve where Self: Sized + Copy + Default, WordsLen: ArrayLength + Add + Shl, diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 6ce3647b6..6f71956c3 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -4,7 +4,7 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; use generic_array::{ArrayLength, typenum::{B1, U1, Unsigned}}; use crate::{ - WeirstrassCurve, CurveKind, + WeierstrassCurve, CurveKind, Word, WordWidth, Words, WordsLen, DoubleWordsLen, @@ -19,7 +19,7 @@ use crate::scalar::Scalar; #[derive(Clone, Copy, Debug)] pub struct ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -33,7 +33,7 @@ pub struct ProjectivePoint impl From> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -52,7 +52,7 @@ impl From> for ProjectivePoint impl ConditionallySelectable for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -70,7 +70,7 @@ impl ConditionallySelectable for ProjectivePoint impl ConstantTimeEq for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -84,7 +84,7 @@ impl ConstantTimeEq for ProjectivePoint impl PartialEq for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -98,7 +98,7 @@ impl PartialEq for ProjectivePoint impl Eq for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -108,7 +108,7 @@ impl Eq for ProjectivePoint impl ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -651,7 +651,7 @@ impl ProjectivePoint impl Default for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -665,7 +665,7 @@ impl Default for ProjectivePoint impl Add for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -681,7 +681,7 @@ impl Add for ProjectivePoint impl AddAssign for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -695,7 +695,7 @@ impl AddAssign for ProjectivePoint impl Add> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -711,7 +711,7 @@ impl Add> for ProjectivePoint impl AddAssign> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -725,7 +725,7 @@ impl AddAssign> for ProjectivePoint impl Sum for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -739,7 +739,7 @@ impl Sum for ProjectivePoint impl Sub for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -755,7 +755,7 @@ impl Sub for ProjectivePoint impl SubAssign for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -769,7 +769,7 @@ impl SubAssign for ProjectivePoint impl Sub> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -785,7 +785,7 @@ impl Sub> for ProjectivePoint impl SubAssign> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -799,7 +799,7 @@ impl SubAssign> for ProjectivePoint impl Mul> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -815,7 +815,7 @@ impl Mul> for ProjectivePoint impl MulAssign> for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -829,7 +829,7 @@ impl MulAssign> for ProjectivePoint impl Neg for ProjectivePoint where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index a7ff676f1..3c7634470 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -6,7 +6,7 @@ use generic_array::ArrayLength; use generic_array::typenum::{B1, U1, Unsigned}; use super::{ - WeirstrassCurve, Word, WordWidth, Words, WordsLen, + WeierstrassCurve, Word, WordWidth, Words, WordsLen, DoubleWordsLen, DoubleWords, WordsBytesLen, WordsBytes, WordsP1Len, WordsP1, @@ -16,7 +16,7 @@ use crate::utils::{adc, sbb, mac}; #[derive(Default, Copy, Clone, Debug, Eq)] pub struct Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -28,7 +28,7 @@ pub struct Scalar impl Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -202,7 +202,7 @@ impl Scalar fn sub_mod_if_necessary(r: &mut WordsP1) where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -342,7 +342,7 @@ impl Scalar impl fmt::UpperHex for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -359,7 +359,7 @@ impl fmt::UpperHex for Scalar impl ConditionallySelectable for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -378,7 +378,7 @@ impl ConditionallySelectable for Scalar impl ConstantTimeEq for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -396,7 +396,7 @@ impl ConstantTimeEq for Scalar impl PartialEq for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -410,7 +410,7 @@ impl PartialEq for Scalar impl Add> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -427,7 +427,7 @@ impl Add> for Scalar impl AddAssign> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -442,7 +442,7 @@ impl AddAssign> for Scalar impl Sub> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -459,7 +459,7 @@ impl Sub> for Scalar impl SubAssign> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -475,7 +475,7 @@ impl SubAssign> for Scalar impl Mul> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -492,7 +492,7 @@ impl Mul> for Scalar impl MulAssign> for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, @@ -507,7 +507,7 @@ impl MulAssign> for Scalar impl Neg for Scalar where - C: WeirstrassCurve, + C: WeierstrassCurve, WordsLen: ArrayLength + Add + Shl, DoubleWordsLen: ArrayLength, WordsP1Len: ArrayLength, From 76e26a845c288ca54c8c7833b992cf327d72e298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 16 Oct 2020 20:59:11 +0300 Subject: [PATCH 15/20] fix loops --- weierstrass/src/field.rs | 6 +++--- weierstrass/src/lib.rs | 5 ++++- weierstrass/src/projective.rs | 6 +++--- weierstrass/src/scalar.rs | 20 +++++++++++++++----- weierstrass/src/utils.rs | 11 +++++------ 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs index d7d5f0592..d1f3c3950 100644 --- a/weierstrass/src/field.rs +++ b/weierstrass/src/field.rs @@ -2,12 +2,12 @@ use core::{fmt, mem}; use core::convert::TryInto; use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; use generic_array::ArrayLength; -use generic_array::typenum::{B1, U1, Unsigned}; +use generic_array::typenum::{B1, U1}; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use rand_core::{RngCore, CryptoRng}; use crate::{ - WeierstrassCurve, Word, WordWidth, + WeierstrassCurve, Word, WORD_WIDTH_BITS, Words, WordsLen, DoubleWords, DoubleWordsLen, WordsBytes, WordsBytesLen, @@ -205,7 +205,7 @@ impl FieldElement pub fn pow_vartime(&self, by: &Words) -> Self { let mut res = Self::one(); for e in by.iter().rev() { - for i in (0..WordWidth::USIZE).rev() { + for i in (0..WORD_WIDTH_BITS).rev() { res = res.square(); if ((*e >> i) & 1) == 1 { res = res.mul(*self); diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 23f8cb3c4..1e0f0ee67 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -1,4 +1,4 @@ -#![no_std] +// #![no_std] pub use {generic_array, subtle}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ @@ -29,6 +29,9 @@ fn random_word(mut rng: impl CryptoRng + RngCore) -> Word { rng.next_u64() } + +const WORD_WIDTH_BITS: usize = 8*WordWidth::USIZE; + pub type WordsLen = Quot<::Size, WordWidth>; pub type Words = GenericArray>; pub type WordsBytesLen = ::Size; diff --git a/weierstrass/src/projective.rs b/weierstrass/src/projective.rs index 6f71956c3..74b8527a7 100644 --- a/weierstrass/src/projective.rs +++ b/weierstrass/src/projective.rs @@ -1,11 +1,11 @@ use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign, Shl}; use core::iter::Sum; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -use generic_array::{ArrayLength, typenum::{B1, U1, Unsigned}}; +use generic_array::{ArrayLength, typenum::{B1, U1}}; use crate::{ WeierstrassCurve, CurveKind, - Word, WordWidth, + Word, WORD_WIDTH_BITS, Words, WordsLen, DoubleWordsLen, WordsBytesLen, @@ -638,7 +638,7 @@ impl ProjectivePoint let mut ret = ProjectivePoint::identity(); for word in k.words.iter().rev() { - for i in (0..WordWidth::USIZE).rev() { + for i in (0..WORD_WIDTH_BITS).rev() { ret = ret.double(); let choice = ((word >> i) & (1 as Word)) as u8; ret.conditional_assign(&(ret + *self), Choice::from(choice)); diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 3c7634470..926e113b9 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -2,11 +2,10 @@ use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; use core::{fmt, mem}; use core::convert::TryInto; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; -use generic_array::ArrayLength; -use generic_array::typenum::{B1, U1, Unsigned}; +use generic_array::{ArrayLength, typenum::{B1, U1}}; use super::{ - WeierstrassCurve, Word, WordWidth, Words, WordsLen, + WeierstrassCurve, Word, WORD_WIDTH_BITS, Words, WordsLen, DoubleWordsLen, DoubleWords, WordsBytesLen, WordsBytes, WordsP1Len, WordsP1, @@ -271,9 +270,8 @@ impl Scalar /// If the exponent is fixed, this operation is effectively constant time. pub fn pow_vartime(&self, by: &Words) -> Self { let mut res = Self::one(); - let n = WordWidth::USIZE; for e in by.iter().rev() { - for i in (0..n).rev() { + for i in (0..WORD_WIDTH_BITS).rev() { res = res.square(); if ((*e >> i) & 1) == 1 { res *= *self; @@ -327,13 +325,25 @@ impl Scalar *wm = Word::from_be_bytes(chunk.try_into().unwrap()); } + for w in words.iter().rev() { + print!("{:016X}", w); + } + println!(); + + for w in C::MODULUS_Q.iter().rev() { + print!("{:016X}", w); + } + println!(); + // If w is in the range [0, n) then w - n will overflow, resulting // in a borrow value of 2^64 - 1. let mut borrow = Word::default(); for (&w, &wm) in words.iter().zip(C::MODULUS_Q.iter()) { borrow = sbb(w, wm, borrow).1; + println!("{:016X}", borrow); } let is_some = (borrow as u8) & 1; + println!("========"); CtOption::new(Self { words }, Choice::from(is_some)).into() } diff --git a/weierstrass/src/utils.rs b/weierstrass/src/utils.rs index 5f7dd9aaf..8537bc9cb 100644 --- a/weierstrass/src/utils.rs +++ b/weierstrass/src/utils.rs @@ -1,20 +1,19 @@ -use generic_array::typenum::Unsigned; -use crate::{DoubleWord, Word, WordWidth}; +use crate::{DoubleWord, Word, WORD_WIDTH_BITS}; /// Computes `a + b + carry`, returning the result along with the new carry. #[inline(always)] pub(crate) const fn adc(a: Word, b: Word, carry: Word) -> (Word, Word) { let ret = (a as DoubleWord) + (b as DoubleWord) + (carry as DoubleWord); - (ret as Word, (ret >> WordWidth::USIZE) as Word) + (ret as Word, (ret >> WORD_WIDTH_BITS) as Word) } /// Computes `a - (b + borrow)`, returning the result along with the new borrow. #[inline(always)] pub(crate) const fn sbb(a: Word, b: Word, borrow: Word) -> (Word, Word) { let (a, b) = (a as DoubleWord, b as DoubleWord); - let t = (borrow >> (WordWidth::USIZE - 1)) as DoubleWord; + let t = (borrow >> (WORD_WIDTH_BITS - 1)) as DoubleWord; let ret = a.wrapping_sub(b + t); - (ret as Word, (ret >> WordWidth::USIZE) as Word) + (ret as Word, (ret >> WORD_WIDTH_BITS) as Word) } /// Computes `a + (b * c) + carry`, returning the result along with the new carry. @@ -22,5 +21,5 @@ pub(crate) const fn sbb(a: Word, b: Word, borrow: Word) -> (Word, Word) { pub(crate) const fn mac(a: Word, b: Word, c: Word, carry: Word) -> (Word, Word) { let (a, b, c) = (a as DoubleWord, b as DoubleWord, c as DoubleWord); let ret = a + b * c + (carry as DoubleWord); - (ret as Word, (ret >> WordWidth::USIZE) as Word) + (ret as Word, (ret >> WORD_WIDTH_BITS) as Word) } From 7de4270dc86296b1334947892f4f2c0ecc805fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 23 Oct 2020 06:39:27 +0300 Subject: [PATCH 16/20] remove printlns, return no_std --- weierstrass/src/lib.rs | 2 +- weierstrass/src/scalar.rs | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 1e0f0ee67..d1814de53 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -1,4 +1,4 @@ -// #![no_std] +#![no_std] pub use {generic_array, subtle}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 926e113b9..9c106b969 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -325,25 +325,13 @@ impl Scalar *wm = Word::from_be_bytes(chunk.try_into().unwrap()); } - for w in words.iter().rev() { - print!("{:016X}", w); - } - println!(); - - for w in C::MODULUS_Q.iter().rev() { - print!("{:016X}", w); - } - println!(); - // If w is in the range [0, n) then w - n will overflow, resulting // in a borrow value of 2^64 - 1. let mut borrow = Word::default(); for (&w, &wm) in words.iter().zip(C::MODULUS_Q.iter()) { borrow = sbb(w, wm, borrow).1; - println!("{:016X}", borrow); } let is_some = (borrow as u8) & 1; - println!("========"); CtOption::new(Self { words }, Choice::from(is_some)).into() } From 1c82455b5fe25803939065405b0fd1c543ec1f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Tue, 10 Nov 2020 12:57:55 +0300 Subject: [PATCH 17/20] disable default features --- weierstrass/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/weierstrass/Cargo.toml b/weierstrass/Cargo.toml index de36b39b8..534fde708 100644 --- a/weierstrass/Cargo.toml +++ b/weierstrass/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] generic-array = "0.14" -subtle = "2.3" -rand_core = "0.5" +subtle = { version = "2.3", default-features = false } +rand_core = { version = "0.5", default-features = false } biguint-literal = { git = "https://github.com/RustCrypto/utils", branch = "biguint" } hex-literal = "0.3" From 4b3036b248b06ebd0d641abfbd0fbee249d4cfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Wed, 2 Dec 2020 15:28:31 +0300 Subject: [PATCH 18/20] add N constant and Mul impl for Scalar --- weierstrass/src/lib.rs | 5 +++- weierstrass/src/scalar.rs | 52 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index d1814de53..0371271bc 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -78,7 +78,7 @@ pub trait WeierstrassCurve /// number of bits (i.e. `0xFFFF...FFFF`) const MODULUS_Q_REDUCE_N: usize; - // we can't define GENERATOR, bacause `Choice` does not + // we can't define GENERATOR, because `Choice` does not // support const construction const GENERATOR_X: FieldElement; const GENERATOR_Y: FieldElement; @@ -91,4 +91,7 @@ pub trait WeierstrassCurve const MU: WordsP1; /// P*PT (mod 2^WORD_WIDTH) == -1 const PT: Word; + + /// The elliptic curve group order divided by subgroup order (m/q) + const N: Word; } diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 9c106b969..5b9502fd2 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -259,6 +259,26 @@ impl Scalar Self::barrett_reduce(w) } + pub fn mul_word(&self, rhs: Word) -> Self { + let mut w = DoubleWords::::default(); + let n = self.words.len(); + + // Schoolbook multiplication. + for i in 0..n { + let mut carry = Word::default(); + let t = mac(w[i], self.words[i], rhs, carry); + w[i] = t.0; + carry = t.1; + for j in 1..n { + let t = mac(w[i + j], self.words[i], 0, carry); + w[i + j] = t.0; + carry = t.1; + } + w[i + n] = carry; + } + Self::barrett_reduce(w) + } + /// Returns self * self mod p pub fn square(&self) -> Self { self.mul(self) @@ -503,6 +523,38 @@ impl MulAssign> for Scalar } } +impl Mul for Scalar + where + C: WeierstrassCurve, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + type Output = Self; + + #[inline] + fn mul(self, other: Word) -> Self { + Scalar::mul_word(&self, other) + } +} + +impl MulAssign for Scalar + where + C: WeierstrassCurve, + WordsLen: ArrayLength + Add + Shl, + DoubleWordsLen: ArrayLength, + WordsP1Len: ArrayLength, + WordsBytesLen: ArrayLength, + Words: Copy, +{ + #[inline] + fn mul_assign(&mut self, other: Word) { + *self = Scalar::mul_word(self, other); + } +} + impl Neg for Scalar where C: WeierstrassCurve, From 74c225c51d5adf522269917ec2e7ad1782a8671e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Wed, 2 Dec 2020 21:33:30 +0300 Subject: [PATCH 19/20] make conversion methods generic over byte order --- Cargo.lock | 1 + weierstrass/Cargo.toml | 1 + weierstrass/src/field.rs | 34 +++++----------- weierstrass/src/lib.rs | 3 +- weierstrass/src/scalar.rs | 64 ++++++++++++------------------ weierstrass/src/utils.rs | 82 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 120 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24e246642..8454ed078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1027,6 +1027,7 @@ name = "weierstrass" version = "0.1.0" dependencies = [ "biguint-literal", + "byteorder", "generic-array", "hex-literal", "rand_core", diff --git a/weierstrass/Cargo.toml b/weierstrass/Cargo.toml index 534fde708..c4478a554 100644 --- a/weierstrass/Cargo.toml +++ b/weierstrass/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] generic-array = "0.14" +byteorder = "1" subtle = { version = "2.3", default-features = false } rand_core = { version = "0.5", default-features = false } biguint-literal = { git = "https://github.com/RustCrypto/utils", branch = "biguint" } diff --git a/weierstrass/src/field.rs b/weierstrass/src/field.rs index d1f3c3950..f08182745 100644 --- a/weierstrass/src/field.rs +++ b/weierstrass/src/field.rs @@ -1,10 +1,9 @@ -use core::{fmt, mem}; -use core::convert::TryInto; -use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; +use core::{fmt, ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}}; use generic_array::ArrayLength; use generic_array::typenum::{B1, U1}; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use rand_core::{RngCore, CryptoRng}; +use crate::utils::BigUintExt; use crate::{ WeierstrassCurve, Word, WORD_WIDTH_BITS, @@ -59,17 +58,11 @@ impl FieldElement FieldElement::montgomery_reduce(t) } - /// Attempts to parse the given byte array as an SEC1-encoded field element. + /// Attempts to parse the given byte array. /// - /// Returns None if the byte array does not contain a big-endian integer in the range - /// [0, p). - pub fn from_bytes(bytes: &WordsBytes) -> CtOption { - let mut words = Words::::default(); - let m = mem::size_of::(); - let iter = words.iter_mut().zip(bytes.chunks_exact(m).rev()); - for (w, chunk) in iter { - *w = Word::from_be_bytes(chunk.try_into().unwrap()); - } + /// Returns None if resulting integer is not in the range [0, p). + pub fn from_bytes(bytes: &WordsBytes) -> CtOption { + let words = B::bytes2biguint(bytes); let mut borrow = Word::default(); for (&w, &wm) in words.iter().zip(C::MODULUS_P.iter()) { @@ -81,21 +74,14 @@ impl FieldElement CtOption::new(Self { words }.mul(C::R2), Choice::from(is_some)) } - /// Returns the SEC1 encoding of this field element. - pub fn to_bytes(&self) -> WordsBytes { + /// Returns byte encoding of this field element. + pub fn to_bytes(&self) -> WordsBytes { // Convert from Montgomery form to canonical form let mut w = DoubleWords::::default(); let n = self.words.len(); w[..n].copy_from_slice(&self.words); - let t = Self::montgomery_reduce(w); - - let m = mem::size_of::(); - let mut buf = WordsBytes::::default(); - let iter = buf.chunks_exact_mut(m).rev().zip(t.words.iter()); - for (chunk, wt) in iter { - chunk.copy_from_slice(&wt.to_be_bytes()); - } - buf + let t = Self::montgomery_reduce(w).words; + B::biguint2bytes(&t) } /// Determine if this `FieldElement` is zero. diff --git a/weierstrass/src/lib.rs b/weierstrass/src/lib.rs index 0371271bc..0a1f458ba 100644 --- a/weierstrass/src/lib.rs +++ b/weierstrass/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -pub use {generic_array, subtle}; +pub use {generic_array, subtle, byteorder}; use generic_array::{ArrayLength, GenericArray}; use generic_array::typenum::{ self, @@ -20,6 +20,7 @@ pub use affine::AffinePoint; pub use field::FieldElement; pub use scalar::Scalar; pub use projective::ProjectivePoint; +pub use utils::BigUintExt; // TODO: add cfgs for other word sizes pub type Word = u64; diff --git a/weierstrass/src/scalar.rs b/weierstrass/src/scalar.rs index 5b9502fd2..1801a5c52 100644 --- a/weierstrass/src/scalar.rs +++ b/weierstrass/src/scalar.rs @@ -1,8 +1,7 @@ -use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}; -use core::{fmt, mem}; -use core::convert::TryInto; +use core::{fmt, ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Neg, Shl}}; use subtle::{ConditionallySelectable, Choice, ConstantTimeEq, CtOption}; use generic_array::{ArrayLength, typenum::{B1, U1}}; +use crate::utils::BigUintExt; use super::{ WeierstrassCurve, Word, WORD_WIDTH_BITS, Words, WordsLen, @@ -46,35 +45,6 @@ impl Scalar t } - /// Parses the given byte array as a scalar. - /// - /// Subtracts the modulus when the byte array is larger than the modulus. - pub fn from_bytes_reduced(bytes: &WordsBytes) -> Self { - let mut words = WordsP1::::default(); - let m = mem::size_of::(); - let iter = words.iter_mut().zip(bytes.chunks_exact(m).rev()); - for (w, chunk) in iter { - *w = Word::from_be_bytes(chunk.try_into().unwrap()); - } - let modulus = Self { words: C::MODULUS_Q }; - let mut res = Self::sub_inner(words, modulus); - for _ in 1..C::MODULUS_Q_REDUCE_N { - res -= modulus; - } - res - } - - /// Returns the SEC1 encoding of this scalar. - pub fn to_bytes(&self) -> WordsBytes { - let mut buf = WordsBytes::::default(); - let m = mem::size_of::(); - let iter = buf.chunks_exact_mut(m).zip(self.words.iter().rev()); - for (chunk, w) in iter { - chunk.copy_from_slice(&w.to_be_bytes()); - } - buf - } - /// Determine if this `Scalar` is zero. pub fn is_zero(&self) -> Choice { self.ct_eq(&Scalar::zero()) @@ -337,13 +307,8 @@ impl Scalar todo!(); } - pub fn from_repr(bytes: WordsBytes) -> Option { - let mut words = Words::::default(); - let n = mem::size_of::(); - let iter = words.iter_mut().rev().zip(bytes.chunks_exact(n)); - for (wm, chunk) in iter { - *wm = Word::from_be_bytes(chunk.try_into().unwrap()); - } + pub fn from_bytes(bytes: WordsBytes) -> Option { + let words = B::bytes2biguint(&bytes); // If w is in the range [0, n) then w - n will overflow, resulting // in a borrow value of 2^64 - 1. @@ -355,6 +320,27 @@ impl Scalar CtOption::new(Self { words }, Choice::from(is_some)).into() } + + /// Parse the given byte array as a scalar. + /// + /// Subtracts the modulus when the byte array is larger than the modulus. + pub fn from_bytes_reduced(bytes: &WordsBytes) -> Self { + let mut words = WordsP1::::default(); + let t = B::bytes2biguint(bytes); + words[..t.len()].copy_from_slice(&t); + + let modulus = Self { words: C::MODULUS_Q }; + let mut res = Self::sub_inner(words, modulus); + for _ in 1..C::MODULUS_Q_REDUCE_N { + res -= modulus; + } + res + } + + /// Returns BE encoding of this scalar. + pub fn to_bytes(&self) -> WordsBytes { + B::biguint2bytes(&self.words) + } } diff --git a/weierstrass/src/utils.rs b/weierstrass/src/utils.rs index 8537bc9cb..5afd5d739 100644 --- a/weierstrass/src/utils.rs +++ b/weierstrass/src/utils.rs @@ -1,4 +1,9 @@ -use crate::{DoubleWord, Word, WORD_WIDTH_BITS}; +use crate::{DoubleWord, Word, WordWidth, WORD_WIDTH_BITS}; +use byteorder::{ByteOrder, BigEndian, LittleEndian}; +use generic_array::{GenericArray, ArrayLength, typenum::{Unsigned, Quot}}; +use core::ops::Div; +use core::mem; +use core::convert::TryInto; /// Computes `a + b + carry`, returning the result along with the new carry. #[inline(always)] @@ -23,3 +28,78 @@ pub(crate) const fn mac(a: Word, b: Word, c: Word, carry: Word) -> (Word, Word) let ret = a + b * c + (carry as DoubleWord); (ret as Word, (ret >> WORD_WIDTH_BITS) as Word) } + +/// Extension of the `ByteOrder` trait for biguint <-> bytes conversion. +pub trait BigUintExt: ByteOrder { + fn bytes2biguint(bytes: &GenericArray) -> Words + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength; + + fn biguint2bytes(words: &Words) -> GenericArray + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength; +} + +type Words = GenericArray>; + +impl BigUintExt for BigEndian { + fn bytes2biguint(bytes: &GenericArray) -> Words + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength + { + let mut words = Words::::default(); + let m = mem::size_of::(); + let iter = words.iter_mut().zip(bytes.chunks_exact(m).rev()); + for (w, chunk) in iter { + *w = Word::from_be_bytes(chunk.try_into().unwrap()); + } + words + } + + fn biguint2bytes(words: &Words) -> GenericArray + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength + { + let mut buf = GenericArray::::default(); + let m = mem::size_of::(); + let iter = buf.chunks_exact_mut(m).zip(words.iter().rev()); + for (chunk, w) in iter { + chunk.copy_from_slice(&w.to_be_bytes()); + } + buf + } +} + +impl BigUintExt for LittleEndian { + fn bytes2biguint(bytes: &GenericArray) -> Words + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength + { + let mut words = Words::::default(); + let n = mem::size_of::(); + let iter = words.iter_mut().zip(bytes.chunks_exact(n)); + for (wm, chunk) in iter { + *wm = Word::from_le_bytes(chunk.try_into().unwrap()); + } + words + } + + fn biguint2bytes(words: &Words) -> GenericArray + where + N: Unsigned + ArrayLength + Div, + Quot: ArrayLength + { + let mut buf = GenericArray::::default(); + let m = mem::size_of::(); + let iter = buf.chunks_exact_mut(m).zip(words.iter()); + for (chunk, w) in iter { + chunk.copy_from_slice(&w.to_le_bytes()); + } + buf + } +} From 95b658dcbb500209d622917ca49fae83ef2c5943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Tue, 8 Dec 2020 07:03:28 +0000 Subject: [PATCH 20/20] disable default features for byteorder --- weierstrass/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weierstrass/Cargo.toml b/weierstrass/Cargo.toml index c4478a554..45bec1f2f 100644 --- a/weierstrass/Cargo.toml +++ b/weierstrass/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] generic-array = "0.14" -byteorder = "1" +byteorder = { version = "1", default-features = false } subtle = { version = "2.3", default-features = false } rand_core = { version = "0.5", default-features = false } biguint-literal = { git = "https://github.com/RustCrypto/utils", branch = "biguint" }