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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| from sage.all import * from sage.all_cmdline import * import gmpy2 import libnum def coppersmith_howgrave_univariate(pol, modulus, beta, mm, tt, XX): """ Taken from https://github.com/mimoo/RSA-and-LLL-attacks/blob/master/coppersmith.sage Coppersmith revisited by Howgrave-Graham
finds a solution if: * b|modulus, b >= modulus^beta , 0 < beta <= 1 * |x| < XX More tunable than sage's builtin coppersmith method, pol.small_roots() """ dd = pol.degree() nn = dd * mm + tt
if not 0 < beta <= 1: raise ValueError("beta should belongs in [0, 1]")
if not pol.is_monic(): raise ArithmeticError("Polynomial must be monic.")
""" * we want to find g(x) such that ||g(xX)|| <= b^m / sqrt(n)
* we know LLL will give us a short vector v such that: ||v|| <= 2^((n - 1)/4) * det(L)^(1/n)
* we will use that vector as a coefficient vector for our g(x)
* so we want to satisfy: 2^((n - 1)/4) * det(L)^(1/n) < N^(beta*m) / sqrt(n)
so we can obtain ||v|| < N^(beta*m) / sqrt(n) <= b^m / sqrt(n) (it's important to use N because we might not know b) """
polZ = pol.change_ring(ZZ) x = polZ.parent().gen()
gg = [] for ii in range(mm): for jj in range(dd): gg.append((x * XX) ** jj * modulus ** (mm - ii) * polZ(x * XX) ** ii) for ii in range(tt): gg.append((x * XX) ** ii * polZ(x * XX) ** mm)
BB = Matrix(ZZ, nn)
for ii in range(nn): for jj in range(ii + 1): BB[ii, jj] = gg[ii][jj]
BB = BB.LLL()
new_pol = 0 for ii in range(nn): new_pol += x ** ii * BB[0, ii] / XX ** ii
potential_roots = new_pol.roots()
roots = [] for root in potential_roots: if root[0].is_integer(): result = polZ(ZZ(root[0])) if gcd(modulus, result) >= modulus ** beta: roots.append(ZZ(root[0])) return roots
def solve(M, n, a, m):
base = int(65537) known = int(pow(base, a, M) * inverse_mod(M, n)) F = PolynomialRing(Zmod(n), implementation='NTL', names=('x',)) (x,) = F._first_ngens(1) pol = x + known beta = 0.1 t = m + 1 XX = floor(2 * n**0.5 / M) roots = coppersmith_howgrave_univariate(pol, n, beta, m, t, XX) for k in roots: p = int(k * M + pow(base, a, M)) if n % p == 0: return p, n // p
def roca(n):
keySize = n.bit_length()
if keySize <= 960: M_prime = 0x1b3e6c9433a7735fa5fc479ffe4027e13bea m = 5
elif 992 <= keySize <= 1952: M_prime = 0x24683144f41188c2b1d6a217f81f12888e4e6513c43f3f60e72af8bd9728807483425d1e m = 4 print("Have you several days/months to spend on this ?")
elif 1984 <= keySize <= 3936: M_prime = 0x16928dc3e47b44daf289a60e80e1fc6bd7648d7ef60d1890f3e0a9455efe0abdb7a748131413cebd2e36a76a355c1b664be462e115ac330f9c13344f8f3d1034a02c23396e6 m = 7 print("You'll change computer before this scripts ends...")
elif 3968 <= keySize <= 4096: print("Just no.") return None
else: print("Invalid key size: {}".format(keySize)) return None
a3 = Zmod(M_prime)(n).log(65537) order = Zmod(M_prime)(65537).multiplicative_order() inf = a3 // 2 sup = (a3 + order) // 2
chunk_size = 10000 for inf_a in range(inf, sup, chunk_size): inputs = [(M_prime, n, a, m) for a in range(inf_a, inf_a + chunk_size)] for a in range(inf_a, inf_a + chunk_size): result = solve(M_prime, n, a, m) if result: p, q = result print(f"found factorization:\np={p}\nq={q}") return result
if __name__ == "__main__": n = 787190064146025392337631797277972559696758830083248285626115725258876808514690830730702705056550628756290183000265129340257928314614351263713241 print("Starting factorization...") p=954455861490902893457047257515590051179337979243488068132318878264162627 q=824752716083066619280674937934149242011126804999047155998788143116757683 enc=365164788284364079752299551355267634718233656769290285760796137651769990253028664857272749598268110892426683253579840758552222893644373690398408 phi=(p-1)*(q-1) e = 65537 d = gmpy2.invert(e,phi) m = pow(enc,d,n) print(libnum.n2s(int(m)))
|