diff --git a/src/constants.rs b/src/constants.rs index 1821f9a..50879da 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -166,6 +166,13 @@ pub const l_minus_1: Scalar = Scalar([ 0xec, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]); +/// `lminus1` is the order of base point minus two, i.e. 2^252 + +/// 27742317777372353535851937790883648493 - 2, in little-endian form +pub const l_minus_2: Scalar = Scalar([ 0xeb, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]); + /// The 8-torsion subgroup Ɛ[8]. /// /// In the case of Curve25519, it is cyclic; the `i`th element of the diff --git a/src/scalar.rs b/src/scalar.rs index 6468ddd..d711173 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -209,6 +209,11 @@ impl Scalar { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]) } + /// Compute the multiplicative inverse of this scalar. + pub fn invert(&self) -> Scalar { + self.unpack().invert().pack() + } + /// Get the bits of the scalar. pub fn bits(&self) -> [i8;256] { let mut bits = [0i8; 256]; @@ -462,6 +467,19 @@ impl UnpackedScalar { UnpackedScalar([1,0,0,0,0,0,0,0,0,0,0,0]) } + /// Compute the multiplicative inverse of this scalar. + pub fn invert(&self) -> UnpackedScalar { + let mut y = UnpackedScalar::one(); + // Run through bits of l-2 from highest to least + for bit in constants::l_minus_2.bits().iter().rev() { + y = &y * &y; + if *bit == 1 { + y *= self; + } + } + y + } + /// Compute `ab+c (mod l)`. pub fn multiply_add(a: &UnpackedScalar, b: &UnpackedScalar, @@ -727,6 +745,14 @@ mod test { } } + #[test] + fn invert() { + let x = UnpackedScalar([2,0,0,0,0,0,0,0,0,0,0,0]); + let x_inv = x.invert(); + let should_be_one = &x * &x_inv; + assert_eq!(should_be_one.pack(), Scalar::one()); + } + // Negating a scalar twice should result in the original scalar. #[test] fn scalar_neg() { @@ -757,6 +783,12 @@ mod bench { b.iter(|| Scalar::multiply_add(&X, &Y, &Z) ); } + #[bench] + fn invert(b: &mut Bencher) { + let x = X.unpack(); + b.iter(|| x.invert()); + } + #[bench] fn scalar_unpacked_multiply_add(b: &mut Bencher) { let x = X.unpack();