diff options
author | Ryan Rueger <git@rueg.re> | 2025-04-30 18:26:40 +0200 |
---|---|---|
committer | Ryan Rueger <git@rueg.re> | 2025-06-10 13:10:04 +0200 |
commit | 1f7e7d968ea1827459f7092abcf48ca83fe25a79 (patch) | |
tree | a6d096edb8c7790dc8bc42ce17f0c77efd5977dd /basis_sampling.py | |
parent | cb6080eaa4f326d9fce5f0a9157be46e91d55e09 (diff) | |
download | pegasis-1f7e7d968ea1827459f7092abcf48ca83fe25a79.tar.gz pegasis-1f7e7d968ea1827459f7092abcf48ca83fe25a79.tar.bz2 pegasis-1f7e7d968ea1827459f7092abcf48ca83fe25a79.zip |
Co-Authored-By: Pierrick Dartois <pierrickdartois@icloud.com>
Co-Authored-By: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com
Co-Authored-By: Boris Fouotsa <tako.fouotsa@epfl.ch>
Co-Authored-By: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com>
Co-Authored-By: Arthur Herlédan Le Merdy <ahlm@riseup.net>
Co-Authored-By: Riccardo Invernizzi <nidadoni@gmail.com>
Co-Authored-By: Damien Robert <Damien.Olivier.Robert+git@gmail.com>
Co-Authored-By: Ryan Rueger <git@rueg.re>
Co-Authored-By: Frederik Vercauteren <frederik.vercauteren@gmail.com>
Co-Authored-By: Benjamin Wesolowski <benjamin@pasch.umpa.ens-lyon.fr>
Diffstat (limited to 'basis_sampling.py')
-rw-r--r-- | basis_sampling.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/basis_sampling.py b/basis_sampling.py new file mode 100644 index 0000000..275e81d --- /dev/null +++ b/basis_sampling.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +import logging +from time import time + +from xonly import xPoint, MontgomeryA + +logger = logging.getLogger(__name__) +logger.setLevel(logging.WARNING) +logger_sh = logging.StreamHandler() +logger_sh.setLevel(logging.WARNING) +formatter = logging.Formatter("%(name)s [%(levelname)s] %(message)s") +logger_sh.setFormatter(formatter) +logger.addHandler(logger_sh) + + +def find_Ts(E, only_T0 = False): + r""" + Given a curve E, finds and marks the non-trivial + 2-torsion points according to Lemma D.1 + """ + A = MontgomeryA(E) + F = E.base_field() + R = F["X"] + X = R.gens()[0] + f = X**2 + A*X + 1 + logger.debug(" > root finding") + lam1, lam2 = f.roots(multiplicities=False) + + R1 = E(lam1, 0) + R2 = E(lam2, 0) + R3 = E(0, 0) + + #Find T0 + Rs = [R1, R2] + for T in Rs: + if T.tate_pairing(T, 2, 1) != 1: + T0 = T + Rs.remove(T) + break + + assert T0 + if only_T0: + return T0 + + assert T0.tate_pairing(T0, 2, 1) == -1 + Rs.append(R3) + for T in Rs: + if T.tate_pairing(T0, 2, 1) == 1: + Tm1 = T + Rs.remove(T) + break + + assert Tm1 + T1 = Rs[0] + assert T1.tate_pairing(T0, 2, 1) != 1 + + return T0, Tm1, T1 + + +def TwoTorsBasis(E, e): + r""" + Fast sampling of a basis P, Q of E[2**e], such that x(P) and x(Q) are both defined over Fp + Input: + - E: Elliptic curve over Fp + - e: Exponent + Output: + - P, Q: Basis of E[2**e] so that P is in E(Fp), and Q is in E^t(Fp) for an Fp-twist of E. + """ + logger.debug(" > Finding TwoTorsionBasis") + tstart = time() + + T0, Tm1, T1 = find_Ts(E) + + A = MontgomeryA(E) + F = E.base_field() + R = F["X"] + X = R.gens()[0] + f = X**2 + A*X + 1 + + logger.debug(f" > Done, have used {time()-tstart} sec") + + logger.debug(" > sample xP") + xT0 = T0.x() + xP = xT0 + F.random_element()**2 + while not (f(xP)*xP).is_square() or (xP-Tm1.x()).is_square(): + xP = xT0 + F.random_element()**2 + + logger.debug(" > sample xQ") + xQ = xT0 - F.random_element()**2 + while (f(xQ)*xQ).is_square() or not ((xQ-T1.x()).is_square()): + xQ = xT0 - F.random_element()**2 + + logger.debug(f" > Done, have used {time()-tstart} sec") + #print(T0.tate_pairing(E.lift_x(xP), 2, 1)) + + P = xPoint(xP, E) + Q = xPoint(xQ, E) + + assert (E.base_field().characteristic()+1) % 2**(e+1) == 0 + cofac = (E.base_field().characteristic()+1)/2**(e+1) + P = P.xMUL(cofac) + Q = Q.xMUL(cofac) + + assert P.xMUL(2**(e-1)) + assert not P.xMUL(2**e) + assert Q.xMUL(2**(e-1)) + assert not Q.xMUL(2**e) + assert Q.xMUL(2**(e-1)) != P.xMUL(2**(e-1)) + + logger.debug(f" > Total time for 2-tors basis finding: {time()-tstart}") + + return P, Q |