def ecdsa_sign(curve_obj, hash_int, hash_num_bits, private_key, message, k=None): """Sign message using the private key. Returns the signature (r, s). @param hash_int: a hash function mapping to an integer, for example lambda m: util.be2int(hashlib.sha256(m).digest()) @param hash_num_bits: the number of bits in the digest above, for example 256. """ n = curve_obj.order if k is None: k = util.randint(1, n - 1) e = hash_int(message) L_n = util.count_bits(n) z = e >> max(hash_num_bits - L_n, 0) while True: (x1, y1) = curve.mul(k, curve_obj.base_point, curve_obj.curve) r = x1 % curve_obj.order if r == 0: continue k_neg = numbertheory.inverse_of(k, n) s = (k_neg * (z + r * private_key)) % n if s == 0: continue break return (r, s)
def test_inverse(self): p = 7873 for n in range(1, 3000): all_valid = set() for m in range(p): if (n * m) % p == 1: all_valid.add(m) break self.assertTrue(inverse_of(n, p) in all_valid)
def ecdsa_verify(curve_obj, hash_int, hash_num_bits, public_key, message, signature): """Verify that signature is over the message using the public key. Returns True if so, False otherwise. Otherwise similar to ecdsa_sign() in usage. """ n = curve_obj.order # Verify if public_key == curve_obj.base_point or \ curve_obj.curve.invert_point(public_key) == curve_obj.base_point: # XXX: Check inverted too? return False if not curve_obj.curve.point_on_curve(public_key): return False if not curve.mul(curve_obj.order, public_key, curve_obj.curve) == curve_obj.curve.neutral_point(): return False (r, s) = signature if not 1 <= r <= n - 1: return False if not 1 <= s <= n - 1: return False e = hash_int(message) L_n = util.count_bits(n) z = e >> max(hash_num_bits - L_n, 0) # Verify w = numbertheory.inverse_of(s, curve_obj.order) % n u_1 = (z * w) % n u_2 = (r * w) % n (x1, y1) = curve_obj.curve.add_points( curve.mul(u_1, curve_obj.base_point, curve_obj.curve), curve.mul(u_2, public_key, curve_obj.curve)) return (r % n) == (x1 % n)
def ecdsa_verify(curve_obj, hash_int, hash_num_bits, public_key, message, signature): """Verify that signature is over the message using the public key. Returns True if so, False otherwise. Otherwise similar to ecdsa_sign() in usage. """ n = curve_obj.order # Verify if public_key == curve_obj.base_point or \ curve_obj.curve.invert_point(public_key) == curve_obj.base_point: # XXX: Check inverted too? return False if not curve_obj.curve.point_on_curve(public_key): return False if not curve.mul(curve_obj.order, public_key, curve_obj.curve) == curve_obj.curve.neutral_point(): return False (r, s) = signature if not 1 <= r <= n - 1: return False if not 1 <= s <= n - 1: return False e = hash_int(message) L_n = util.count_bits(n) z = e >> max(hash_num_bits - L_n, 0) # Verify w = numbertheory.inverse_of(s, curve_obj.order) % n u_1 = (z * w) % n u_2 = (r * w) % n (x1, y1) = curve_obj.curve.add_points( curve.mul(u_1, curve_obj.base_point, curve_obj.curve), curve.mul(u_2, public_key, curve_obj.curve) ) return (r % n) == (x1 % n)
def mul_inv(self, n): return numbertheory.inverse_of(n, self.p)
def div(a, b): return (a * numbertheory.inverse_of(b, curve_obj.order)) % curve_obj.order