diff --git a/src/hash_to_curve.rs b/src/hash_to_curve.rs index 7605ec6a..b4d19b86 100644 --- a/src/hash_to_curve.rs +++ b/src/hash_to_curve.rs @@ -1,15 +1,13 @@ #![allow(clippy::op_ref)] use ff::{Field, FromUniformBytes, PrimeField}; -use group::Group; use pasta_curves::arithmetic::CurveExt; use static_assertions::const_assert; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use crate::{ ff_ext::Legendre, - secp256k1::{IsoSecp256k1, Secp256k1}, - utils::fe_from_str, + secp256k1::{iso_map_secp256k1, IsoSecp256k1, Secp256k1}, }; /// Hashes over a message and writes the output to all of `buf`. @@ -195,72 +193,6 @@ pub(crate) fn sswu_hash_to_curve_secp256k1<'a>( }) } -/// 3-Isogeny Map for Secp256k1 -/// Reference: -pub fn iso_map_secp256k1(rp: IsoSecp256k1) -> Secp256k1 { - // constants for secp256k1 iso_map computation - const K: [[&str; 4]; 5] = [ - ["0x00", "0x00", "0x00", "0x00"], - [ - "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa8c7", - "0x7d3d4c80bc321d5b9f315cea7fd44c5d595d2fc0bf63b92dfff1044f17c6581", - "0x534c328d23f234e6e2a413deca25caece4506144037c40314ecbd0b53d9dd262", - "0x8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38daaaaa88c", - ], - [ - "0xd35771193d94918a9ca34ccbb7b640dd86cd409542f8487d9fe6b745781eb49b", - "0xedadc6f64383dc1df7c4b2d51b54225406d36b641f5e41bbc52a56612a8c6d14", - "0x00", - "0x00", - ], - [ - "0x4bda12f684bda12f684bda12f684bda12f684bda12f684bda12f684b8e38e23c", - "0xc75e0c32d5cb7c0fa9d0a54b12a0a6d5647ab046d686da6fdffc90fc201d71a3", - "0x29a6194691f91a73715209ef6512e576722830a201be2018a765e85a9ecee931", - "0x2f684bda12f684bda12f684bda12f684bda12f684bda12f684bda12f38e38d84", - ], - [ - "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffff93b", - "0x7a06534bb8bdb49fd5e9e6632722c2989467c1bfc8e8d978dfb425d2685c2573", - "0x6484aa716545ca2cf3a70c3fa8fe337e0a3d21162f0d6299a7bf8192bfd2a76f", - "0x00", - ], - ]; - let mut k: [[::Base; 4]; 5] = [[fe_from_str("0x00"); 4]; 5]; - for i in 1..5 { - for j in 0..4 { - k[i][j] = fe_from_str(K[i][j]); - } - } - - // convert to affine form: (x, y) = (X/Z, Y/Z) - let (x, y) = { - let z_inv = rp.z.invert().unwrap(); - (rp.x * z_inv, rp.y * z_inv) - }; - - // iso_map logic - let x_squared = x.square(); - let x_cubed = x * x_squared; - - let x_num = k[1][3] * x_cubed + k[1][2] * x_squared + k[1][1] * x + k[1][0]; - let x_den = x_squared + k[2][1] * x + k[2][0]; - - let y_num = k[3][3] * x_cubed + k[3][2] * x_squared + k[3][1] * x + k[3][0]; - let y_den = x_cubed + k[4][2] * x_squared + k[4][1] * x + k[4][0]; - - // exceptional case MUST return identity - // reference: - if x_den.is_zero().into() || y_den.is_zero().into() { - return Secp256k1::identity(); - } - - let x = x_num * x_den.invert().unwrap(); - let y = y * (y_num * y_den.invert().unwrap()); - - Secp256k1::new_jacobian(x, y, ::Base::ONE).unwrap() -} - #[allow(clippy::too_many_arguments)] pub(crate) fn svdw_map_to_curve( u: C::Base, diff --git a/src/secp256k1/curve.rs b/src/secp256k1/curve.rs index fdc6fb89..a93f75f9 100644 --- a/src/secp256k1/curve.rs +++ b/src/secp256k1/curve.rs @@ -124,7 +124,7 @@ impl group::cofactor::CofactorGroup for IsoSecp256k1 { } new_curve_impl!( - (pub), + (pub(crate)), IsoSecp256k1, IsoSecp256k1Affine, true, @@ -149,6 +149,130 @@ impl IsoSecp256k1 { ]); } +/// 3-Isogeny Map for Secp256k1 +/// Reference: +pub(crate) fn iso_map_secp256k1(rp: IsoSecp256k1) -> Secp256k1 { + // constants for secp256k1 iso_map computation + const K: [[Fp; 4]; 5] = [ + [Fp::ZERO; 4], + [ + Fp([ + 0x8e38e38daaaaa8c7, + 0x38e38e38e38e38e3, + 0xe38e38e38e38e38e, + 0x8e38e38e38e38e38, + ]), + Fp([ + 0xdfff1044f17c6581, + 0xd595d2fc0bf63b92, + 0xb9f315cea7fd44c5, + 0x7d3d4c80bc321d5, + ]), + Fp([ + 0x4ecbd0b53d9dd262, + 0xe4506144037c4031, + 0xe2a413deca25caec, + 0x534c328d23f234e6, + ]), + Fp([ + 0x8e38e38daaaaa88c, + 0x38e38e38e38e38e3, + 0xe38e38e38e38e38e, + 0x8e38e38e38e38e38, + ]), + ], + [ + Fp([ + 0x9fe6b745781eb49b, + 0x86cd409542f8487d, + 0x9ca34ccbb7b640dd, + 0xd35771193d94918a, + ]), + Fp([ + 0xc52a56612a8c6d14, + 0x06d36b641f5e41bb, + 0xf7c4b2d51b542254, + 0xedadc6f64383dc1d, + ]), + Fp::ZERO, + Fp::ZERO, + ], + [ + Fp([ + 0xa12f684b8e38e23c, + 0x2f684bda12f684bd, + 0x684bda12f684bda1, + 0x4bda12f684bda12f, + ]), + Fp([ + 0xdffc90fc201d71a3, + 0x647ab046d686da6f, + 0xa9d0a54b12a0a6d5, + 0xc75e0c32d5cb7c0f, + ]), + Fp([ + 0xa765e85a9ecee931, + 0x722830a201be2018, + 0x715209ef6512e576, + 0x29a6194691f91a73, + ]), + Fp([ + 0x84bda12f38e38d84, + 0xbda12f684bda12f6, + 0xa12f684bda12f684, + 0x2f684bda12f684bd, + ]), + ], + [ + Fp([ + 0xfffffffefffff93b, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + ]), + Fp([ + 0xdfb425d2685c2573, + 0x9467c1bfc8e8d978, + 0xd5e9e6632722c298, + 0x7a06534bb8bdb49f, + ]), + Fp([ + 0xa7bf8192bfd2a76f, + 0x0a3d21162f0d6299, + 0xf3a70c3fa8fe337e, + 0x6484aa716545ca2c, + ]), + Fp::ZERO, + ], + ]; + + // Convert to affine coordinates: + let coords = ::AffineExt::coordinates(&rp.into()).unwrap(); + let x = coords.x(); + let y = coords.y(); + + // iso_map logic + let x_squared = x.square(); + let x_cubed = x * x_squared; + + let x_num = K[1][3] * x_cubed + K[1][2] * x_squared + K[1][1] * x + K[1][0]; + let x_den = x_squared + K[2][1] * x + K[2][0]; + + let y_num = K[3][3] * x_cubed + K[3][2] * x_squared + K[3][1] * x + K[3][0]; + let y_den = x_cubed + K[4][2] * x_squared + K[4][1] * x + K[4][0]; + + // exceptional case MUST return identity + // reference: + if x_den.is_zero().into() || y_den.is_zero().into() { + return Secp256k1::identity(); + } + + let x = x_num * x_den.invert().unwrap(); + let y = y * (y_num * y_den.invert().unwrap()); + + Secp256k1::new_jacobian(x, y, ::Base::ONE).unwrap() +} + #[cfg(test)] mod tests { use super::*;