Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/shared/hensel.py
2587 views
1
from sage.all import ZZ
2
from sage.all import Zmod
3
4
5
def hensel_lift_linear(f, p, k, roots):
6
"""
7
Uses Hensel lifting to lift the roots of f mod p^k to f mod p^(k + 1)
8
:param f: the polynomial
9
:param p: the prime
10
:param k: the power
11
:param roots: a generator generating the roots of f mod p^k
12
:return: a generator generating the roots of f mod p^(k + 1)
13
"""
14
pk = p ** k
15
pk1 = p ** (k + 1)
16
for root in roots:
17
# We're really not using Hensel's lemma correctly here...
18
# Maybe this will be fixed later
19
for i in range(p):
20
new_root = root + i * pk
21
if f(new_root) % pk1 == 0:
22
yield new_root
23
24
25
def hensel_roots(f, p, k):
26
"""
27
Uses Hensel lifting to generate the roots of f mod p^k.
28
:param f: the polynomial
29
:param p: the prime
30
:param k: the power
31
:return: a generator generating the roots of f mod p^k
32
"""
33
f_ = f.change_ring(Zmod(p))
34
if f_ == 0:
35
roots = range(p)
36
elif f_.is_constant():
37
return
38
else:
39
roots = map(int, f_.roots(multiplicities=False))
40
41
f = f.change_ring(ZZ)
42
for i in range(1, k):
43
roots = hensel_lift_linear(f, p, i, roots)
44
45
return roots
46
47