-
Notifications
You must be signed in to change notification settings - Fork 0
/
factoring_lab.py
129 lines (107 loc) · 3.61 KB
/
factoring_lab.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from vec import Vec
from GF2 import one
from factoring_support import dumb_factor
from factoring_support import intsqrt
from factoring_support import gcd
from factoring_support import primes
from factoring_support import prod
import echelon
from math import sqrt
from random import randint
## Ungraded Task
## Find integers a and b such that a^2 - b^2 == N ..
## Writing an algorithim for this problem is too hard,
## either the program runs forever or it just returns
## a trivial divisor ...
def root_method(N):
a = intsqrt(N) + 1
while not isinstance(sqrt(a**2 - N), int): a += 1
b = sqrt( a**2 - N )
return a - b
r, s, t = randint(1,10000000), randint(1,10000000), randint(1, 10000000)
a = r * s
b = s * t
d = gcd(a, b)
print(a % d == 0)
print(b % d == 0)
print(d >= s)
## Task 1
def int2GF2(i):
'''
Returns one if i is odd, 0 otherwise.
Input:
- i: an int
Output:
- one if i is congruent to 1 mod 2 ( an odd number )
- 0 if i is congruent to 0 mod 2 ( an even number )
Examples:
>>> int2GF2(3)
one
>>> int2GF2(100)
0
'''
if i % 2 == 0: return 0
else: return one
## Task 2
def make_Vec(primeset, factors):
'''
Input:
- primeset: a set of primes
- factors: a list of factors [(p_1,a_1), ..., (p_n, a_n)]
with p_i in primeset
Output:
- a vector v over GF(2) with domain primeset
such that v[p_i] = int2GF2(a_i) for all i
Example:
>>> make_Vec({2,3,11}, [(2,3), (3,2)]) == Vec({2,3,11},{2:one})
True
'''
return Vec( primeset , { k: int2GF2(v) for (k,v) in factors } )
## Task 3
def find_candidates(N, primeset):
'''
Input:
- N: an int to factor
- primeset: a set of primes
Output:
- a list [roots, rowlist]
- roots: a list a_0, a_1, ..., a_n where a_i*a_i - N can be factored
over primeset
- rowlist: a list such that rowlist[i] is a
primeset-vector over GF(2) corresponding to a_i
such that len(roots) = len(rowlist) and len(roots) > len(primeset)
'''
roots, rowlist, i = [], [], 2
while len(roots) < len(primeset)+1: # continue until
x = intsqrt(N) + i
if dumb_factor( x*x - N , primeset) != []: # ask if x*x-N is unfactorable
roots.append(x) # if not, then append to root list
# append to rowlist a vector mapping the parity of the exponent to an element in GF2 (1 or 0)
# the elements in the domain of this vec are the primes in primeset
rowlist.append(make_Vec(primeset, dumb_factor( x*x-N, primeset )))
i += 1
return roots, rowlist
## Task 4
def find_a_and_b(v, roots, N):
'''
Input:
- a {0,1,..., n-1}-vector v over GF(2) where n = len(roots)
- a list roots of integers
- an integer N to factor
Output:
a pair (a,b) of integers
such that a*a-b*b is a multiple of N
(if v is correctly chosen)
'''
alist = [ roots[root] for root in v.D if v[root] == one ] # create list of roots corresponding to the nonzero entries of the vector v
a = prod( alist )
c = prod({ x*x-N for x in alist })
b = intsqrt(c)
assert b*b == c
return (a, b)
## Task 5
##N = 2461799993978700679
##primelist = primes(10000) # build set of primes up to 10000
##roots, rowlist = find_candidates(N, primelist) # compute roots and rowlist
##M = echelon.transformation(rowlist) # get matrix M from rowlist , put in echelon form
smallest_nontrivial_divisor_of_2461799993978700679 = 1230926561