mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-04 20:24:10 +00:00
curve25519-dalek: add batch montgomery conversion (#722)
This commit is contained in:
parent
dd5bd108d6
commit
dcd39743ea
1 changed files with 47 additions and 0 deletions
|
|
@ -563,6 +563,28 @@ impl EdwardsPoint {
|
|||
MontgomeryPoint(u.as_bytes())
|
||||
}
|
||||
|
||||
/// Converts a large batch of points to Edwards at once. This has the same
|
||||
/// behavior on identity elements as [`Self::to_montgomery`].
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn to_montgomery_batch(eds: &[Self]) -> Vec<MontgomeryPoint> {
|
||||
// Do the same thing as the above function. u = (1+y)/(1-y) = (Z+Y)/(Z-Y).
|
||||
// We will do this in a batch, ie compute (Z-Y) for all the input
|
||||
// points, then invert them all at once
|
||||
|
||||
// Compute the denominators in a batch
|
||||
let mut denominators = eds.iter().map(|p| &p.Z - &p.Y).collect::<Vec<_>>();
|
||||
FieldElement::batch_invert(&mut denominators);
|
||||
|
||||
// Now compute the Montgomery u coordinate for every point
|
||||
let mut ret = Vec::with_capacity(eds.len());
|
||||
for (ed, d) in eds.iter().zip(denominators.iter()) {
|
||||
let u = &(&ed.Z + &ed.Y) * d;
|
||||
ret.push(MontgomeryPoint(u.as_bytes()));
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/// Compress this point to `CompressedEdwardsY` format.
|
||||
pub fn compress(&self) -> CompressedEdwardsY {
|
||||
let recip = self.Z.invert();
|
||||
|
|
@ -2189,6 +2211,31 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn batch_to_montgomery() {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let scalars = (0..128)
|
||||
.map(|_| Scalar::random(&mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let points = scalars
|
||||
.iter()
|
||||
.map(EdwardsPoint::mul_base)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let single_monts = points
|
||||
.iter()
|
||||
.map(EdwardsPoint::to_montgomery)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for i in [0, 1, 2, 3, 10, 50, 128] {
|
||||
let invs = EdwardsPoint::to_montgomery_batch(&points[..i]);
|
||||
assert_eq!(&invs, &single_monts[..i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn vartime_precomputed_vs_nonprecomputed_multiscalar() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue