Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/shared/small_roots/aono.py
2589 views
1
import logging
2
from itertools import product
3
from math import prod
4
5
from sage.all import ZZ
6
from sage.all import xgcd
7
8
from shared import small_roots
9
10
11
def integer_multivariate(F, e, m, X, roots_method="groebner"):
12
"""
13
Computes small integer roots of a list of polynomials.
14
More information: Aono Y., "Minkowski sum based lattice construction for multivariate simultaneous Coppersmith's technique and applications to RSA" (Section 4)
15
:param F: the list of polynomials
16
:param e: the list of e values
17
:param m: the parameter m
18
:param X: an approximate bound on the x roots
19
:param roots_method: the method to use to find roots (default: "groebner")
20
:return: a generator generating small roots (dicts of (x0: x0root, x1: x1root, ..., y: yroot) entries) of the polynomials
21
"""
22
# We need lexicographic ordering for .lc() below.
23
pr = F[0].parent().change_ring(ZZ, order="lex")
24
x = pr.gens()
25
26
l = len(e)
27
for k in range(l):
28
F[k] = pr(F[k])
29
30
logging.debug("Generating shifts...")
31
32
g = []
33
for k in range(l):
34
gk = {}
35
for i in range(m + 1):
36
for j in range(i + 1):
37
gk[i, j] = x[k] ** (i - j) * F[k] ** j * e[k] ** (m - j)
38
g.append(gk)
39
40
Ig = {}
41
for tup in product(*g):
42
g_ = prod(g[k][tup[k]] for k in range(l))
43
index = tuple(g_.exponents()[0])
44
if index not in Ig:
45
Ig[index] = []
46
Ig[index].append(g_)
47
48
shifts = []
49
for g in Ig.values():
50
gp = g[0]
51
lc = gp.lc()
52
for gi in g[1:]:
53
lc, s, t = xgcd(lc, gi.lc())
54
gp = s * gp + t * gi
55
shifts.append(gp)
56
57
L, monomials = small_roots.create_lattice(pr, shifts, X)
58
L = small_roots.reduce_lattice(L)
59
polynomials = small_roots.reconstruct_polynomials(L, None, prod(e) ** m, monomials, X)
60
yield from small_roots.find_roots(pr, polynomials, method=roots_method)
61
62