Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/shared/small_roots/coron.py
2589 views
1
import logging
2
from math import gcd
3
4
from sage.all import ZZ
5
6
from shared import small_roots
7
from shared.polynomial import max_norm
8
9
10
def integer_bivariate(p, k, X, Y, roots_method="groebner"):
11
"""
12
Computes small integer roots of a bivariate polynomial.
13
More information: Coron J., "Finding Small Roots of Bivariate Integer Polynomial Equations Revisited"
14
Note: integer_bivariate in the coron_direct will probably be more efficient.
15
:param p: the polynomial
16
:param k: the amount of shifts to use
17
:param X: an approximate bound on the x roots
18
:param Y: an approximate bound on the y roots
19
:param roots_method: the method to use to find roots (default: "groebner")
20
:return: a generator generating small roots (tuples of x and y roots) of the polynomial
21
"""
22
pr = p.parent()
23
x, y = pr.gens()
24
delta = max(p.degrees())
25
26
_, W = max_norm(p(x * X, y * Y))
27
28
p00 = int(p.constant_coefficient())
29
assert p00 != 0
30
while gcd(p00, X) != 1:
31
X += 1
32
while gcd(p00, Y) != 1:
33
Y += 1
34
while gcd(p00, W) != 1:
35
W += 1
36
37
u = W + (1 - W) % abs(p00)
38
n = u * (X * Y) ** k
39
assert gcd(p00, n) == 1
40
q = ((pow(p00, -1, n) * p) % n).change_ring(ZZ)
41
42
logging.debug("Generating shifts...")
43
44
shifts = []
45
for i in range(k + delta + 1):
46
for j in range(k + delta + 1):
47
if i <= k and j <= k:
48
shifts.append(x ** i * y ** j * X ** (k - i) * Y ** (k - j) * q)
49
else:
50
shifts.append(x ** i * y ** j * n)
51
52
L, monomials = small_roots.create_lattice(pr, shifts, [X, Y])
53
L = small_roots.reduce_lattice(L)
54
polynomials = small_roots.reconstruct_polynomials(L, p, n, monomials, [X, Y])
55
for roots in small_roots.find_roots(pr, [p] + polynomials, method=roots_method):
56
yield roots[x], roots[y]
57
58