def BreakDSA(m1, m2, publicKey, dsa_params): # m1 and m2 are interchangeable, but if you compute m1['s'] - m2['s'] # (and the rest accordingly), you get a negative K, which is not valid # according to the spec, and our implementation hangs trying to sign # a message. k = rsa.invmod((m2['s'] - m1['s']), dsa_params['Q']) k *= (int(m2['m'], 16) - int(m1['m'], 16)) top = (m1['s'] * k) - int(m1['m'], 16) bottom = rsa.invmod(m1['r'], dsa_params['Q']) privateKey = (top * bottom) % dsa_params['Q'] # Derive the public key from the private key and compare it # with the one we know. testPub = dsa.modexp(dsa_params['G'], privateKey, dsa_params['P']) if testPub == publicKey: print('[**] Success!') print('K:', k) print('X:', privateKey) # Sign one of the two messages with the private key and compare # the signature with the one we got from the file. sig = dsa.dsa_sign(dsa_params['Q'], dsa_params['P'], dsa_params['G'], privateKey, int('0x' + m1['m'], 16), k=k) if sig == (m1['r'], m1['s']): print('[**] Broken private key passes validation') return True return False
def china(shifr): c_0, c_1, c_2 = shifr[0][0], shifr[1][0], shifr[2][0] n_0, n_1, n_2 = shifr[0][1], shifr[1][1], shifr[2][1] m_s_0, m_s_1, m_s_2 = n_1*n_2, n_0*n_2, n_0*n_1 a0 = (c_0*m_s_0*invmod(m_s_0, n_0)) a1 = (c_1*m_s_1*invmod(m_s_1, n_1)) a2 = (c_2*m_s_2*invmod(m_s_2, n_2)) c = (a0+a1+a2) % (n_0*n_1*n_2) return int2byte(c**(1/3))
def BreakDSA(p, g, q, r, s): publicKey = int( '0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17', 16) H = dsa.HashMessage( b'For those that envy a MC it can be hazardous to your health\n' b'So be friendly, a matter of life and death, just like a etch-a-sketch\n' ) k = 0 brokenKey = None for k in range(1, 2**16 + 1): top = (s * k) - H bottom = rsa.invmod(r, q) privateKey = (top * bottom) % q # Derive the public key from the private key and compare it # with the one we know. testPub = modexp(g, privateKey, p) if testPub == publicKey: brokenKey = privateKey break else: print('[!!] Unable to break private key') return print('[**] Success!') print('K:', k) print('X:', brokenKey) return brokenKey, k
def BreakRSA(C, N): n12 = N[1] * N[2] n02 = N[0] * N[2] n01 = N[0] * N[1] n012 = N[0] * N[1] * N[2] # Using the Chinese Remainder Theorem we can decompose C and N. r0 = C[0] * n12 * rsa.invmod(n12, N[0]) r1 = C[1] * n02 * rsa.invmod(n02, N[1]) r2 = C[2] * n01 * rsa.invmod(n01, N[2]) res = r0 + r1 + r2 res = res % n012 # Compute the cube root and round to the nearest integer. return round(res**(1.0 / 3.0))
def BreakDSA(p, g, q, r, s): publicKey = int('0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17', 16) H = dsa.HashMessage(b'For those that envy a MC it can be hazardous to your health\n' b'So be friendly, a matter of life and death, just like a etch-a-sketch\n') k = 0 brokenKey = None for k in range(1, 2 ** 16 + 1): top = (s * k) - H bottom = rsa.invmod(r, q) privateKey = (top * bottom) % q # Derive the public key from the private key and compare it # with the one we know. testPub = modexp(g, privateKey, p) if testPub == publicKey: brokenKey = privateKey break else: print('[!!] Unable to break private key') return print('[**] Success!') print('K:', k) print('X:', brokenKey) return brokenKey, k
def Reveal(text, publicKey): _, n = publicKey s = 14 # same as above # We are in modulo N group, so instead of dividing by n, we # need to multiply by its inverse in the group. inverse = rsa.invmod(s, n) return (text * inverse) % n
def verify(m, g, p, q, r, s, y): for j in [r, s]: if j <= 0: pass # Bad! Should reject, but breaking on purpose. if j >= q: return False w = invmod(s, q) u1 = s2i(sha1(m).digest()) * w % q u2 = r * w % q v = (pow(g, u1, p) * pow(y, u2, p)) % p % q return v == r
def sign_sha1(priv, msg): group, x = priv h = hash(msg) while True: k = random.randrange(1, group.q - 1) r = pow(group.g, k, group.p) % group.q if r == 0: continue kinv = rsa.invmod(k, group.q) s = (kinv * (h + x * r)) % group.q if s == 0: continue return (r, s)
def text_recovery(shifr, rsa_server): e, n = rsa_server.get_public_key() while True: s=randint(2, n-1) if s%n>1: break shifr2=(pow(s, e, n)*shifr)%n text2=rsa_server.dec(shifr2) inttext = int.from_bytes(text2, byteorder='big') r=(inttext*invmod(s, n))%n return int2byte(r)
def verify_sha1(pub, sig, msg): group, y = pub r, s = sig h = hash(msg) if not (r > 0 and r < group.q and s > 0 and s < group.q): raise ValueError, 'invalid dsa signature' w = rsa.invmod(s, group.q) u1 = (h * w) % group.q u2 = (r * w) % group.q v = (pow(group.g, u1, group.p) * pow(y, u2, group.p)) % group.p v %= group.q if v != r: raise ValueError, 'invalid dsa signature'
def sign(message, g, p, q, x): """DSA signing. Deliberately bad max value for k, the nonce. Really, max should be = q. Also deliberately bad to give up and allow r = 0. """ r = 0 s = 0 i = 0 while r == 0 or s == 0: i += 1 if i > 60000: return [r, s] # bad! k = random.randint(1, 2**16) # bad ! r = pow(g, k, p) % q H = s2i(sha1(message).digest()) s = ((H + x * r) * invmod(k, q)) % q return [r, s]
def sign(message, g, p, q, x): """DSA signing. Deliberately bad max value for k, the nonce. Really, max should be = q. Also deliberately bad to give up and allow r = 0. """ r = 0 s = 0 i = 0 while r == 0 or s == 0: i += 1 if i > 60000: return [r,s] # bad! k = random.randint(1, 2 ** 16) # bad ! r = pow(g, k, p) % q H = s2i(sha1(message).digest()) s = ((H + x * r) * invmod(k, q)) % q return [r, s]
def unpadded_msg_recovery_oracle(): pub, oracle = get_rsa_unpadded_dec_oracle(1024) m = "Hello World!" print "M is '%s'" % m c = rsa.encrypt(pub, m) print "C is %d\n" % c # use the decryption oracle print "Using decryption oracle..." m2 = oracle(c) print "Decrypted '%s'\n" % m2 print "Testing that decryption oracle will reject this ciphertext" print "Using decryption oracle..." m2 = oracle(c) # pick random S > 1 mod N such that S has a multiplicative inverse mod N print "\nSearching for suitable S > 1 mod N" E, N = pub S, S_inv = None, None while True: S = random.randint(2, N-1) if S == E: continue S_inv = rsa.invmod(S, N) if S_inv: break print "Doing the attack with S == %d, S_inv == %d" % (S, S_inv) c_prime = (rsa.modexp(S, E, N) * c) % N print "Using decryption oracle..." m_prime = long(binascii.hexlify(oracle(c_prime)), 16) m2 = rsa._tohex(m_prime * S_inv % N) print "Messsage is '%s'" % m2
decrypt = rsa.decrypt_string(ciphertext, R) print print "Bob gets this message:", decrypt #### Eve # Calculate products of the moduli (pubkeys) EXCEPT pubkey number i. ms = [None] * k for i in range(k): x = copy.copy(n) del x[i] ms[i] = reduce(lambda a, b: a * b, x) # Work thru Chinese Remainder Theorem result = 0 for i in range(k): result += c[i] * ms[i] * rsa.invmod(ms[i], n[i]) result = result % reduce(lambda a, b: a * b, n) # Get final text overheard = rsa.i2s(cuberoot(result)) print "Eve hears this message:", overheard #### tests #### assert message == decrypt assert message == overheard assert decrypt == overheard warn("Passed assertions:", __file__)
import dsa import rsa p = 0x800000000000000089e1855218a0e7dac38136ffafa72eda7859f2171e25e65eac698c1702578b07dc2a1076da241c76c62d374d8389ea5aeffd3226a0530cc565f3bf6b50929139ebeac04f48c3c84afb796d61e5a4f9a8fda812ab59494232c7d2b4deb50aa18ee9e132bfa85ac4374d7f9091abc3d015efc871a584471bb1 q = 0xf4f47f05794b256174bba6e9b396a7707e563c5b if __name__ == '__main__': # er, g = 0 means all signature r values will be 0 -- signature generation won't halt # because that case is detected and retried with another k value # # for signature validation, the signature is rejected early because r < 1 group = dsa.group(p, q, p + 1) pub, priv = dsa.gen_pair(group) z = 1 y = pub[1] r = pow(y, z, group.p) % group.q zinv = rsa.invmod(z, group.q) s = (r * zinv) % group.q magic_sig = (r, s) dsa.verify_sha1(pub, magic_sig, 'hello world') dsa.verify_sha1(pub, magic_sig, 'goodbye world') print 'ok'
if key == 's' or key == 'r': exec('row2["' + key + '"] = ' + val) # int means no quote else: exec('row2["' + key + '"] = "' + val + '"') # str means quote if key != 'm': continue #### Find repeated r row1 = first_row_where('r', row2['r'], all_past) if not row1: all_past.append(row2) continue #### get cracking m1 = int(row1['m'], 16) m2 = int(row2['m'], 16) k = ((m1 - m2) * invmod((row1['s'] - row2['s']), q) % q) print "k =", k x = find_private_key(row1['r'], row1['s'], k, m1, q) print "x =", x hex_x = hex(x).replace('0x','').replace('L','') s1x = sha1(hex_x).hexdigest() print "sha1(x) =", s1x break #### tests #### h = [{'a':10, 'b':9, 'c':4}, {'a':777, 'b':99, 'c':42}, {'a':11, 'b':10, 'c':4}] assert first_row_where('c', 42, h) == {'a': 777, 'c': 42, 'b': 99} assert s1x == "ca8f6f7c66fa362d40760d135b763eb8527d3d52" warn("Passed assertions:", __file__)
def recover_x_given_sig_k(group, k, sig, msg): r, s = sig rinv = rsa.invmod(r, group.q) h = hash(msg) x = ((s * k - h) * rinv) % group.q return x
r = 228998983350752111397582948403934722619745721541, m = 'd6340bfcda59b6b75b59ca634813d572de800e8f') ] if __name__ == '__main__': pub = (group, y) # check signatures for sanity for s in sigs: sig = (s['r'], s['s']) dsa.verify_sha1(pub, sig, s['msg']) # look at all pairs for signatures and see if key falls out for i1, d1 in enumerate(sigs): for i2, d2 in enumerate(sigs): if i1 == i2: continue m1 = dsa.hash(d1['msg']) m2 = dsa.hash(d2['msg']) s1 = d1['s'] s2 = d2['s'] sd = (s1 - s2) % group.q invsd = rsa.invmod(sd, group.q) k = (((m1 - m2) % group.q) * invsd) % group.q x = dsa.recover_x_given_sig_k(group, k, (d1['r'], d1['s']), d1['msg']) if dsa.sha1('%x' % x).hexdigest() == hash_x: print 'i1: %d, i2: %d, k: 0x%x, x: 0x%x' % (i1, i2, k, x) exit(0)
breakme = alice.encrypt(secret_for_bob) E = breakme['pubkey'][0] # pub key exponent N = breakme['pubkey'][1] # public key modulus C = breakme['ciphertext'] # long integer, not string print "Bob calls Alice and receives..." print alice.decrypt(C) print #### Mallory print "Mallory calls Alice the 1st time and receives..." print alice.decrypt(C) print "Mallory calls w/ seemingly different string & receives..." S = random.randint(2, 100000) assert S % N > 1 Cp = (pow(S, E, N) * C) % N Pp_string = alice.decrypt(Cp) print Pp_string Pp = rsa.s2i(Pp_string) print "Alice's hash table suspects nothing..." print alice.log P = (Pp * rsa.invmod(S, N) ) % N print "But Mallory now knows..." print rsa.i2s(P) #### tests #### assert rsa.i2s(P) == secret_for_bob warn("Passed assertions:", __file__)
import rsa if __name__ == '__main__': pubkeys = [] for _ in range(3): pub, priv = rsa.gen_rsa(1024, 3) pubkeys.append(pub) m = 0x1235123 ciphertexts = [] for pub in pubkeys: e = rsa.raw_encrypt(pub, m) ciphertexts.append(e) # pubkeys are e, n tuples moduli = [pubkeys[x][1] for x in range(3)] m_s = [ moduli[1] * moduli[2], moduli[0] * moduli[2], moduli[0] * moduli[1] ] n_012 = moduli[0] * moduli[1] * moduli[2] magic = 0 for i in range(3): inv = rsa.invmod(m_s[i], moduli[i]) magic += ciphertexts[i] * m_s[i] * inv magic %= n_012 assert m == rsa.cuberoot(magic) print 'ok'
row2 = {} if key == 's' or key == 'r': exec('row2["' + key + '"] = ' + val) # int means no quote else: exec('row2["' + key + '"] = "' + val + '"') # str means quote if key != 'm': continue #### Find repeated r row1 = first_row_where('r', row2['r'], all_past) if not row1: all_past.append(row2) continue #### get cracking m1 = int(row1['m'], 16) m2 = int(row2['m'], 16) k = ((m1 - m2) * invmod((row1['s'] - row2['s']), q) % q) print "k =", k x = find_private_key(row1['r'], row1['s'], k, m1, q) print "x =", x hex_x = hex(x).replace('0x', '').replace('L', '') s1x = sha1(hex_x).hexdigest() print "sha1(x) =", s1x break #### tests #### h = [{ 'a': 10, 'b': 9, 'c': 4 }, { 'a': 777,
print "g ", print_long(g) print "x (shh!) ", x print "y ", print_long(y) print "sig ", r print " ", s return [r, s, y] for g in [g_original, 0, p + 1]: for message in m: [r, s, y] = tamper(message, g) answer = verify(message, g, p, q, r, s, y) print "verifies?", answer assert answer print if g == p + 1: z = 42 # arbitrary r_magic = pow(y, z, p) % q s_magic = r * invmod(z, q) % q print "Made magic signature that will validate against any string." print "r", r_magic print "s", s_magic for string in m + ["I fooled you", "asdfswe", "xcvbnm"]: print "Signing:", string answer = verify(string, g, p, q, r_magic, s_magic, y) print "verifies?", answer assert answer #### tests #### warn("Passed assertions:", __file__)
print "s =", s print #### Breaking, given a signature [r,s], and given that k <= 2**16. #### Also of course given parameters g, p, q, and hash H of message. print "Searching for k (nonce, subkey) and thus x (private key)...." matasano_r = 548099063082341131477253921760299949438196259240 matasano_s = 857042759984254168557880549501802188789837994940 k_found = 0 x_found = 0 start = time.time() for k in range (1, 2 ** 16): r = pow(g, k, p) % q x = find_private_key(matasano_r, matasano_s, k, H, q) s = ((H + x * r) * invmod(k, q)) % q if s == matasano_s and r == matasano_r: print "k =", k print "x =", x k_found = k x_found = x # Deciding not to break out of the for loop, in rare event # there would be two valid values of k. end = time.time() dur = end - start rate = k / dur print "Tried", k, "nonces in", int(dur), "s, for", int(rate), "per s." # 5800 per sec on MacBook Pro 8,1 (early 2011, OS X, 2.7 GHz Intel Core i7) S = hex(x_found).replace("L", "").replace("0x", "") print S
import random ciphers = [] def decrypt_once(priv, ct): global ciphers if ct in ciphers: return None ciphers.append(ct) return rsa.raw_decrypt(priv, ct) if __name__ == "__main__": pub, priv = rsa.gen_rsa(1024, rsa.PUBLIC_EXP) m = 0x12351234 ct = rsa.raw_encrypt(pub, m) assert decrypt_once(priv, ct) == m assert decrypt_once(priv, ct) is None N = pub[1] S = random.randrange(1, N) S_ct = rsa.raw_encrypt(pub, S) S_pt = decrypt_once(priv, (S_ct * ct) % N) S_inv = rsa.invmod(S, N) assert (S_inv * S_pt) % N == m print "ok"
def find_private_key(r, s, k, H, q): """s = (H+rx)/k. Therefore (sk-H)/r = x.""" return ((s * k - H) * invmod(r, q)) % q
continue assert rlow <= rhigh, [a, b, rlow, rhigh] for r in range(rlow, rhigh+1): mlow = max(a, ceildiv(2*B + r*n, s[i])) mhigh = min(b, (3*B - 1 + r*n) // s[i]) assert mlow <= mhigh, [mlow, mhigh, mlow - a, b - mhigh, rlow, rhigh, r] this_interval = [mlow, mhigh] if this_interval not in m_set: m_set.append(this_interval) M.append(simplify(m_set)) #### Step 4 if len(M[i]) == 1 and M[i][0][0] == M[i][0][1]: a = M[i][0][0] m = a * rsa.invmod(s[0], n) % n print print print "Hooray! m=", m result = rsa.i2s(m) print "i2s=", [result] break else: if len(M[i]) > 1: print "Iterate because len", len(M[i]) else: if i % 20 == 0: print "Iterate because interval > 0" i += 1 #### tests ####
breakme = alice.encrypt(secret_for_bob) E = breakme["pubkey"][0] # pub key exponent N = breakme["pubkey"][1] # public key modulus C = breakme["ciphertext"] # long integer, not string print "Bob calls Alice and receives..." print alice.decrypt(C) print #### Mallory print "Mallory calls Alice the 1st time and receives..." print alice.decrypt(C) print "Mallory calls w/ seemingly different string & receives..." S = random.randint(2, 100000) assert S % N > 1 Cp = (pow(S, E, N) * C) % N Pp_string = alice.decrypt(Cp) print Pp_string Pp = rsa.s2i(Pp_string) print "Alice's hash table suspects nothing..." print alice.log P = (Pp * rsa.invmod(S, N)) % N print "But Mallory now knows..." print rsa.i2s(P) #### tests #### assert rsa.i2s(P) == secret_for_bob warn("Passed assertions:", __file__)
decrypt = rsa.decrypt_string(ciphertext, R) print print "Bob gets this message:", decrypt #### Eve # Calculate products of the moduli (pubkeys) EXCEPT pubkey number i. ms = [None]*k for i in range(k): x = copy.copy(n) del x[i] ms[i] = reduce(lambda a, b: a*b, x) # Work thru Chinese Remainder Theorem result = 0 for i in range(k): result += c[i] * ms[i] * rsa.invmod(ms[i], n[i]) result = result % reduce(lambda a, b: a*b, n) # Get final text overheard = rsa.i2s(cuberoot(result)) print "Eve hears this message:", overheard #### tests #### assert message == decrypt assert message == overheard assert decrypt == overheard warn("Passed assertions:", __file__)
print "m ", m print "g ", print_long(g) print "x (shh!) ", x print "y ", print_long(y) print "sig ", r print " ", s return [r,s,y] for g in [g_original, 0, p+1]: for message in m: [r,s,y] = tamper(message, g) answer = verify(message, g, p, q, r, s, y) print "verifies?", answer assert answer print if g == p+1: z = 42 # arbitrary r_magic = pow(y, z, p) % q s_magic = r * invmod(z, q) % q print "Made magic signature that will validate against any string." print "r", r_magic print "s", s_magic for string in m + ["I fooled you", "asdfswe", "xcvbnm"]: print "Signing:", string answer = verify(string, g, p, q, r_magic, s_magic, y) print "verifies?", answer assert answer #### tests #### warn("Passed assertions:", __file__)
print "s =", s print #### Breaking, given a signature [r,s], and given that k <= 2**16. #### Also of course given parameters g, p, q, and hash H of message. print "Searching for k (nonce, subkey) and thus x (private key)...." matasano_r = 548099063082341131477253921760299949438196259240 matasano_s = 857042759984254168557880549501802188789837994940 k_found = 0 x_found = 0 start = time.time() for k in range(1, 2**16): r = pow(g, k, p) % q x = find_private_key(matasano_r, matasano_s, k, H, q) s = ((H + x * r) * invmod(k, q)) % q if s == matasano_s and r == matasano_r: print "k =", k print "x =", x k_found = k x_found = x # Deciding not to break out of the for loop, in rare event # there would be two valid values of k. end = time.time() dur = end - start rate = k / dur print "Tried", k, "nonces in", int(dur), "s, for", int(rate), "per s." # 5800 per sec on MacBook Pro 8,1 (early 2011, OS X, 2.7 GHz Intel Core i7) S = hex(x_found).replace("L", "").replace("0x", "") print S
m='d6340bfcda59b6b75b59ca634813d572de800e8f') ] if __name__ == '__main__': pub = (group, y) # check signatures for sanity for s in sigs: sig = (s['r'], s['s']) dsa.verify_sha1(pub, sig, s['msg']) # look at all pairs for signatures and see if key falls out for i1, d1 in enumerate(sigs): for i2, d2 in enumerate(sigs): if i1 == i2: continue m1 = dsa.hash(d1['msg']) m2 = dsa.hash(d2['msg']) s1 = d1['s'] s2 = d2['s'] sd = (s1 - s2) % group.q invsd = rsa.invmod(sd, group.q) k = (((m1 - m2) % group.q) * invsd) % group.q x = dsa.recover_x_given_sig_k(group, k, (d1['r'], d1['s']), d1['msg']) if dsa.sha1('%x' % x).hexdigest() == hash_x: print 'i1: %d, i2: %d, k: 0x%x, x: 0x%x' % (i1, i2, k, x) exit(0)
import rsa import random ciphers = [] def decrypt_once(priv, ct): global ciphers if ct in ciphers: return None ciphers.append(ct) return rsa.raw_decrypt(priv, ct) if __name__ == '__main__': pub, priv = rsa.gen_rsa(1024, rsa.PUBLIC_EXP) m = 0x12351234 ct = rsa.raw_encrypt(pub, m) assert decrypt_once(priv, ct) == m assert decrypt_once(priv, ct) is None N = pub[1] S = random.randrange(1, N) S_ct = rsa.raw_encrypt(pub, S) S_pt = decrypt_once(priv, (S_ct * ct) % N) S_inv = rsa.invmod(S, N) assert (S_inv * S_pt) % N == m print 'ok'