From 45bac916af81fbf8cd15484150aaff5ae6d2b109 Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Wed, 23 Oct 2024 23:50:44 +0200 Subject: [PATCH] gt: fix aliasing issue in mixed torus multiplication --- constantine/math/pairings/gt_prj.nim | 13 +++- tests/math_pairings/t_gt_prj.nim | 85 +++++++++++++++++++++- tests/math_pairings/t_pairing_template.nim | 3 +- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/constantine/math/pairings/gt_prj.nim b/constantine/math/pairings/gt_prj.nim index 1be315be..1f7001db 100644 --- a/constantine/math/pairings/gt_prj.nim +++ b/constantine/math/pairings/gt_prj.nim @@ -333,7 +333,7 @@ proc fromTorus2_vartime*[F](r: var QuadraticExt[F], a: T2Aff[F]) = # Special case identity element if bool a.isNeutral(): - r.setNeutral() + r.setOne() return var num {.noInit.}, den {.noInit.}: typeof(r) @@ -380,13 +380,14 @@ proc mixedProd_vartime*[F](r: var T2Prj[F], a: T2Prj[F], b: T2Aff[F]) = r = a return - var u0 {.noInit.}, u1 {.noInit.}: F + var u0 {.noInit.}, u1 {.noInit.}, t{.noInit.}: F u0.prod(a.x, F b) u1.prod(a.z, F b) + t.prod(a.z, NonResidue) - r.x.prod(a.z, NonResidue) - r.x += u0 + # Aliasing: a.x must be read before r.x is written to r.z.sum(u1, a.x) + r.x.sum(u0, t) proc affineProd_vartime*[F](r: var T2Prj[F], a, b: T2Aff[F]) = @@ -535,6 +536,10 @@ proc batchFromTorus2_vartime*[F](dst: var openArray[QuadraticExt[F]], t.conj(QF src[0]) dst[0] *= t +func toHex*[F](a: T2Aff[F] or T2Prj[F], indent = 0, order: static Endianness = bigEndian): string = + var t {.noInit.}: QuadraticExt[F] + t.fromTorus2_vartime(a) + t.toHex(indent, order) when isMainModule: var a, c: QuadraticExt[Fp6[BLS12_381]] diff --git a/tests/math_pairings/t_gt_prj.nim b/tests/math_pairings/t_gt_prj.nim index 46ae93cf..4e0c4980 100644 --- a/tests/math_pairings/t_gt_prj.nim +++ b/tests/math_pairings/t_gt_prj.nim @@ -181,7 +181,7 @@ suite "Torus-based Cryptography for 𝔾ₜ, T₂(𝔽p6) compression": var r_tprj: T2Prj[Fp6[Name]] a_taff.fromGT_vartime(a) b_taff.fromGT_vartime(b) - r_tprj.affineProd(a_taff, b_taff) + r_tprj.affineProd_vartime(a_taff, b_taff) var r_gt: MyFp12 r_gt.prod(a, b) @@ -207,7 +207,34 @@ suite "Torus-based Cryptography for 𝔾ₜ, T₂(𝔽p6) compression": var a_tprj, r_tprj: T2Prj[Fp6[Name]] a_tprj.fromGT_vartime(a) b_taff.fromGT_vartime(b) - r_tprj.mixedProd(a_tprj, b_taff) + r_tprj.mixedProd_vartime(a_tprj, b_taff) + + var r_gt: MyFp12 + r_gt.prod(a, b) + + var r: MyFp12 + r.fromTorus2_vartime(r_tprj) + + doAssert bool r == r_gt + + test(BN254_Nogami) + # test(BN254_Snarks) + test(BLS12_381) + + test "T₂prj(𝔽p6) <- T₂prj(𝔽p6) * T₂aff(𝔽p6) - with aliasing": + proc test(Name: static Algebra) = + for i in 0 ..< Fp6iters: + type MyFp12 = QuadraticExt[Fp6[Name]] # Even if we choose to Fp2 -> Fp4 -> Fp12 + # we want this test to pass + let a = rng.random_gt(MyFp12) + let b = rng.random_gt(MyFp12) + + var b_taff: T2Aff[Fp6[Name]] + var a_tprj, r_tprj: T2Prj[Fp6[Name]] + a_tprj.fromGT_vartime(a) + b_taff.fromGT_vartime(b) + r_tprj = a_tprj + r_tprj.mixedProd_vartime(r_tprj, b_taff) var r_gt: MyFp12 r_gt.prod(a, b) @@ -246,6 +273,58 @@ suite "Torus-based Cryptography for 𝔾ₜ, T₂(𝔽p6) compression": # test(BN254_Snarks) test(BLS12_381) + test "T₂prj(𝔽p6) <- T₂prj(𝔽p6) * T₂prj(𝔽p6) - with aliasing of lhs": + proc test(Name: static Algebra) = + for i in 0 ..< Fp6iters: + type MyFp12 = QuadraticExt[Fp6[Name]] # Even if we choose to Fp2 -> Fp4 -> Fp12 + # we want this test to pass + let a = rng.random_gt(MyFp12) + let b = rng.random_gt(MyFp12) + + var a_tprj, b_tprj, r_tprj: T2Prj[Fp6[Name]] + a_tprj.fromGT_vartime(a) + b_tprj.fromGT_vartime(b) + r_tprj = a_tprj + r_tprj.prod(r_tprj, b_tprj) + + var r_gt: MyFp12 + r_gt.prod(a, b) + + var r: MyFp12 + r.fromTorus2_vartime(r_tprj) + + doAssert bool r == r_gt + + test(BN254_Nogami) + # test(BN254_Snarks) + test(BLS12_381) + + test "T₂prj(𝔽p6) <- T₂prj(𝔽p6) * T₂prj(𝔽p6) - with aliasing of rhs": + proc test(Name: static Algebra) = + for i in 0 ..< Fp6iters: + type MyFp12 = QuadraticExt[Fp6[Name]] # Even if we choose to Fp2 -> Fp4 -> Fp12 + # we want this test to pass + let a = rng.random_gt(MyFp12) + let b = rng.random_gt(MyFp12) + + var a_tprj, b_tprj, r_tprj: T2Prj[Fp6[Name]] + a_tprj.fromGT_vartime(a) + b_tprj.fromGT_vartime(b) + r_tprj = b_tprj + r_tprj.prod(a_tprj, r_tprj) + + var r_gt: MyFp12 + r_gt.prod(a, b) + + var r: MyFp12 + r.fromTorus2_vartime(r_tprj) + + doAssert bool r == r_gt + + test(BN254_Nogami) + # test(BN254_Snarks) + test(BLS12_381) + # ==================================================================================== test "T₂prj(𝔽p6) <- T₂aff(𝔽p6)²": @@ -258,7 +337,7 @@ suite "Torus-based Cryptography for 𝔾ₜ, T₂(𝔽p6) compression": var a_taff: T2Aff[Fp6[Name]] var r_tprj: T2Prj[Fp6[Name]] a_taff.fromGT_vartime(a) - r_tprj.affineSquare(a_taff) + r_tprj.affineSquare_vartime(a_taff) var r_gt: MyFp12 r_gt.square(a) diff --git a/tests/math_pairings/t_pairing_template.nim b/tests/math_pairings/t_pairing_template.nim index 6d9482ba..e8f798c2 100644 --- a/tests/math_pairings/t_pairing_template.nim +++ b/tests/math_pairings/t_pairing_template.nim @@ -151,6 +151,7 @@ proc runGTsubgroupTests*(GT: typedesc, iters: int) = func random_gt(rng: var RngState, F: typedesc, gen: RandomGen): F {.noInit.} = result = rng.random_elem(F, gen) result.finalExp() + debug: doAssert bool result.isInPairingSubgroup() proc runGTexponentiationTests*(GT: typedesc, iters: int) = var rng: RngState @@ -217,7 +218,7 @@ proc runGTexponentiationTests*(GT: typedesc, iters: int) = proc runGTmultiexpTests*[N: static int](GT: typedesc, num_points: array[N, int], iters: int) = var rng: RngState - let timeseed = 1727299797 # uint32(toUnix(getTime()) and (1'i64 shl 32 - 1)) # unixTime mod 2^32 + let timeseed = uint32(toUnix(getTime()) and (1'i64 shl 32 - 1)) # unixTime mod 2^32 seed(rng, timeseed) echo "\n------------------------------------------------------\n" echo "test_pairing_",$GT.Name,"_gt_multiexp xoshiro512** seed: ", timeseed