|
|
|
@ -75,6 +75,9 @@ ssl.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p,
@@ -75,6 +75,9 @@ ssl.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p,
|
|
|
|
|
# this specifies the curve used with ECDSA. |
|
|
|
|
NID_secp256k1 = 714 # from openssl/obj_mac.h |
|
|
|
|
|
|
|
|
|
SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 |
|
|
|
|
SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2 |
|
|
|
|
|
|
|
|
|
# Thx to Sam Devlin for the ctypes magic 64-bit fix. |
|
|
|
|
def _check_result(val, func, args): |
|
|
|
|
if val == 0: |
|
|
|
@ -147,7 +150,7 @@ class CECKey(object):
@@ -147,7 +150,7 @@ class CECKey(object):
|
|
|
|
|
r = self.get_raw_ecdh_key(other_pubkey) |
|
|
|
|
return kdf(r) |
|
|
|
|
|
|
|
|
|
def sign(self, hash): |
|
|
|
|
def sign(self, hash, low_s = True): |
|
|
|
|
# FIXME: need unit tests for below cases |
|
|
|
|
if not isinstance(hash, bytes): |
|
|
|
|
raise TypeError('Hash must be bytes instance; got %r' % hash.__class__) |
|
|
|
@ -159,7 +162,25 @@ class CECKey(object):
@@ -159,7 +162,25 @@ class CECKey(object):
|
|
|
|
|
mb_sig = ctypes.create_string_buffer(sig_size0.value) |
|
|
|
|
result = ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k) |
|
|
|
|
assert 1 == result |
|
|
|
|
assert mb_sig.raw[0] == 0x30 |
|
|
|
|
assert mb_sig.raw[1] == sig_size0.value - 2 |
|
|
|
|
total_size = mb_sig.raw[1] |
|
|
|
|
assert mb_sig.raw[2] == 2 |
|
|
|
|
r_size = mb_sig.raw[3] |
|
|
|
|
assert mb_sig.raw[4 + r_size] == 2 |
|
|
|
|
s_size = mb_sig.raw[5 + r_size] |
|
|
|
|
s_value = int.from_bytes(mb_sig.raw[6+r_size:6+r_size+s_size], byteorder='big') |
|
|
|
|
if (not low_s) or s_value <= SECP256K1_ORDER_HALF: |
|
|
|
|
return mb_sig.raw[:sig_size0.value] |
|
|
|
|
else: |
|
|
|
|
low_s_value = SECP256K1_ORDER - s_value |
|
|
|
|
low_s_bytes = (low_s_value).to_bytes(33, byteorder='big') |
|
|
|
|
while len(low_s_bytes) > 1 and low_s_bytes[0] == 0 and low_s_bytes[1] < 0x80: |
|
|
|
|
low_s_bytes = low_s_bytes[1:] |
|
|
|
|
new_s_size = len(low_s_bytes) |
|
|
|
|
new_total_size_byte = (total_size + new_s_size - s_size).to_bytes(1,byteorder='big') |
|
|
|
|
new_s_size_byte = (new_s_size).to_bytes(1,byteorder='big') |
|
|
|
|
return b'\x30' + new_total_size_byte + mb_sig.raw[2:5+r_size] + new_s_size_byte + low_s_bytes |
|
|
|
|
|
|
|
|
|
def verify(self, hash, sig): |
|
|
|
|
"""Verify a DER signature""" |
|
|
|
|