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:
parent
c392ffbeb2
commit
aa0628ffcf
54
src/lib.rs
54
src/lib.rs
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue