def test_forge_hash_sig(self): """forging valid hash signatures""" ec = secp256k1 # see https://twitter.com/pwuille/status/1063582706288586752 # Satoshi's key P = point_from_octets( secp256k1, "0311db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" ) u1 = 1 u2 = 2 # pick them at will R = double_mult(ec, u1, ec.G, u2, P) r = R[0] % ec.n u2inv = mod_inv(u2, ec.n) s = r * u2inv % ec.n sig = r, s e = s * u1 % ec.n dsa._verhlp(ec, e, P, sig) u1 = 1234567890 u2 = 987654321 # pick them at will R = double_mult(ec, u1, ec.G, u2, P) r = R[0] % ec.n u2inv = mod_inv(u2, ec.n) s = r * u2inv % ec.n sig = r, s e = s * u1 % ec.n dsa._verhlp(ec, e, P, sig)
def test_forge_hash_sig(): """forging valid hash signatures""" ec = secp256k1 # see https://twitter.com/pwuille/status/1063582706288586752 # Satoshi's key key = "03 11db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c" P = point_from_octets(key, ec) # pick u1 and u2 at will u1 = 1 u2 = 2 R = double_mult(u2, P, u1, ec.G, ec) r = R[0] % ec.n u2inv = mod_inv(u2, ec.n) s = r * u2inv % ec.n e = s * u1 % ec.n dsa._verhlp(e, (P[0], P[1], 1), r, s, ec) # pick u1 and u2 at will u1 = 1234567890 u2 = 987654321 R = double_mult(u2, P, u1, ec.G, ec) r = R[0] % ec.n u2inv = mod_inv(u2, ec.n) s = r * u2inv % ec.n e = s * u1 % ec.n dsa._verhlp(e, (P[0], P[1], 1), r, s, ec)
def test_low_cardinality(self): """test all msg/key pairs of low cardinality elliptic curves""" # ec.n has to be prime to sign prime = [11, 13, 17, 19] for ec in low_card_curves: # only low card or it would take forever if ec._p in prime: # only few curves or it would take too long for d in range(ec.n): # all possible private keys if d == 0: # invalid prvkey = 0 self.assertRaises(ValueError, dsa._sign, ec, 1, d, 1) continue P = mult(ec, d, ec.G) # public key for e in range(ec.n): # all possible int from hash for k in range(ec.n): # all possible ephemeral keys if k == 0: self.assertRaises(ValueError, dsa._sign, ec, e, d, k) continue R = mult(ec, k, ec.G) r = R[0] % ec.n if r == 0: self.assertRaises(ValueError, dsa._sign, ec, e, d, k) continue s = mod_inv(k, ec.n) * (e + d * r) % ec.n if s == 0: self.assertRaises(ValueError, dsa._sign, ec, e, d, k) continue # bitcoin canonical 'low-s' encoding for ECDSA if s > ec.n / 2: s = ec.n - s # valid signature sig = dsa._sign(ec, e, d, k) self.assertEqual((r, s), sig) # valid signature must validate self.assertTrue(dsa._verhlp(ec, e, P, sig)) keys = dsa._pubkey_recovery(ec, e, sig) self.assertIn(P, keys) for Q in keys: self.assertTrue(dsa._verhlp(ec, e, Q, sig))
def test_low_cardinality(self): """test low-cardinality curves for all msg/key pairs.""" # ec.n has to be prime to sign prime = [11, 13, 17, 19] for ec in low_card_curves: # only low card or it would take forever if ec._p in prime: # only few curves or it would take too long for q in range(1, ec.n): # all possible private keys PJ = _mult_jac(q, ec.GJ, ec) # public key for e in range(ec.n): # all possible int from hash for k in range(1, ec.n): # all possible ephemeral keys RJ = _mult_jac(k, ec.GJ, ec) Rx = (RJ[0] * mod_inv(RJ[2] * RJ[2], ec._p)) % ec._p r = Rx % ec.n s = mod_inv(k, ec.n) * (e + q * r) % ec.n # bitcoin canonical 'low-s' encoding for ECDSA if s > ec.n / 2: s = ec.n - s if r == 0 or s == 0: self.assertRaises(ValueError, dsa._sign, e, q, k, ec) continue sig = dsa._sign(e, q, k, ec) self.assertEqual((r, s), sig) # valid signature must pass verification self.assertIsNone(dsa._verhlp(e, PJ, r, s, ec)) JacobianKeys = dsa._recover_pubkeys(e, r, s, ec) Qs = [ ec._aff_from_jac(key) for key in JacobianKeys ] self.assertIn(ec._aff_from_jac(PJ), Qs)