Skip to content

Commit 9f0397a

Browse files
committed
Make test framework produce lowS signatures
1 parent 4c0c25a commit 9f0397a

File tree

1 file changed

+23
-2
lines changed
  • qa/rpc-tests/test_framework

1 file changed

+23
-2
lines changed

qa/rpc-tests/test_framework/key.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
# this specifies the curve used with ECDSA.
7676
NID_secp256k1 = 714 # from openssl/obj_mac.h
7777

78+
SECP256K1_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
79+
SECP256K1_ORDER_HALF = SECP256K1_ORDER // 2
80+
7881
# Thx to Sam Devlin for the ctypes magic 64-bit fix.
7982
def _check_result(val, func, args):
8083
if val == 0:
@@ -147,7 +150,7 @@ def get_ecdh_key(self, other_pubkey, kdf=lambda k: hashlib.sha256(k).digest()):
147150
r = self.get_raw_ecdh_key(other_pubkey)
148151
return kdf(r)
149152

150-
def sign(self, hash):
153+
def sign(self, hash, low_s = True):
151154
# FIXME: need unit tests for below cases
152155
if not isinstance(hash, bytes):
153156
raise TypeError('Hash must be bytes instance; got %r' % hash.__class__)
@@ -159,7 +162,25 @@ def sign(self, hash):
159162
mb_sig = ctypes.create_string_buffer(sig_size0.value)
160163
result = ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k)
161164
assert 1 == result
162-
return mb_sig.raw[:sig_size0.value]
165+
assert mb_sig.raw[0] == 0x30
166+
assert mb_sig.raw[1] == sig_size0.value - 2
167+
total_size = mb_sig.raw[1]
168+
assert mb_sig.raw[2] == 2
169+
r_size = mb_sig.raw[3]
170+
assert mb_sig.raw[4 + r_size] == 2
171+
s_size = mb_sig.raw[5 + r_size]
172+
s_value = int.from_bytes(mb_sig.raw[6+r_size:6+r_size+s_size], byteorder='big')
173+
if (not low_s) or s_value <= SECP256K1_ORDER_HALF:
174+
return mb_sig.raw[:sig_size0.value]
175+
else:
176+
low_s_value = SECP256K1_ORDER - s_value
177+
low_s_bytes = (low_s_value).to_bytes(33, byteorder='big')
178+
while len(low_s_bytes) > 1 and low_s_bytes[0] == 0 and low_s_bytes[1] < 0x80:
179+
low_s_bytes = low_s_bytes[1:]
180+
new_s_size = len(low_s_bytes)
181+
new_total_size_byte = (total_size + new_s_size - s_size).to_bytes(1,byteorder='big')
182+
new_s_size_byte = (new_s_size).to_bytes(1,byteorder='big')
183+
return b'\x30' + new_total_size_byte + mb_sig.raw[2:5+r_size] + new_s_size_byte + low_s_bytes
163184

164185
def verify(self, hash, sig):
165186
"""Verify a DER signature"""

0 commit comments

Comments
 (0)