ExtendedNielsPoint::multiply_bits

This allows the caller to control which stack frames pay the cost of
Montgomery reduction and scalar multiplication, by splitting
Fr::into_bytes out from the multiplication step. It also enables the
caller to drop the Montgomery multiplication and reduction round-trip if
they already have an encoded Fr element.
This commit is contained in:
Jack Grigg 2019-04-30 10:34:51 +01:00
parent c392ffbeb2
commit aa0628ffcf
No known key found for this signature in database
GPG Key ID: 9E8255172BBF9898
1 changed files with 32 additions and 22 deletions

View File

@ -262,6 +262,37 @@ impl ExtendedNielsPoint {
t2d: Fq::zero(),
}
}
#[inline]
fn multiply(&self, by: &[u8; 32]) -> ExtendedPoint {
let zero = ExtendedNielsPoint::identity();
let mut acc = ExtendedPoint::identity();
// This is a simple double-and-add implementation of point
// multiplication, moving from most significant to least
// significant bit of the scalar.
//
// We skip the leading four bits because they're always
// unset for Fr.
for bit in by
.iter()
.rev()
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
.skip(4)
{
acc = acc.double();
acc += ExtendedNielsPoint::conditional_select(&zero, &self, bit);
}
acc
}
/// Multiplies this point by the specific little-endian bit pattern in the
/// given byte array, ignoring the highest four bits.
pub fn multiply_bits(&self, by: &[u8; 32]) -> ExtendedPoint {
self.multiply(by)
}
}
// `d = -(10240/10241)`
@ -556,28 +587,7 @@ impl ExtendedPoint {
#[inline]
fn multiply(self, by: &[u8; 32]) -> Self {
let zero = ExtendedNielsPoint::identity();
let base = self.to_niels();
let mut acc = ExtendedPoint::identity();
// This is a simple double-and-add implementation of point
// multiplication, moving from most significant to least
// significant bit of the scalar.
//
// We skip the leading four bits because they're always
// unset for Fr.
for bit in by
.iter()
.rev()
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
.skip(4)
{
acc = acc.double();
acc = acc + ExtendedNielsPoint::conditional_select(&zero, &base, bit);
}
acc
self.to_niels().multiply(by)
}
/// This is only for debugging purposes and not