def verify(msghash, sig, pub): assert isinstance(msghash, bytes) assert isinstance(sig, tuple) assert isinstance(pub, tuple) _, r, s = sig w = ec.inv(s, ec.N) z = convert.bytes_to_int(msghash) u1, u2 = z * w % ec.N, r * w % ec.N x, _ = ec.add(ec.multiply(ec.G, u1), ec.multiply(pub, u2)) return r == x
def sign(msghash, priv): assert isinstance(msghash, bytes) assert isinstance(priv, int) z = convert.bytes_to_int(msghash) k = deterministic_generate_k(msghash, priv) r, y = ec.multiply(ec.G, k) s = ec.inv(k, ec.N) * (z + r * priv) % ec.N # Ensure Low S constraint against tx malleability # https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#Low_S_values_in_signatures if s > ec.N // 2: s = ec.N - s y += 1 # Switch parity of y, otherwise recover breaks. return 27 + (y % 2), r, s
def test_all(self): for _ in range(20): x, y = random.randrange(2**256), random.randrange(2**256) self.assertFalse(ec.is_curve_point((x,y))) G_x = ec.multiply(ec.G, x) G_y = ec.multiply(ec.G, y) self.assertTrue(ec.is_curve_point(G_x)) self.assertEqual( ec.multiply(G_x, y)[0], ec.multiply(G_y, x)[0] ) self.assertEqual( ec.add(G_x, G_y)[0], ec.multiply(ec.G, ec.add_scalar(x, y))[0] ) self.assertEqual( ec.substract(G_x, G_y)[0], ec.multiply(ec.G, ec.substract_scalar(x, y))[0] ) self.assertEqual(ec.G[0], ec.multiply(ec.divide(ec.G, x), x)[0])
def priv_to_pub(priv): assert isinstance(priv, int) return ec.multiply(ec.G, priv)