From d88f92276a3b17afe389b232d1b3effbe4260eac Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Tue, 21 Nov 2017 11:28:25 -0800 Subject: [PATCH] Add Scalar::reduce method --- src/scalar.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/scalar.rs b/src/scalar.rs index ec5e225..b7bd2b0 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -47,6 +47,7 @@ use subtle::ConditionallyAssignable; use subtle::Equal; use backend; +use constants; /// An `UnpackedScalar` represents an element of the field GF(l), optimized for speed. #[cfg(feature="radix_51")] @@ -438,6 +439,14 @@ impl Scalar { UnpackedScalar::add(&UnpackedScalar::mul(&a.unpack(), &b.unpack()), &c.unpack()).pack() } + /// Reduce this `Scalar` mod l. + pub fn reduce(&self) -> Scalar { + let x = self.unpack(); + let xR = UnpackedScalar::mul_internal(&x, &constants::R); + let x_mod_l = UnpackedScalar::montgomery_reduce(&xR); + x_mod_l.pack() + } + /// Reduce a 512-bit little endian number mod l pub fn reduce_wide(input: &[u8; 64]) -> Scalar { UnpackedScalar::from_bytes_wide(input).pack() @@ -669,6 +678,17 @@ mod test { } } + #[test] + fn reduce() { + let biggest = Scalar([0xff; 32]); + // sage: l = 2^252 + 27742317777372353535851937790883648493 + // sage: big = 2^256 - 1 + // sage: repr((big % l).digits(256)) + let biggest_mod_l = Scalar([28, 149, 152, 141, 116, 49, 236, 214, 112, 207, 125, 115, 244, 91, 239, 198, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15]); + let reduced = biggest.reduce(); + assert_eq!(reduced, biggest_mod_l); + } + #[test] fn reduce_wide() { let mut bignum = [0u8; 64]; @@ -717,7 +737,6 @@ mod test { assert_eq!(should_be_unpacked.0, unpacked.0); } - #[test] fn montgomery_reduce_matches_reduce_wide() { let mut bignum = [0u8; 64]; @@ -769,6 +788,13 @@ mod bench { use super::*; use super::test::{X}; + #[bench] + fn reduce(b: &mut Bencher) { + let unreduced = Scalar([0xff; 32]); + + b.iter(|| unreduced.reduce()); + } + #[bench] fn scalar_random(b: &mut Bencher) { let mut csprng: OsRng = OsRng::new().unwrap();