diff --git a/CHANGELOG.md b/CHANGELOG.md index b723ca3..c56a6ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Add `repr-c` cargo feature to facilitate FFI by conditionally adding + `repr(C)` attribute to point structures. + +### Changed +- Add `repr(transparent)` attribute to Fp/Fq structures. +- Omit 'infinity' field from affine coordinates structures and use (0, 0) + to denote the identity points. ## [0.3.0] - 2022-01-03 ### Added diff --git a/Cargo.toml b/Cargo.toml index 620104f..38452d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,3 +62,4 @@ alloc = ["group/alloc", "blake2b_simd"] bits = ["ff/bits"] gpu = ["alloc", "ec-gpu"] sqrt-table = ["alloc", "lazy_static"] +repr-c = [] diff --git a/src/curves.rs b/src/curves.rs index 7c16ead..8efc206 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -29,6 +29,7 @@ macro_rules! new_curve_impl { $curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => { /// Represents a point in the projective coordinate space. #[derive(Copy, Clone, Debug)] + #[cfg_attr(feature = "repr-c", repr(C))] $($privacy)* struct $name { x: $base, y: $base, @@ -48,15 +49,15 @@ macro_rules! new_curve_impl { /// Represents a point in the affine coordinate space (or the point at /// infinity). #[derive(Copy, Clone)] + #[cfg_attr(feature = "repr-c", repr(C))] $($privacy)* struct $name_affine { x: $base, y: $base, - infinity: Choice, } impl fmt::Debug for $name_affine { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - if self.infinity.into() { + if self.is_identity().into() { write!(f, "Infinity") } else { write!(f, "({:?}, {:?})", self.x, self.y) @@ -81,7 +82,6 @@ macro_rules! new_curve_impl { let p = $name_affine { x, y, - infinity: Choice::from(0u8), }; break p.to_curve(); } @@ -200,7 +200,6 @@ macro_rules! new_curve_impl { q.x = p.x * tmp2; q.y = p.y * tmp3; - q.infinity = Choice::from(0u8); *q = $name_affine::conditional_select(&q, &$name_affine::identity(), skip); } @@ -216,7 +215,6 @@ macro_rules! new_curve_impl { let tmp = $name_affine { x, y, - infinity: Choice::from(0u8), }; $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.is_zero()) @@ -502,7 +500,6 @@ macro_rules! new_curve_impl { $name_affine { x: self.x, y: -self.y, - infinity: self.infinity, } } } @@ -621,19 +618,18 @@ macro_rules! new_curve_impl { Self { x: $base::zero(), y: $base::zero(), - infinity: Choice::from(1u8), } } fn is_identity(&self) -> Choice { - self.infinity + self.x.is_zero() & self.y.is_zero() } fn to_curve(&self) -> Self::Curve { $name { x: self.x, y: self.y, - z: $base::conditional_select(&$base::one(), &$base::zero(), self.infinity), + z: $base::conditional_select(&$base::one(), &$base::zero(), self.is_identity()), } } } @@ -679,7 +675,6 @@ macro_rules! new_curve_impl { $name_affine { x, y, - infinity: Choice::from(0u8), }, Choice::from(1u8), ) @@ -717,7 +712,7 @@ macro_rules! new_curve_impl { fn is_on_curve(&self) -> Choice { // y^2 - x^3 - ax ?= b (self.y.square() - (self.x.square() + &$name::curve_constant_a()) * self.x).ct_eq(&$name::curve_constant_b()) - | self.infinity + | self.is_identity() } fn coordinates(&self) -> CtOption> { @@ -726,7 +721,7 @@ macro_rules! new_curve_impl { fn from_xy(x: Self::Base, y: Self::Base) -> CtOption { let p = $name_affine { - x, y, infinity: 0u8.into() + x, y, }; CtOption::new(p, p.is_on_curve()) } @@ -760,10 +755,7 @@ macro_rules! new_curve_impl { impl ConstantTimeEq for $name_affine { fn ct_eq(&self, other: &Self) -> Choice { - let z1 = self.infinity; - let z2 = other.infinity; - - (z1 & z2) | ((!z1) & (!z2) & (self.x.ct_eq(&other.x)) & (self.y.ct_eq(&other.y))) + self.x.ct_eq(&other.x) & self.y.ct_eq(&other.y) } } @@ -780,7 +772,6 @@ macro_rules! new_curve_impl { $name_affine { x: $base::conditional_select(&a.x, &b.x, choice), y: $base::conditional_select(&a.y, &b.y, choice), - infinity: Choice::conditional_select(&a.infinity, &b.infinity, choice), } } } @@ -951,7 +942,6 @@ macro_rules! impl_affine_curve_specific { Self { x: NEGATIVE_ONE, y: TWO, - infinity: Choice::from(0u8), } } }; diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 50dba17..6e39fc1 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -26,6 +26,7 @@ use crate::arithmetic::SqrtTables; // integers in little-endian order. `Fp` values are always in // Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256. #[derive(Clone, Copy, Eq)] +#[repr(transparent)] pub struct Fp(pub(crate) [u64; 4]); impl fmt::Debug for Fp { diff --git a/src/fields/fq.rs b/src/fields/fq.rs index d01a609..5604c15 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -26,6 +26,7 @@ use crate::arithmetic::SqrtTables; // integers in little-endian order. `Fq` values are always in // Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256. #[derive(Clone, Copy, Eq)] +#[repr(transparent)] pub struct Fq(pub(crate) [u64; 4]); impl fmt::Debug for Fq {