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_with_vector(self, PUB, REPR, PRIV, VALID): Repr = ref_ed.decodeint(''.join(map(chr, REPR))) X = ref_ed.decodeint(''.join(map(chr, PUB))) Priv = ref_ed.decodeint(''.join(map(chr, PRIV))) Pub = curvemod.mul(Priv, self.curve25519.base_point, self.curve25519.curve) # Check valid valid = True try: P1, P2 = self.curve25519.curve.get_y(X) except: valid = False self.assertEquals(valid, VALID) # Check mappings back and forth if valid: """ print print 'P1', P1 print 'P2', P2 print 'XXX', self.ell2.map_random_to_point(Repr) print self.assertEquals(Repr, self.ell2.map_point_to_random(P1)) self.assertEquals(Repr, self.ell2.map_point_to_random(P2)) """ self.assertEquals(Repr, self.ell2.map_point_to_random(Pub)) self.assertEquals(X, self.ell2.map_random_to_point(Repr)[0])
def _test_with_vector(self, PUB, REPR, PRIV, VALID): Repr = ref_ed.decodeint("".join(map(chr, REPR))) X = ref_ed.decodeint("".join(map(chr, PUB))) Priv = ref_ed.decodeint("".join(map(chr, PRIV))) Pub = curvemod.mul(Priv, self.curve25519.base_point, self.curve25519.curve) # Check valid valid = True try: P1, P2 = self.curve25519.curve.get_y(X) except: valid = False self.assertEquals(valid, VALID) # Check mappings back and forth if valid: """ print print 'P1', P1 print 'P2', P2 print 'XXX', self.ell2.map_random_to_point(Repr) print self.assertEquals(Repr, self.ell2.map_point_to_random(P1)) self.assertEquals(Repr, self.ell2.map_point_to_random(P2)) """ self.assertEquals(Repr, self.ell2.map_point_to_random(Pub)) self.assertEquals(X, self.ell2.map_random_to_point(Repr)[0])
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 _test_with_vector(self, PUB, REPR, PRIV, VALID): Repr = ref_ed.decodeint(''.join(map(chr, REPR))) X = ref_ed.decodeint(''.join(map(chr, PUB))) Priv = ref_ed.decodeint(''.join(map(chr, PRIV))) Pub = curvemod.mul(Priv, self.curve25519.base_point, self.curve25519.curve) self.assertEquals(arr2str(PRIV), self.curve25519.canonical_binary_form_private(Priv)) self.assertEquals(arr2str(PUB), self.curve25519.canonical_binary_form_public(Pub)) self.assertEquals(Priv, self.curve25519.binary_to_private(arr2str(PRIV)))
def test_multiplication_by_0(self): self.assertEquals(self.curve.neutral_point(), mul(0, self.A, self.curve))
def generate_key_pair(self, seed): private = self.generate_private_key(seed) public = curve.mul(private, self.base_point, self.curve) return (public, private)
def test_generator(self): self.assertEquals(self.curve.neutral_point(), mul(self.bp_order, self.bp, self.curve))
def test_multiplication(self): self.assertEquals(self.MUL_P_1, mul(self.MUL_K_1, self.bp, self.curve)) self.assertEquals(self.MUL_P_2, mul(self.MUL_K_2, self.bp, self.curve))
def test_multiplication_by_1(self): self.assertEquals(self.A, mul(1, self.A, self.curve))
def test_multiplication_by_2_equals_doubling(self): self.assertEquals(self.curve.double_point(self.A), mul(2, self.A, self.curve))
def derive_public_key(self, private): return curve.mul(private, self.base_point, self.curve)
def ecdh(curve_obj, my_private, other_public): """Derive the shared secret in ECDH.""" # here curve_obj is from asymmetric.ECCBase return curve.mul(my_private, other_public, curve_obj.curve)