|
1 |
| -use super::field_extension::{BLS12381PrimeField, Degree2ExtensionField}; |
| 1 | +use super::{ |
| 2 | + field_extension::{BLS12381PrimeField, Degree2ExtensionField}, |
| 3 | + twist::BLS12381TwistCurve, |
| 4 | +}; |
| 5 | +use crate::cyclic_group::IsGroup; |
2 | 6 | use crate::elliptic_curve::short_weierstrass::point::ShortWeierstrassProjectivePoint;
|
3 | 7 | use crate::elliptic_curve::traits::IsEllipticCurve;
|
| 8 | +use crate::unsigned_integer::element::U256; |
4 | 9 | use crate::{
|
5 | 10 | elliptic_curve::short_weierstrass::traits::IsShortWeierstrass, field::element::FieldElement,
|
6 | 11 | };
|
7 | 12 |
|
| 13 | +pub const SUBGROUP_ORDER: U256 = |
| 14 | + U256::from_hex_unchecked("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); |
| 15 | + |
8 | 16 | pub type BLS12381FieldElement = FieldElement<BLS12381PrimeField>;
|
9 | 17 | pub type BLS12381TwistCurveFieldElement = FieldElement<Degree2ExtensionField>;
|
10 | 18 |
|
@@ -35,18 +43,111 @@ impl IsShortWeierstrass for BLS12381Curve {
|
35 | 43 | }
|
36 | 44 | }
|
37 | 45 |
|
| 46 | +/// This is equal to the frobenius trace of the BLS12 381 curve minus one or seed value z. |
| 47 | +pub const MILLER_LOOP_CONSTANT: u64 = 0xd201000000010000; |
| 48 | + |
| 49 | +/// 𝛽 : primitive cube root of unity of 𝐹ₚ that §satisfies the minimal equation |
| 50 | +/// 𝛽² + 𝛽 + 1 = 0 mod 𝑝 |
| 51 | +pub const CUBE_ROOT_OF_UNITY_G1: BLS12381FieldElement = FieldElement::from_hex_unchecked( |
| 52 | + "5f19672fdf76ce51ba69c6076a0f77eaddb3a93be6f89688de17d813620a00022e01fffffffefffe", |
| 53 | +); |
| 54 | + |
| 55 | +/// x-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E |
| 56 | +pub const ENDO_U: BLS12381TwistCurveFieldElement = |
| 57 | +BLS12381TwistCurveFieldElement::const_from_raw([ |
| 58 | + FieldElement::from_hex_unchecked("0"), |
| 59 | + FieldElement::from_hex_unchecked("1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad") |
| 60 | +]); |
| 61 | + |
| 62 | +/// y-coordinate of 𝜁 ∘ 𝜋_q ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E |
| 63 | +pub const ENDO_V: BLS12381TwistCurveFieldElement = |
| 64 | +BLS12381TwistCurveFieldElement::const_from_raw([ |
| 65 | + FieldElement::from_hex_unchecked("135203e60180a68ee2e9c448d77a2cd91c3dedd930b1cf60ef396489f61eb45e304466cf3e67fa0af1ee7b04121bdea2"), |
| 66 | + FieldElement::from_hex_unchecked("6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09") |
| 67 | +]); |
| 68 | + |
| 69 | +impl ShortWeierstrassProjectivePoint<BLS12381Curve> { |
| 70 | + /// Returns 𝜙(P) = (𝑥, 𝑦) ⇒ (𝛽𝑥, 𝑦), where 𝛽 is the Cube Root of Unity in the base prime field |
| 71 | + /// https://eprint.iacr.org/2022/352.pdf 2 Preliminaries |
| 72 | + fn phi(&self) -> Self { |
| 73 | + // This clone is unsightly |
| 74 | + let mut a = self.clone(); |
| 75 | + a.0.value[0] = a.x() * CUBE_ROOT_OF_UNITY_G1; |
| 76 | + a |
| 77 | + } |
| 78 | + |
| 79 | + /// 𝜙(P) = −𝑢²P |
| 80 | + /// https://eprint.iacr.org/2022/352.pdf 4.3 Prop. 4 |
| 81 | + pub fn is_in_subgroup(&self) -> bool { |
| 82 | + self.operate_with_self(MILLER_LOOP_CONSTANT) |
| 83 | + .operate_with_self(MILLER_LOOP_CONSTANT) |
| 84 | + .neg() |
| 85 | + == self.phi() |
| 86 | + } |
| 87 | +} |
| 88 | + |
| 89 | +impl ShortWeierstrassProjectivePoint<BLS12381TwistCurve> { |
| 90 | + /// 𝜓(P) = 𝜁 ∘ 𝜋ₚ ∘ 𝜁⁻¹, where 𝜁 is the isomorphism u:E'(𝔽ₚ₆) −> E(𝔽ₚ₁₂) from the twist to E,, 𝜋ₚ is the p-power frobenius endomorphism |
| 91 | + /// and 𝜓 satisifies minmal equation 𝑋² + 𝑡𝑋 + 𝑞 = 𝑂 |
| 92 | + /// https://eprint.iacr.org/2022/352.pdf 4.2 (7) |
| 93 | + fn psi(&self) -> Self { |
| 94 | + let [x, y, z] = self.coordinates(); |
| 95 | + Self::new([ |
| 96 | + x.conjugate() * ENDO_U, |
| 97 | + y.conjugate() * ENDO_V, |
| 98 | + z.conjugate(), |
| 99 | + ]) |
| 100 | + } |
| 101 | + |
| 102 | + /// 𝜓(P) = 𝑢P, where 𝑢 = SEED of the curve |
| 103 | + /// https://eprint.iacr.org/2022/352.pdf 4.2 |
| 104 | + pub fn is_in_subgroup(&self) -> bool { |
| 105 | + self.psi() == self.operate_with_self(MILLER_LOOP_CONSTANT).neg() |
| 106 | + } |
| 107 | +} |
| 108 | + |
38 | 109 | #[cfg(test)]
|
39 | 110 | mod tests {
|
40 | 111 | use super::*;
|
41 | 112 | use crate::{
|
42 |
| - cyclic_group::IsGroup, elliptic_curve::traits::EllipticCurveError, |
| 113 | + cyclic_group::IsGroup, |
| 114 | + elliptic_curve::{ |
| 115 | + short_weierstrass::curves::bls12_381::field_extension::BLS12381_PRIME_FIELD_ORDER, |
| 116 | + traits::EllipticCurveError, |
| 117 | + }, |
43 | 118 | field::element::FieldElement,
|
| 119 | + unsigned_integer::element::U384, |
44 | 120 | };
|
45 | 121 |
|
46 |
| - use super::BLS12381Curve; |
| 122 | + // -15132376222941642751 = MILLER_LOOP_CONSTANT + 1 = -d20100000000ffff |
| 123 | + // we want the positive of this coordinate based on x^2 - tx + q |
| 124 | + pub const TRACE_OF_FROBENIUS: U256 = U256::from_u64(15132376222941642751); |
| 125 | + |
| 126 | + const ENDO_U_2: BLS12381TwistCurveFieldElement = |
| 127 | + BLS12381TwistCurveFieldElement::const_from_raw([ |
| 128 | + FieldElement::from_hex_unchecked("1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaac"), |
| 129 | + FieldElement::from_hex_unchecked("0") |
| 130 | + ]); |
| 131 | + |
| 132 | + const ENDO_V_2: BLS12381TwistCurveFieldElement = |
| 133 | + BLS12381TwistCurveFieldElement::const_from_raw([ |
| 134 | + FieldElement::from_hex_unchecked("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa"), |
| 135 | + FieldElement::from_hex_unchecked("0") |
| 136 | + ]); |
| 137 | + |
| 138 | + // Cmoputes the psi^2() 'Untwist Frobenius Endomorphism' |
| 139 | + fn psi_square( |
| 140 | + p: &ShortWeierstrassProjectivePoint<BLS12381TwistCurve>, |
| 141 | + ) -> ShortWeierstrassProjectivePoint<BLS12381TwistCurve> { |
| 142 | + let [x, y, z] = p.coordinates(); |
| 143 | + // Since power of frobenius map is 2 we apply once as applying twice is inverse |
| 144 | + ShortWeierstrassProjectivePoint::new([x * ENDO_U_2, y * ENDO_V_2, z.clone()]) |
| 145 | + } |
47 | 146 |
|
48 | 147 | #[allow(clippy::upper_case_acronyms)]
|
49 | 148 | type FEE = FieldElement<BLS12381PrimeField>;
|
| 149 | + #[allow(clippy::upper_case_acronyms)] |
| 150 | + type FTE = FieldElement<Degree2ExtensionField>; |
50 | 151 |
|
51 | 152 | fn point_1() -> ShortWeierstrassProjectivePoint<BLS12381Curve> {
|
52 | 153 | let x = FEE::new_base("36bb494facde72d0da5c770c4b16d9b2d45cfdc27604a25a1a80b020798e5b0dbd4c6d939a8f8820f042a29ce552ee5");
|
@@ -117,4 +218,74 @@ mod tests {
|
117 | 218 | g.operate_with_self(3_u16)
|
118 | 219 | );
|
119 | 220 | }
|
| 221 | + |
| 222 | + #[test] |
| 223 | + fn generator_g1_is_in_subgroup() { |
| 224 | + let g = BLS12381Curve::generator(); |
| 225 | + assert!(g.is_in_subgroup()) |
| 226 | + } |
| 227 | + |
| 228 | + #[test] |
| 229 | + fn arbitrary_g1_point_is_in_subgroup() { |
| 230 | + let g = BLS12381Curve::generator().operate_with_self(32u64); |
| 231 | + assert!(g.is_in_subgroup()) |
| 232 | + } |
| 233 | + |
| 234 | + //TODO |
| 235 | + #[test] |
| 236 | + fn arbitrary_g1_point_not_in_subgroup() { |
| 237 | + let x = FEE::new_base("178212cbe4a3026c051d4f867364b3ea84af623f93233b347ffcd3d6b16f16e0a7aedbe1c78d33c6beca76b2b75c8486"); |
| 238 | + let y = FEE::new_base("13a8b1347e5b43bc4051754b2a29928b5df78cf03ca3b1f73d0424b09fccdef116c9f0ecbec7420a99b2dd785209e9d"); |
| 239 | + let p = BLS12381Curve::create_point_from_affine(x, y).unwrap(); |
| 240 | + assert!(!p.is_in_subgroup()) |
| 241 | + } |
| 242 | + |
| 243 | + #[test] |
| 244 | + fn generator_g2_is_in_subgroup() { |
| 245 | + let g = BLS12381TwistCurve::generator(); |
| 246 | + assert!(g.is_in_subgroup()) |
| 247 | + } |
| 248 | + |
| 249 | + #[test] |
| 250 | + fn arbitrary_g2_point_is_in_subgroup() { |
| 251 | + let g = BLS12381TwistCurve::generator().operate_with_self(32u64); |
| 252 | + assert!(g.is_in_subgroup()) |
| 253 | + } |
| 254 | + |
| 255 | + //`TODO` |
| 256 | + #[test] |
| 257 | + fn arbitrary_g2_point_not_in_subgroup() { |
| 258 | + let x = FTE::new([ |
| 259 | + FEE::new(U384::from_hex_unchecked("97798b4a61ac301bbee71e36b5174e2f4adfe3e1729bdae1fcc9965ae84181be373aa80414823eed694f1270014012d")), |
| 260 | + FEE::new(U384::from_hex_unchecked("c9852cc6e61868966249aec153b50b29b3c22409f4c7880fd13121981c103c8ef84d9ea29b552431360e82cf69219fa")) |
| 261 | + ]); |
| 262 | + let y = FTE::new([ |
| 263 | + FEE::new(U384::from_hex_unchecked("16cb3a60f3fa52c8273aceeb94c4c7303e8074aa9eedec7355bbb1e8cceedd4ec1497f573f62822140377b8e339619ed")), |
| 264 | + FEE::new(U384::from_hex_unchecked("1cd919b08afe06bebe9adf6223a55868a6fd8b77efc5c67b60fff39be36e9b44b7f10db16827c83b43ad2dad1947778")) |
| 265 | + ]); |
| 266 | + |
| 267 | + let p = BLS12381TwistCurve::create_point_from_affine(x, y).unwrap(); |
| 268 | + assert!(!p.is_in_subgroup()) |
| 269 | + } |
| 270 | + |
| 271 | + #[test] |
| 272 | + fn g2_conjugate_works() { |
| 273 | + let a = FTE::zero(); |
| 274 | + let mut expected = a.conjugate(); |
| 275 | + expected = expected.conjugate(); |
| 276 | + |
| 277 | + assert_eq!(a, expected); |
| 278 | + } |
| 279 | + |
| 280 | + #[test] |
| 281 | + fn untwist_morphism_has_minimal_poly() { |
| 282 | + // generator |
| 283 | + let p = BLS12381TwistCurve::generator(); |
| 284 | + let psi_square = psi_square(&p); |
| 285 | + let tx = p.psi().operate_with_self(TRACE_OF_FROBENIUS).neg(); |
| 286 | + let q = p.operate_with_self(BLS12381_PRIME_FIELD_ORDER); |
| 287 | + // Minimal Polynomial of Untwist Frobenius Endomorphism: X^2 + tX + q, where X = psh(P) -> psi(p)^2 - t * psi(p) + q * p = 0 |
| 288 | + let min_poly = psi_square.operate_with(&tx.neg()).operate_with(&q); |
| 289 | + assert!(min_poly.is_neutral_element()) |
| 290 | + } |
120 | 291 | }
|
0 commit comments