mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-03 20:13:48 +00:00
curve: extract AffinePoint type (#769)
* curve: extract `AffinePoint` type Based on discussions about `elliptic-curve` trait impls in #746, and observing a similar type in `ed448-goldilocks` which inspired this one (not to mention in all of the @RustCrypto elliptic curve crates), adds an `AffinePoint` type with `x` and `y` coordinates. For now, the type is kept out of the public API, and used as an implementation detail for point compression. However, it's been written with the intent of eventually stabilizing and exposing it. It's been marked `pub` so unused functionality doesn't automatically trigger dead code lints. Further work could include refactoring point decompression to first produce an `AffinePoint` and then convert to extended twisted Edwards coordinates (i.e. `EdwardsPoint`), which is more or less what the existing `step_1` and `step_2` functions do (`step_1` technically produces projective coordinates, but `Z` is always set to `ONE`). * Update curve25519-dalek/src/edwards.rs
This commit is contained in:
parent
cf7b099585
commit
8c53a8f10b
2 changed files with 129 additions and 14 deletions
|
|
@ -93,6 +93,8 @@
|
|||
// affine and projective cakes and eat both of them too.
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
mod affine;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use core::array::TryFromSliceError;
|
||||
use core::borrow::Borrow;
|
||||
|
|
@ -146,6 +148,8 @@ use crate::traits::BasepointTable;
|
|||
use crate::traits::ValidityCheck;
|
||||
use crate::traits::{Identity, IsIdentity};
|
||||
|
||||
use affine::AffinePoint;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::traits::MultiscalarMul;
|
||||
#[cfg(feature = "alloc")]
|
||||
|
|
@ -528,7 +532,7 @@ impl EdwardsPoint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Dehomogenize to a AffineNielsPoint.
|
||||
/// Dehomogenize to a `AffineNielsPoint`.
|
||||
/// Mainly for testing.
|
||||
pub(crate) fn as_affine_niels(&self) -> AffineNielsPoint {
|
||||
let recip = self.Z.invert();
|
||||
|
|
@ -542,6 +546,14 @@ impl EdwardsPoint {
|
|||
}
|
||||
}
|
||||
|
||||
/// Dehomogenize to `AffinePoint`.
|
||||
pub(crate) fn to_affine(self) -> AffinePoint {
|
||||
let recip = self.Z.invert();
|
||||
let x = &self.X * &recip;
|
||||
let y = &self.Y * &recip;
|
||||
AffinePoint { x, y }
|
||||
}
|
||||
|
||||
/// Convert this `EdwardsPoint` on the Edwards model to the
|
||||
/// corresponding `MontgomeryPoint` on the Montgomery model.
|
||||
///
|
||||
|
|
@ -587,10 +599,7 @@ impl EdwardsPoint {
|
|||
|
||||
/// Compress this point to `CompressedEdwardsY` format.
|
||||
pub fn compress(&self) -> CompressedEdwardsY {
|
||||
let recip = self.Z.invert();
|
||||
let x = &self.X * &recip;
|
||||
let y = &self.Y * &recip;
|
||||
Self::compress_affine(x, y)
|
||||
self.to_affine().compress()
|
||||
}
|
||||
|
||||
/// Compress several `EdwardsPoint`s into `CompressedEdwardsY` format, using a batch inversion
|
||||
|
|
@ -606,19 +615,11 @@ impl EdwardsPoint {
|
|||
.map(|(input, recip)| {
|
||||
let x = &input.X * recip;
|
||||
let y = &input.Y * recip;
|
||||
Self::compress_affine(x, y)
|
||||
AffinePoint { x, y }.compress()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Compress affine Edwards coordinates into `CompressedEdwardsY` format.
|
||||
#[inline]
|
||||
fn compress_affine(x: FieldElement, y: FieldElement) -> CompressedEdwardsY {
|
||||
let mut s = y.to_bytes();
|
||||
s[31] ^= x.is_negative().unwrap_u8() << 7;
|
||||
CompressedEdwardsY(s)
|
||||
}
|
||||
|
||||
#[cfg(feature = "digest")]
|
||||
/// Maps the digest of the input bytes to the curve. This is NOT a hash-to-curve function, as
|
||||
/// it produces points with a non-uniform distribution. Rather, it performs something that
|
||||
|
|
|
|||
114
curve25519-dalek/src/edwards/affine.rs
Normal file
114
curve25519-dalek/src/edwards/affine.rs
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
use super::{CompressedEdwardsY, EdwardsPoint};
|
||||
use crate::traits::Identity;
|
||||
use crate::{field::FieldElement, Scalar};
|
||||
use core::ops::Mul;
|
||||
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
|
||||
|
||||
#[cfg(feature = "zeroize")]
|
||||
use zeroize::DefaultIsZeroes;
|
||||
|
||||
/// Affine Edwards point on untwisted curve.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct AffinePoint {
|
||||
pub(super) x: FieldElement,
|
||||
pub(super) y: FieldElement,
|
||||
}
|
||||
|
||||
impl ConstantTimeEq for AffinePoint {
|
||||
fn ct_eq(&self, other: &Self) -> Choice {
|
||||
self.x.ct_eq(&other.x) & self.y.ct_eq(&other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for AffinePoint {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Self {
|
||||
x: FieldElement::conditional_select(&a.x, &b.x, choice),
|
||||
y: FieldElement::conditional_select(&a.y, &b.y, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AffinePoint {
|
||||
fn default() -> AffinePoint {
|
||||
AffinePoint::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl Identity for AffinePoint {
|
||||
fn identity() -> AffinePoint {
|
||||
AffinePoint {
|
||||
x: FieldElement::ZERO,
|
||||
y: FieldElement::ONE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for AffinePoint {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.ct_eq(other).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for AffinePoint {}
|
||||
|
||||
#[cfg(feature = "zeroize")]
|
||||
impl DefaultIsZeroes for AffinePoint {}
|
||||
|
||||
impl AffinePoint {
|
||||
/// Convert to extended coordinates.
|
||||
pub fn to_edwards(self) -> EdwardsPoint {
|
||||
EdwardsPoint {
|
||||
X: self.x,
|
||||
Y: self.y,
|
||||
Z: FieldElement::ONE,
|
||||
T: &self.x * &self.y,
|
||||
}
|
||||
}
|
||||
|
||||
/// Compress affine Edwards coordinates into `CompressedEdwardsY` format.
|
||||
#[inline]
|
||||
pub fn compress(self) -> CompressedEdwardsY {
|
||||
let mut s = self.y.to_bytes();
|
||||
s[31] ^= self.x.is_negative().unwrap_u8() << 7;
|
||||
CompressedEdwardsY(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<AffinePoint> for Scalar {
|
||||
type Output = EdwardsPoint;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: AffinePoint) -> EdwardsPoint {
|
||||
self * &rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<&AffinePoint> for Scalar {
|
||||
type Output = EdwardsPoint;
|
||||
|
||||
#[inline]
|
||||
fn mul(self, rhs: &AffinePoint) -> EdwardsPoint {
|
||||
rhs.to_edwards() * self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AffinePoint, EdwardsPoint, Identity};
|
||||
use crate::constants;
|
||||
|
||||
#[test]
|
||||
fn identity_conversion() {
|
||||
assert_eq!(
|
||||
AffinePoint::identity().to_edwards(),
|
||||
EdwardsPoint::identity()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generator_round_trip() {
|
||||
let basepoint = constants::ED25519_BASEPOINT_POINT;
|
||||
assert_eq!(basepoint.to_affine().to_edwards(), basepoint);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue