def recover_private_key(m, r, s, k, q, H_m=None): '''recover dsa private key from k and signature''' #s = k^(-1)(H(m) + xr) mod q #==> sk - H(m) = xr (mod q) #==> x = r^(-1)(sk - H(m)) mod q if not H_m: H_m = util.bytes_to_bigint(util.sha1sum(m)) r_inv = number_theory.mod_inv(r, q) x = ((((s * k) % q - H_m) % q) * r_inv) % q return x
def dsa_verify(r, s, m, y, p=p, q=q, g=g, h=util.sha1sum): #check that 0 < r < q and 0 < s < q if 0 >= r or r >= q or 0 >= s or r >= q: return False H_m = util.bytes_to_bigint(h(m)) #w = s^(-1) mod q w = number_theory.mod_inv(s, q) u1 = (H_m * w) % q #u_2 = r*w = r*s^(-1) u2 = (r * w) % q v = ((pow(g, u1, p) * pow(y, u2, p)) % p) % q return v == r
def dsa_sign(m, x, p=p, q=q, g=g, h=util.sha1sum): H_m = util.bytes_to_bigint(h(m)) while True: #generate nonce 1 < k < q k = random.SystemRandom().randrange(1, q - 1) #r = (g^k mod p) mod q r = pow(g, k, p) % q #if r == 0, pick new k and try again if r == 0: continue #s = k^(-1)(H(m) + xr) mod q k_inv = number_theory.mod_inv(k, q) s = (k_inv * ((H_m + ((x * r) % q)) % q)) % q #if s == 0, pick new k and try again if s == 0: continue return (r, s)
def load(path='44.txt'): '''reads list of messages and signatures in the format: \nmsg: <msg>\ns: <s>\nr: <r>\nm: <m>\n''' with open(path, 'r') as f: lines = f.read().split('\n') assert (len(lines) % 4 == 0) sigs = [] for i in range(0, len(lines), 4): msg = lines[i][len('msg: '):] s = int(lines[i + 1][3:]) r = int(lines[i + 2][3:]) m = lines[i + 3][3:] if len(m) % 2: m = '0' + m m = util.bytes_to_bigint(m.decode('hex')) sigs.append((msg, s, r, m)) return sigs
def recv_bigint(con): '''reads <length> <bigint>''' return util.bytes_to_bigint(recv_len_payload(con))
def rsa_decrypt(c, d, n): if isinstance(c, basestring): c = util.bytes_to_bigint(c) return pow(c, d, n)
def rsa_encrypt(m, e, n): if isinstance(m, basestring): m = util.bytes_to_bigint(m) return pow(m, e, n)
#s = k^(-1)(H(m) + xr) mod q k_inv = number_theory.mod_inv(k, q) s = (k_inv * ((H_m + ((x * r) % q)) % q)) % q return (r, s) if __name__ == '__main__': y = 0x84ad4719d044495496a3201c8ff484feb45b962e7302e56a392aee4abab3e4bdebf2955b4736012f21a08084056b19bcd7fee56048e004e44984e2f411788efdc837a0d2e5abb7b555039fd243ac01f0fb2ed1dec568280ce678e931868d23eb095fde9d3779191b8c0299d6e07bbb283e6633451e535c45513b2d33c99ea17 msg = '''For those that envy a MC it can be hazardous to your health\nSo be friendly, a matter of life and death, just like a etch-a-sketch\n''' r = 548099063082341131477253921760299949438196259240 s = 857042759984254168557880549501802188789837994940 assert (util.sha1sum(msg).encode('hex') == 'd2d0714f014a9784047eaeccf956520045c45265') H_m = util.bytes_to_bigint(util.sha1sum(msg)) r_inv = number_theory.mod_inv(r, dsa.q) for k in range(1, 1 << 16): #x = ((((s*k) % dsa.q + dsa.q - H_m) % dsa.q) * r_inv) % dsa.q x = ((s * k - H_m) * r_inv) % dsa.q if dsa_sign_with_k(H_m, x, k) == (r, s): #if x is actual privake key => y = g^x mod p assert (y == pow(dsa.g, x, dsa.p)) print 'k =', k print 'Private key =', x key_hash = util.sha1sum('%x' % x).encode('hex') assert (key_hash == '0954edd5e0afe5542a4adf012611a91912a3ec16') break
def _compute_u(A, B): #compute u = H(A | B) return bytes_to_bigint(sha256sum(bigint_to_bytes(A) + bigint_to_bytes(B)))
def _compute_x(salt, password): #compute x = H(salt || password) return bytes_to_bigint(sha256sum(salt + password))
if padding_oracle((pow(s, e, n) * c) % n): found = True break s += 1 r += 1 a, b = _step3([(a, b)], B, n, s)[0] return b if __name__ == '__main__': #don't want to have to wait for key generation each time #256 bit key #d, e, n = (37255313119928308596958693738000904270148055374803475499902820648455212368979L, 3, 55882969679892462895438040607001356405695530651745489982532299779733176320093L) d, e, n = rsa._sample_params m = 'Hello Adrian.' mod_len = pkcs1.num_bytes(n) B = 1 << (8 * mod_len - 16) M = util.bytes_to_bigint(pkcs1.pkcs1_pad(m, mod_len)) c = rsa.rsa_encrypt(M, e, n) p = decrypt(c, e, n, lambda c: fast_oracle(c, d, n, 2 * B, 3 * B)) p = util.bigint_to_bytes(p) #pad start with 0s so it has same length as modulus p = '\x00' * (mod_len - len(p)) + p p = pkcs1.pkcs1_unpad(p, mod_len) print p assert (p == m)
def forge(msg, bit_length=1024): #find x such that x^3 ~= 00 01 FF 00 ASN.1 HASH garbage padding evil = prefix + pkcs_magic_bytes + util.sha1sum(msg) pad = '\x01' * (bit_length / 8 - len(evil)) target = util.bytes_to_bigint(evil + pad) return number_theory.ith_root(target, 3)