From cf210fe58627ff9698ff7e903f22cf3df0e2d85c Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 31 Aug 2018 19:47:53 -0600 Subject: [PATCH] Implementation of inversion for Fp --- Cargo.toml | 5 +++++ src/fq.rs | 41 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 47 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e02d2fb..fafbd69 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,8 @@ version = "0.0.0" [dependencies.byteorder] version = "1" default-features = false + +[dependencies.subtle] +version = "0.7" +default-features = false +features = ["generic-impls"] diff --git a/src/fq.rs b/src/fq.rs index af055e7..1368c09 100644 --- a/src/fq.rs +++ b/src/fq.rs @@ -1,6 +1,7 @@ use core::ops::{AddAssign, SubAssign, MulAssign, Neg}; use byteorder::{ByteOrder, LittleEndian}; +use subtle::{Choice, ConditionallySelectable, ConditionallyAssignable}; /// Represents an element of `GF(q)`. // The internal representation of this type is four 64-bit unsigned @@ -9,6 +10,17 @@ use byteorder::{ByteOrder, LittleEndian}; #[derive(Clone, Copy)] pub struct Fq([u64; 4]); +impl ConditionallySelectable for Fq { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Fq([ + u64::conditional_select(&a.0[0], &b.0[0], choice), + u64::conditional_select(&a.0[1], &b.0[1], choice), + u64::conditional_select(&a.0[2], &b.0[2], choice), + u64::conditional_select(&a.0[3], &b.0[3], choice) + ]) + } +} + // Constant representing the modulus // q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 const MODULUS: Fq = Fq([ @@ -198,6 +210,35 @@ impl Fq { res } + /// Squares this element. + pub fn square_assign(&mut self) { + let tmp = *self; + self.mul_assign(&tmp); + } + + /// Exponentiates `self` by `by`, where `by` is a + /// little-endian order integer exponent. + pub fn pow(&self, by: &[u64; 4]) -> Self { + let mut res = Self::one(); + for e in by.iter().rev() { + res.square_assign(); + let mut e = *e; + for i in (0..64).rev() { + let mut tmp = res; + tmp.mul_assign(self); + res.conditional_assign(&tmp, (((e >> i) & 0x1) as u8).into()); + } + } + res + } + + /// Exponentiates `self` by q - 2, which has the + /// effect of inverting the element if it is + /// nonzero. + pub fn pow_q_minus_2(&self) -> Self { + self.pow(&[0xfffffffeffffffff, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48]) + } + #[inline(always)] fn montgomery_reduce( &mut self, diff --git a/src/lib.rs b/src/lib.rs index a5fa9d0..f6a59a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ extern crate core; extern crate byteorder; +extern crate subtle; mod fq; pub use fq::*;