diff --git a/math/src/elliptic_curve/point.rs b/math/src/elliptic_curve/point.rs index 3c654c0da..fa579d2c5 100644 --- a/math/src/elliptic_curve/point.rs +++ b/math/src/elliptic_curve/point.rs @@ -63,38 +63,80 @@ impl PartialEq for ProjectivePoint { } impl Eq for ProjectivePoint {} - #[derive(Debug, Clone)] + pub struct JacobianPoint { pub value: [FieldElement; 3], } impl JacobianPoint { + /// Creates an elliptic curve point giving the Jacobian [x: y: z] coordinates. pub const fn new(value: [FieldElement; 3]) -> Self { Self { value } } + /// Returns the `x` coordinate of the point. pub fn x(&self) -> &FieldElement { &self.value[0] } + /// Returns the `y` coordinate of the point. pub fn y(&self) -> &FieldElement { &self.value[1] } + /// Returns the `z` coordinate of the point. pub fn z(&self) -> &FieldElement { &self.value[2] } + /// Returns a tuple [x, y, z] with the coordinates of the point. pub fn coordinates(&self) -> &[FieldElement; 3] { &self.value } - pub fn from_affine(x: FieldElement, y: FieldElement) -> Self { - Self::new([x, y, FieldElement::one()]) + pub fn to_affine(&self) -> Self { + let [x, y, z] = self.coordinates(); + // If it's the point at infinite + if z == &FieldElement::zero() { + // We make sure all the points in the infinite have the same values + return Self::new([ + FieldElement::zero(), + FieldElement::one(), + FieldElement::zero(), + ]); + }; + let inv_z = z.inv().unwrap(); + let inv_z_square = inv_z.square(); + let inv_z_cube = &inv_z_square * &inv_z; + JacobianPoint::new([x * inv_z_square, y * inv_z_cube, FieldElement::one()]) } } +impl PartialEq for JacobianPoint { + fn eq(&self, other: &Self) -> bool { + // In Jacobian coordinates, the equality of two points is defined as: + // X1 * Z2^2 == X2 * Z1^2 y Y1 * Z2^3 == Y2 * Z1^3 + + let [px, py, pz] = self.coordinates(); + let [qx, qy, qz] = other.coordinates(); + + let zp_sq = pz.square(); + let zq_sq = qz.square(); + + let zp_cu = &zp_sq * pz; + let zq_cu = &zq_sq * qz; + + let xp_zq_sq = px * zq_sq; + let xq_zp_sq = qx * zp_sq; + + let yp_zq_cu = py * zq_cu; + let yq_zp_cu = qy * zp_cu; + + (xp_zq_sq == xq_zp_sq) && (yp_zq_cu == yq_zp_cu) + } +} +impl Eq for JacobianPoint {} #[cfg(test)] mod tests { use crate::cyclic_group::IsGroup; diff --git a/math/src/elliptic_curve/short_weierstrass/point.rs b/math/src/elliptic_curve/short_weierstrass/point.rs index 2325aa511..4c75cfebd 100644 --- a/math/src/elliptic_curve/short_weierstrass/point.rs +++ b/math/src/elliptic_curve/short_weierstrass/point.rs @@ -1,7 +1,7 @@ use crate::{ cyclic_group::IsGroup, elliptic_curve::{ - point::ProjectivePoint, + point::{JacobianPoint, ProjectivePoint}, traits::{EllipticCurveError, FromAffine, IsEllipticCurve}, }, errors::DeserializationError, @@ -14,8 +14,7 @@ use super::traits::IsShortWeierstrass; #[cfg(feature = "alloc")] use crate::traits::AsBytes; #[cfg(feature = "alloc")] -use alloc::vec::Vec; - +use alloc::vec::Vec; // Import the Double trait #[derive(Clone, Debug)] pub struct ShortWeierstrassProjectivePoint(pub ProjectivePoint); @@ -349,226 +348,82 @@ where } } -#[derive(Clone, Debug)] -pub struct ShortWeierstrassJacobianPoint(pub JacobianPoint); - -impl ShortWeierstrassJacobianPoint { - pub fn new( - x: FieldElement, - y: FieldElement, - z: FieldElement, - ) -> Self { - Self(JacobianPoint::new(x, y, z)) - } - - pub fn x(&self) -> &FieldElement { - self.0.x() - } - - pub fn y(&self) -> &FieldElement { - self.0.y() - } - - pub fn z(&self) -> &FieldElement { - self.0.z() - } - - pub fn coordinates(&self) -> [&FieldElement; 3] { - [self.x(), self.y(), self.z()] - } - - pub fn to_affine(&self) -> (FieldElement, FieldElement) { - self.0.to_affine() - } - - pub fn from_affine(x: FieldElement, y: FieldElement) -> Self { - Self(JacobianPoint::from_affine(x, y)) - } - - pub fn neutral_element() -> Self { - Self(JacobianPoint::neutral_element()) - } - - pub fn is_neutral_element(&self) -> bool { - self.0.is_neutral_element() - } - - pub fn double(&self) -> Self { - Self(self.0.double()) - } - - pub fn operate_with(&self, other: &Self) -> Self { - Self(self.0.operate_with(&other.0)) - } - - pub fn negate(&self) -> Self { - Self(self.0.negate()) - } -} - -impl PartialEq for JacobianPoint { - fn eq(&self, other: &Self) -> bool { - // In Jacobian coordinates, the equality of two points is defined as: - // X1 * Z2^2 == X2 * Z1^2 y Y1 * Z2^3 == Y2 * Z1^3 - - let z1_sq = self.z.square(); - let z2_sq = other.z.square(); - - let z1_cu = &z1_sq * &self.z; - let z2_cu = &z2_sq * &other.z; - - let x1_z2_sq = &self.x * &z2_sq; - let x2_z1_sq = &other.x * &z1_sq; - - let y1_z2_cu = &self.y * &z2_cu; - let y2_z1_cu = &other.y * &z1_cu; - - x1_z2_sq == x2_z1_sq && y1_z2_cu == y2_z1_cu - } -} - -impl Eq for JacobianPoint {} - -impl IsGroup for JacobianPoint { - fn neutral_element() -> Self { - Self::neutral_element() - } - - fn is_neutral_element(&self) -> bool { - self.is_neutral_element() - } - - fn operate_with(&self, other: &Self) -> Self { - self.operate_with(other) - } - - fn neg(&self) -> Self { - self.negate() - } -} - -impl PartialEq for ShortWeierstrassJacobianPoint { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl Eq for ShortWeierstrassJacobianPoint {} - -impl From> for JacobianPoint +#[cfg(feature = "alloc")] +impl AsBytes for ShortWeierstrassProjectivePoint where E: IsShortWeierstrass, + FieldElement: ByteConversion, { - fn from(point: ShortWeierstrassProjectivePoint) -> Self { - if let Ok(z_inv) = point.z().inv() { - Self { - x: point.x() * &z_inv, - y: point.y() * z_inv.square(), - z: point.z().clone(), - } - } else { - Self::neutral_element() - } + fn as_bytes(&self) -> alloc::vec::Vec { + self.serialize(PointFormat::Projective, Endianness::LittleEndian) } } -impl From> - for ShortWeierstrassJacobianPoint +#[cfg(feature = "alloc")] +impl From> for alloc::vec::Vec +where + E: IsShortWeierstrass, + FieldElement: ByteConversion, { - fn from(point: ShortWeierstrassProjectivePoint) -> Self { - if point.is_neutral_element() { - Self::neutral_element() - } else { - Self::from_affine(point.x().clone(), point.y().clone()) - } + fn from(value: ShortWeierstrassProjectivePoint) -> Self { + value.as_bytes() } } -impl FromAffine for ShortWeierstrassJacobianPoint { - fn from_affine( - x: FieldElement, - y: FieldElement, - ) -> Result { - Ok(Self(JacobianPoint::from_affine(x, y))) +impl Deserializable for ShortWeierstrassProjectivePoint +where + E: IsShortWeierstrass, + FieldElement: ByteConversion, +{ + fn deserialize(bytes: &[u8]) -> Result + where + Self: Sized, + { + Self::deserialize(bytes, PointFormat::Projective, Endianness::LittleEndian) } } #[derive(Clone, Debug)] -pub struct JacobianPoint { - x: FieldElement, - y: FieldElement, - z: FieldElement, -} +pub struct ShortWeierstrassJacobianPoint(pub JacobianPoint); -impl JacobianPoint { - pub const fn new( - x: FieldElement, - y: FieldElement, - z: FieldElement, - ) -> Self { - Self { x, y, z } +impl ShortWeierstrassJacobianPoint { + /// Creates an elliptic curve point giving the projective [x: y: z] coordinates. + pub const fn new(value: [FieldElement; 3]) -> Self { + Self(JacobianPoint::new(value)) } + /// Returns the `x` coordinate of the point. pub fn x(&self) -> &FieldElement { - &self.x + self.0.x() } + /// Returns the `y` coordinate of the point. pub fn y(&self) -> &FieldElement { - &self.y + self.0.y() } + /// Returns the `z` coordinate of the point. pub fn z(&self) -> &FieldElement { - &self.z - } - - pub fn from_affine(x: FieldElement, y: FieldElement) -> Self { - Self { - x, - y, - z: FieldElement::one(), - } - } - - pub fn to_affine(&self) -> (FieldElement, FieldElement) { - if self.is_neutral_element() { - panic!("Cannot convert the point at infinity to affine coordinates"); - } - - let z_inv = self - .z() - .inv() - .expect("Z should not be zero for a valid point."); - let z_inv_sq = &z_inv * &z_inv; - let z_inv_cu = &z_inv_sq * &z_inv; - let x_affine = &self.x * &z_inv_sq; - let y_affine = &self.y * &z_inv_cu; - (x_affine, y_affine) + self.0.z() } - pub fn neutral_element() -> Self { - Self { - x: FieldElement::zero(), - y: FieldElement::one(), - z: FieldElement::zero(), - } + /// Returns a tuple [x, y, z] with the coordinates of the point. + pub fn coordinates(&self) -> &[FieldElement; 3] { + self.0.coordinates() } - pub fn is_neutral_element(&self) -> bool { - self.z == FieldElement::zero() + /// Creates the same point in affine coordinates. That is, + /// returns [x / z^2: y / z^3: 1] where `self` is [x: y: z]. + /// Panics if `self` is the point at infinity. + pub fn to_affine(&self) -> Self { + Self(self.0.to_affine()) } -} -impl JacobianPoint { - // Immplementation taken from - // https://github.com/mratsim/constantine/blob/65147ed815d96fa94a05d307c1d9980877b7d0e8/constantine/math/elliptic/ec_shortweierstrass_jacobian.md pub fn double(&self) -> Self { if self.is_neutral_element() { return self.clone(); } - - let x1 = &self.x; - let y1 = &self.y; - let z1 = &self.z; + let [x1, y1, z1] = self.coordinates(); let a_coeff = E::a(); //http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/doubling/dbl-2009-l @@ -585,7 +440,7 @@ impl JacobianPoint { let y3 = &e * (&d - &x3) - &c.double().double().double(); // Y3 = E * (D - X3) - 8 * C let z3 = (y1 * z1).double(); // Z3 = 2 * Y1 * Z1 - JacobianPoint::new(x3, y3, z3) + Self::new([x3, y3, z3]) } else { // http://www.hyperelliptic.org/EFD/g1p/data/shortw/jacobian-0/doubling/dbl-2009-alnr // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l @@ -599,12 +454,83 @@ impl JacobianPoint { let y3 = m * (&s - &x3) - &yyyy.double().double().double(); // Y3 = M * (S - X3) - 8 * YYYY let z3 = (y1 + z1).square() - &yy - &zz; // Z3 = (Y1 + Z1)^2 - YY - ZZ - JacobianPoint::new(x3, y3, z3) + Self::new([x3, y3, z3]) } } - // Implementation taken from: - // https://github.com/mratsim/constantine/blob/65147ed815d96fa94a05d307c1d9980877b7d0e8/constantine/math/elliptic/ec_shortweierstrass_jacobian.md - pub fn operate_with(&self, other: &Self) -> Self { + + pub fn operate_with_affine(&self, other: &Self) -> Self { + let [x1, y1, z1] = self.coordinates(); + let [x2, y2, z2] = other.coordinates(); + + if *z2 != FieldElement::one() { + panic!("The second point must be in affine coordinates (Z = 1)"); + } + + if self.is_neutral_element() { + return other.clone(); + } + if other.is_neutral_element() { + return self.clone(); + } + + let z1z1 = z1.square(); + let u1 = x1; + let u2 = x2 * &z1z1; + let s1 = y1; + let s2 = y2 * z1 * &z1z1; + let h = &u2 - u1; + let hh = h.square(); + let hhh = &h * &hh; + let r = &s2 - s1; + let v = u1 * &hh; + let x3 = r.square() - &hhh - &v - &v; + let y3 = r * (&v - &x3) - s1 * &hhh; + let z3 = z1 * &h; + + Self::new([x3, y3, z3]) + } +} + +impl PartialEq for ShortWeierstrassJacobianPoint { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Eq for ShortWeierstrassJacobianPoint {} + +impl FromAffine for ShortWeierstrassJacobianPoint { + fn from_affine( + x: FieldElement, + y: FieldElement, + ) -> Result { + if E::defining_equation(&x, &y) != FieldElement::zero() { + Err(EllipticCurveError::InvalidPoint) + } else { + let coordinates = [x, y, FieldElement::one()]; + Ok(ShortWeierstrassJacobianPoint::new(coordinates)) + } + } +} + +impl IsGroup for ShortWeierstrassJacobianPoint { + /// The point at infinity. + fn neutral_element() -> Self { + Self::new([ + FieldElement::zero(), + FieldElement::one(), + FieldElement::zero(), + ]) + } + + fn is_neutral_element(&self) -> bool { + let pz = self.z(); + pz == &FieldElement::zero() + } + + /// Computes the addition of `self` and `other`. + /// https://github.com/mratsim/constantine/blob/65147ed815d96fa94a05d307c1d9980877b7d0e8/constantine/math/elliptic/ec_shortweierstrass_jacobian.md + fn operate_with(&self, other: &Self) -> Self { if self.is_neutral_element() { return other.clone(); } @@ -614,13 +540,8 @@ impl JacobianPoint { } // let a: FieldElement<::BaseField> = E::a(); - let x1 = &self.x; - let y1 = &self.y; - let z1 = &self.z; - - let x2 = &other.x; - let y2 = &other.y; - let z2 = &other.z; + let [x1, y1, z1] = self.coordinates(); + let [x2, y2, z2] = other.coordinates(); let z1_sq = z1.square(); // Z1^2 let z2_sq = z2.square(); // Z2^2 @@ -654,291 +575,64 @@ impl JacobianPoint { let mut z3 = (z1 + z2).square() - &z1_sq - &z2_sq; // Z3 = (Z1 + Z2)^2 - Z1^2 - Z2^2 z3 *= &h; // Z3 = H * Z3 = H * ((Z1 + Z2)^2 - Z1^2 - Z2^2) - Self::new(x3, y3, z3) + Self::new([x3, y3, z3]) } - pub fn operate_with_affine(&self, other: &Self) -> Self { - if other.z != FieldElement::one() { - panic!("The second point must be in affine coordinates (Z = 1)"); - } + /// Returns the additive inverse of the projective point `p` + fn neg(&self) -> Self { + let [x, y, z] = self.coordinates(); + Self::new([x.clone(), -y, z.clone()]) + } +} +// Delete until here +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + elliptic_curve::short_weierstrass::curves::bls12_381::curve::BLS12381Curve, + unsigned_integer::element::U256, + }; - let x1 = &self.x; - let y1 = &self.y; - let z1 = &self.z; - let x2 = &other.x; - let y2 = &other.y; + #[cfg(feature = "alloc")] + use crate::{ + elliptic_curve::short_weierstrass::curves::bls12_381::field_extension::BLS12381PrimeField, + field::element::FieldElement, + }; + pub const SUBGROUP_ORDER: U256 = U256::from_hex_unchecked( + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", + ); - if self.is_neutral_element() { - return other.clone(); - } - if other.is_neutral_element() { - return self.clone(); - } + pub const CURVE_COFACTOR: U256 = U256::from_hex_unchecked("0x396c8c005555e1568c00aaab0000aaab"); - let z1z1 = z1.square(); - let u1 = x1; - let u2 = x2 * &z1z1; - let s1 = y1; - let s2 = y2 * z1 * &z1z1; - let h = &u2 - u1; - let hh = h.square(); - let hhh = &h * &hh; - let r = &s2 - s1; - let v = u1 * &hh; - let x3 = r.square() - &hhh - &v - &v; - let y3 = r * (&v - &x3) - s1 * &hhh; - let z3 = z1 * &h; + #[cfg(feature = "alloc")] + #[allow(clippy::upper_case_acronyms)] + type FEE = FieldElement; - Self::new(x3, y3, z3) + #[cfg(feature = "alloc")] + fn point() -> ShortWeierstrassProjectivePoint { + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); + BLS12381Curve::create_point_from_affine(x, y).unwrap() } - pub fn negate(&self) -> Self { - Self { - x: self.x.clone(), - y: -self.y.clone(), - z: self.z.clone(), - } - } -} - -impl ShortWeierstrassJacobianPoint -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - /// Serialize the points in the given format - #[cfg(feature = "alloc")] - pub fn serialize(&self, point_format: PointFormat, endianness: Endianness) -> Vec { - let mut bytes: Vec = Vec::new(); - let x_bytes: Vec; - let y_bytes: Vec; - let z_bytes: Vec; - - match point_format { - PointFormat::Jacobian => { - let [x, y, z] = self.coordinates(); - if endianness == Endianness::BigEndian { - x_bytes = x.to_bytes_be(); - y_bytes = y.to_bytes_be(); - z_bytes = z.to_bytes_be(); - } else { - x_bytes = x.to_bytes_le(); - y_bytes = y.to_bytes_le(); - z_bytes = z.to_bytes_le(); - } - bytes.extend(&x_bytes); - bytes.extend(&y_bytes); - bytes.extend(&z_bytes); - } - PointFormat::Uncompressed => { - /*let affine_representation = self.to_affine(); - let [x, y, _z] = affine_representation.coordinates();*/ - let (x, y) = self.to_affine(); - if endianness == Endianness::BigEndian { - x_bytes = x.to_bytes_be(); - y_bytes = y.to_bytes_be(); - } else { - x_bytes = x.to_bytes_le(); - y_bytes = y.to_bytes_le(); - } - bytes.extend(&x_bytes); - bytes.extend(&y_bytes); - } - PointFormat::Projective => { - panic!("Projective format is not supported for ShortWeierstrassJacobianPoint"); - } - } - bytes - } - - pub fn deserialize( - bytes: &[u8], - point_format: PointFormat, - endianness: Endianness, - ) -> Result { - match point_format { - PointFormat::Jacobian => { - if bytes.len() % 3 != 0 { - return Err(DeserializationError::InvalidAmountOfBytes); - } - let len = bytes.len() / 3; - let x: FieldElement; - let y: FieldElement; - let z: FieldElement; - - if endianness == Endianness::BigEndian { - x = ByteConversion::from_bytes_be(&bytes[..len])?; - y = ByteConversion::from_bytes_be(&bytes[len..len * 2])?; - z = ByteConversion::from_bytes_be(&bytes[len * 2..])?; - } else { - x = ByteConversion::from_bytes_le(&bytes[..len])?; - y = ByteConversion::from_bytes_le(&bytes[len..len * 2])?; - z = ByteConversion::from_bytes_le(&bytes[len * 2..])?; - } - - let point = Self::new(x, y, z.clone()); - - if z == FieldElement::zero() { - if point.is_neutral_element() { - Ok(point) - } else { - Err(DeserializationError::FieldFromBytesError) - } - } else { - /* - let affine_point = point.to_affine(); - let x_affine = affine_point.x(); - let y_affine = affine_point.y(); - */ - let (x_affine, y_affine) = point.to_affine(); - if E::defining_equation(&x_affine, &y_affine) == FieldElement::zero() { - Ok(point) - } else { - Err(DeserializationError::FieldFromBytesError) - } - } - } - PointFormat::Uncompressed => { - if bytes.len() % 2 != 0 { - return Err(DeserializationError::InvalidAmountOfBytes); - } - let len = bytes.len() / 2; - let x: FieldElement; - let y: FieldElement; - - if endianness == Endianness::BigEndian { - x = ByteConversion::from_bytes_be(&bytes[..len])?; - y = ByteConversion::from_bytes_be(&bytes[len..])?; - } else { - x = ByteConversion::from_bytes_le(&bytes[..len])?; - y = ByteConversion::from_bytes_le(&bytes[len..])?; - } - if E::defining_equation(&x, &y) == FieldElement::zero() { - Ok(Self::new(x, y, FieldElement::one())) - } else { - Err(DeserializationError::FieldFromBytesError) - } - } - PointFormat::Projective => { - panic!("Projective format is not supported for ShortWeierstrassJacobianPoint"); - } - } - } -} - -#[cfg(feature = "alloc")] -impl AsBytes for ShortWeierstrassProjectivePoint -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn as_bytes(&self) -> alloc::vec::Vec { - self.serialize(PointFormat::Projective, Endianness::LittleEndian) - } -} - -#[cfg(feature = "alloc")] -impl From> for alloc::vec::Vec -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn from(value: ShortWeierstrassProjectivePoint) -> Self { - value.as_bytes() - } -} - -impl Deserializable for ShortWeierstrassProjectivePoint -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - Self::deserialize(bytes, PointFormat::Projective, Endianness::LittleEndian) - } -} - -#[cfg(feature = "alloc")] -impl AsBytes for ShortWeierstrassJacobianPoint -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn as_bytes(&self) -> alloc::vec::Vec { - self.serialize(PointFormat::Jacobian, Endianness::LittleEndian) - } -} - -#[cfg(feature = "alloc")] -impl From> for alloc::vec::Vec -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn from(value: ShortWeierstrassJacobianPoint) -> Self { - value.as_bytes() - } -} - -impl Deserializable for ShortWeierstrassJacobianPoint -where - E: IsShortWeierstrass, - FieldElement: ByteConversion, -{ - fn deserialize(bytes: &[u8]) -> Result - where - Self: Sized, - { - Self::deserialize(bytes, PointFormat::Jacobian, Endianness::LittleEndian) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - elliptic_curve::short_weierstrass::curves::bls12_381::curve::BLS12381Curve, - unsigned_integer::element::U256, - }; - - #[cfg(feature = "alloc")] - use crate::{ - elliptic_curve::short_weierstrass::curves::bls12_381::field_extension::BLS12381PrimeField, - field::element::FieldElement, - }; - pub const SUBGROUP_ORDER: U256 = U256::from_hex_unchecked( - "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", - ); - - pub const CURVE_COFACTOR: U256 = U256::from_hex_unchecked("0x396c8c005555e1568c00aaab0000aaab"); - - #[cfg(feature = "alloc")] - #[allow(clippy::upper_case_acronyms)] - type FEE = FieldElement; - - #[cfg(feature = "alloc")] - fn point() -> ShortWeierstrassProjectivePoint { - let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); - let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); - BLS12381Curve::create_point_from_affine(x, y).unwrap() + #[cfg(feature = "alloc")] + #[test] + fn operate_with_works_jacobian() { + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); + let p = ShortWeierstrassJacobianPoint::::from_affine(x, y).unwrap(); + + assert_eq!(p.operate_with(&p), p.double()); } #[cfg(feature = "alloc")] #[test] fn operate_with_self_works_jacobian() { - let p = JacobianPoint::from(point()); - assert_eq!(p.operate_with(&p), p.double()); - } + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); + let p = ShortWeierstrassJacobianPoint::::from_affine(x, y).unwrap(); - #[cfg(feature = "alloc")] - #[test] - fn double_is_equal_to_operate_with_self_jacobian() { - let g = BLS12381Curve::generator(); - let p = JacobianPoint::from(g); - assert_eq!(p.double(), p.operate_with(&p)); + assert_eq!(p.operate_with_self(3_u16), p.double().operate_with(&p)); } #[cfg(feature = "alloc")] #[test] @@ -954,20 +648,6 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_be_jacobian() { - let p = point(); - let expected_point = ShortWeierstrassJacobianPoint::::from(p); - let bytes_be = expected_point.serialize(PointFormat::Jacobian, Endianness::BigEndian); - let result = ShortWeierstrassJacobianPoint::deserialize( - &bytes_be, - PointFormat::Jacobian, - Endianness::BigEndian, - ); - assert_eq!(expected_point, result.unwrap()); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_be_uncompressed() { @@ -980,18 +660,6 @@ mod tests { ); assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_be_uncompressed_jacobian() { - let expected_point = ShortWeierstrassJacobianPoint::::from(point()); - let bytes_be = expected_point.serialize(PointFormat::Uncompressed, Endianness::BigEndian); - let result = ShortWeierstrassJacobianPoint::deserialize( - &bytes_be, - PointFormat::Uncompressed, - Endianness::BigEndian, - ); - assert_eq!(expected_point, result.unwrap()); - } #[cfg(feature = "alloc")] #[test] @@ -1007,20 +675,6 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_le_jacobian() { - let expected_point = ShortWeierstrassJacobianPoint::::from(point()); - let bytes_be = expected_point.serialize(PointFormat::Jacobian, Endianness::LittleEndian); - - let result = ShortWeierstrassJacobianPoint::deserialize( - &bytes_be, - PointFormat::Jacobian, - Endianness::LittleEndian, - ); - assert_eq!(expected_point, result.unwrap()); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_le_uncompressed() { @@ -1036,21 +690,6 @@ mod tests { assert_eq!(expected_point, result.unwrap()); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_le_uncompressed_jacobian() { - let expected_point = ShortWeierstrassJacobianPoint::::from(point()); - let bytes_be = - expected_point.serialize(PointFormat::Uncompressed, Endianness::LittleEndian); - - let result = ShortWeierstrassJacobianPoint::deserialize( - &bytes_be, - PointFormat::Uncompressed, - Endianness::LittleEndian, - ); - assert_eq!(expected_point, result.unwrap()); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_projective() { @@ -1068,24 +707,6 @@ mod tests { ); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_projective_jacobian() { - let bytes = ShortWeierstrassJacobianPoint::::from(point()) - .serialize(PointFormat::Jacobian, Endianness::LittleEndian); - - let result = ShortWeierstrassJacobianPoint::::deserialize( - &bytes, - PointFormat::Jacobian, - Endianness::BigEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::FieldFromBytesError - ); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_uncompressed() { @@ -1103,24 +724,6 @@ mod tests { ); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_with_mixed_le_and_be_does_not_work_uncompressed_jacobian() { - let bytes = ShortWeierstrassJacobianPoint::::from(point()) - .serialize(PointFormat::Uncompressed, Endianness::LittleEndian); - - let result = ShortWeierstrassJacobianPoint::::deserialize( - &bytes, - PointFormat::Uncompressed, - Endianness::BigEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::FieldFromBytesError - ); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_projective() { @@ -1138,24 +741,6 @@ mod tests { ); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_jacobian() { - let bytes = ShortWeierstrassJacobianPoint::::from(point()) - .serialize(PointFormat::Jacobian, Endianness::BigEndian); - - let result = ShortWeierstrassJacobianPoint::::deserialize( - &bytes, - PointFormat::Jacobian, - Endianness::LittleEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::FieldFromBytesError - ); - } - #[cfg(feature = "alloc")] #[test] fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_uncompressed() { @@ -1173,22 +758,6 @@ mod tests { ); } - #[cfg(feature = "alloc")] - #[test] - fn byte_conversion_from_and_to_with_mixed_be_and_le_does_not_work_uncompressed_jacobian() { - let bytes = point().serialize(PointFormat::Uncompressed, Endianness::BigEndian); - - let result = ShortWeierstrassProjectivePoint::::deserialize( - &bytes, - PointFormat::Uncompressed, - Endianness::LittleEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::FieldFromBytesError - ); - } #[test] fn cannot_create_point_from_wrong_number_of_bytes_le_projective() { let bytes = &[0_u8; 13]; @@ -1205,22 +774,6 @@ mod tests { ); } - #[test] - fn cannot_create_point_from_wrong_number_of_bytes_le_jacobian() { - let bytes = &[0_u8; 13]; - - let result = ShortWeierstrassJacobianPoint::::deserialize( - bytes, - PointFormat::Jacobian, - Endianness::LittleEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::InvalidAmountOfBytes - ); - } - #[test] fn cannot_create_point_from_wrong_number_of_bytes_le_uncompressed() { let bytes = &[0_u8; 13]; @@ -1237,22 +790,6 @@ mod tests { ); } - #[test] - fn cannot_create_point_from_wrong_number_of_bytes_le_uncompressed_jacobian() { - let bytes = &[0_u8; 13]; - - let result = ShortWeierstrassJacobianPoint::::deserialize( - bytes, - PointFormat::Uncompressed, - Endianness::LittleEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::InvalidAmountOfBytes - ); - } - #[test] fn cannot_create_point_from_wrong_number_of_bytes_be_projective() { let bytes = &[0_u8; 13]; @@ -1269,22 +806,6 @@ mod tests { ); } - #[test] - fn cannot_create_point_from_wrong_number_of_bytes_be_jacobian() { - let bytes = &[0_u8; 13]; - - let result = ShortWeierstrassJacobianPoint::::deserialize( - bytes, - PointFormat::Jacobian, - Endianness::BigEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::InvalidAmountOfBytes - ); - } - #[test] fn cannot_create_point_from_wrong_number_of_bytes_be_uncompressed() { let bytes = &[0_u8; 13]; @@ -1301,51 +822,38 @@ mod tests { ); } - #[test] - fn cannot_create_point_from_wrong_number_of_bytes_be_uncompressed_jacobian() { - let bytes = &[0_u8; 13]; - - let result = ShortWeierstrassJacobianPoint::::deserialize( - bytes, - PointFormat::Uncompressed, - Endianness::BigEndian, - ); - - assert_eq!( - result.unwrap_err(), - DeserializationError::InvalidAmountOfBytes - ); - } - #[test] fn test_jacobian_vs_projective_operation() { - let p1 = point(); - let p2 = point(); + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); - // Convert into jacobian coordinates - let j1 = ShortWeierstrassJacobianPoint::::from(p1.clone()); - let j2 = ShortWeierstrassJacobianPoint::::from(p2.clone()); + let p = ShortWeierstrassJacobianPoint::::from_affine(x.clone(), y.clone()) + .unwrap(); + let q = ShortWeierstrassProjectivePoint::::from_affine(x, y).unwrap(); - // - let sum_jacobian = j1.operate_with(&j2); + let sum_jacobian = p.operate_with_self(2_u16); + let sum_projective = q.operate_with_self(2_u16); // Convert the result to affine coordinates - let (x_j, y_j) = sum_jacobian.to_affine(); - - // - let sum_projective = p1.operate_with(&p2); + let sum_jacobian_affine = sum_jacobian.to_affine(); + let [x_j, y_j, _] = sum_jacobian_affine.coordinates(); // Convert the result to affine coordinates let binding = sum_projective.to_affine(); let [x_p, y_p, _] = binding.coordinates(); - assert_eq!(x_j, *x_p, "x coordintates do not match"); - assert_eq!(y_j, *y_p, "y coordinates do not match"); + assert_eq!(x_j, x_p, "x coordintates do not match"); + assert_eq!(y_j, y_p, "y coordinates do not match"); } #[test] fn test_multiplication_by_order_projective() { - let p = ShortWeierstrassProjectivePoint::::from(point()); + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); + + let p = ShortWeierstrassProjectivePoint::::from_affine(x.clone(), y.clone()) + .unwrap(); + let g = p .operate_with_self(SUBGROUP_ORDER) .operate_with_self(CURVE_COFACTOR); @@ -1356,20 +864,22 @@ mod tests { ); } /* - #[test] - fn test_multiplication_by_order_jacobian() { - let p = ShortWeierstrassJacobianPoint::::from(point()); - let g = p - .operate_with_self(SUBGROUP_ORDER) - .operate_with_self(CURVE_COFACTOR); - - assert!( - g.is_neutral_element(), - "Multiplication by order should result in the neutral element" - ); - }*/ + /// Need to work on this, it is not working but i am not sure why + #[test] + fn test_multiplication_by_order_jacobian() { + let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5"); + let y = FEE::new_base("7acf6e49cc000ff53b06ee1d27056734019c0a1edfa16684da41ebb0c56750f73bc1b0eae4c6c241808a5e485af0ba0"); + + let p = ShortWeierstrassJacobianPoint::::from_affine(x.clone(), y.clone()) + .unwrap(); + let g = p + .operate_with_self(SUBGROUP_ORDER) + .operate_with_self(CURVE_COFACTOR); + + assert!( + g.is_neutral_element(), + "Multiplication by order should result in the neutral element" + ); + } + */ } - -/* -multiplicar por orden me de punto en infinito -*/