-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwiener.py
73 lines (57 loc) · 2.18 KB
/
wiener.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from typing import Tuple, Iterator, Iterable, Optional
def isqrt(n: int) -> int:
if n == 0:
return 0
x = 2 ** ((n.bit_length() + 1) // 2)
while True:
y = (x + n // x) // 2
if y >= x:
return x
x = y
def is_perfect_square(n: int) -> bool:
sq_mod256 = (1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0)
if sq_mod256[n & 0xff] == 0:
return False
mt = (
(9, (1,1,0,0,1,0,0,1,0)),
(5, (1,1,0,0,1)),
(7, (1,1,1,0,1,0,0)),
(13, (1,1,0,1,1,0,0,0,0,1,1,0,1)),
(17, (1,1,1,0,1,0,0,0,1,1,0,0,0,1,0,1,1))
)
a = n % (9 * 5 * 7 * 13 * 17)
if any(t[a % m] == 0 for m, t in mt):
return False
return isqrt(n) ** 2 == n
def rational_to_contfrac(x: int, y: int) -> Iterator[int]:
while y:
a = x // y
yield a
x, y = y, x - a * y
def contfrac_to_rational_iter(contfrac: Iterable[int]) -> Iterator[Tuple[int, int]]:
n0, d0 = 0, 1
n1, d1 = 1, 0
for q in contfrac:
n = q * n1 + n0
d = q * d1 + d0
yield n, d
n0, d0 = n1, d1
n1, d1 = n, d
def convergents_from_contfrac(contfrac: Iterable[int]) -> Iterator[Tuple[int, int]]:
n_, d_ = 1, 0
for i, (n, d) in enumerate(contfrac_to_rational_iter(contfrac)):
if i % 2 == 0:
yield n + n_, d + d_
else:
yield n, d
n_, d_ = n, d
def attack(e: int, n: int) -> Optional[int]:
f_ = rational_to_contfrac(e, n)
for k, dg in convergents_from_contfrac(f_):
edg = e * dg
phi = edg // k
x = n - phi + 1
if x % 2 == 0 and is_perfect_square((x // 2) ** 2 - n):
g = edg - phi * k
return dg // g
return None