Skip to content

Commit d0d6a34

Browse files
author
Atif Nazir
committed
Prepare for 1.1.14
Use low R signatures by default Update tests Update package dependencies Disallow Python 3.0-3.4 given dependencies
1 parent 8af8a7f commit d0d6a34

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

block_io/__init__.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,22 @@ def __init__(self, privkey, pubkey = None, compressed = True):
4444
# use the uncompressed public key
4545
self.public_key = unhexlify('04' + hexlify(self.private_key.get_verifying_key().to_string()).decode("utf-8"))
4646

47-
def sign(self, data_to_sign):
48-
der_sig = self.private_key.sign_digest_deterministic(data_to_sign, sha256, util.sigencode_der_canonize)
49-
return der_sig
50-
51-
def sign_hex(self, hex_data):
52-
return hexlify(self.sign(unhexlify(hex_data)))
47+
def sign(self, data_to_sign, use_low_r = True):
48+
counter = 0
49+
50+
while True:
51+
extra_entropy = b""
52+
if (counter > 0):
53+
extra_entropy = bytearray.fromhex(hex(counter).split("x")[1].rjust(64,"0"))[::-1]
54+
der_sig = hexlify(self.private_key.sign_digest_deterministic(data_to_sign, sha256, util.sigencode_der_canonize, extra_entropy))
55+
if use_low_r == False or (int(der_sig[6:8],16) == 32 and int(der_sig[8:10],16) < 128): # der_sig[3] == 32 and der_sig[4] < 128):
56+
break
57+
counter = counter + 1
58+
59+
return unhexlify(der_sig)
60+
61+
def sign_hex(self, hex_data, use_low_r = True):
62+
return hexlify(self.sign(unhexlify(hex_data), use_low_r))
5363

5464
def pubkey_hex(self):
5565
return hexlify(self.public_key)

setup.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,22 @@
44
long_description = fh.read()
55

66
setup(name='block-io',
7-
version='1.1.13',
7+
version='1.1.14',
88
description='The easiest way to integrate Bitcoin, Dogecoin and Litecoin in your applications. Sign up at Block.io for your API key.',
99
url='https://github.com/BlockIo/block_io-python',
1010
author='Atif Nazir',
1111
author_email='a@block.io',
1212
license='MIT',
1313
packages=['block_io'],
14-
python_requires='>=2.7, <4',
14+
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4',
1515
long_description=long_description,
1616
long_description_content_type="text/markdown",
1717
install_requires=[
1818
'requests>=2.20.0',
19-
'pycryptodome>=3.6.6,<4.0',
20-
'ecdsa==0.13.3',
19+
'pycryptodome>=3.9.8,<4.0',
20+
'ecdsa==0.15',
2121
'six>=1.8.0',
2222
'base58==1.0.3'
2323
],
2424
zip_safe=False)
2525

26-
# for packages not on pypi
27-
# dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']

test.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,38 @@ def setUp(self):
9797
self.key = BlockIo.Key(unhexlify("6b0e34587dece0ef042c4c7205ce6b3d4a64d0bc484735b9325f7971a0ead963"))
9898
self.hex_data = "feedfacedeadbeeffeedfacedeadbeeffeedfacedeadbeeffeedfacedeadbeef"
9999

100-
def test_deterministic_k(self):
100+
def test_deterministic_k_no_extra_entropy(self):
101101
k = rfc6979.generate_k(SECP256k1.generator.order(), self.key.private_key.privkey.secret_multiplier, sha256, unhexlify(self.hex_data))
102102
self.assertEqual(hexlify(util.number_to_string(k, self.key.private_key.privkey.order)), b'ab56733dc6b9cf8fbecd9af7ba64ee5b658b8a1def2f4c4c510a2996d2761d6f')
103103

104-
def test_signature(self):
105-
sig = self.key.sign_hex(self.hex_data)
104+
def test_deterministic_k_extra_entropy_1(self):
105+
extra_entropy = bytearray.fromhex(hex(1).split("x")[1].rjust(64,"0"))[::-1]
106+
k = rfc6979.generate_k(SECP256k1.generator.order(), self.key.private_key.privkey.secret_multiplier, sha256, unhexlify(self.hex_data), 0, extra_entropy)
107+
self.assertEqual(hexlify(util.number_to_string(k, self.key.private_key.privkey.order)), b'f24f24e2e6510071c86da612ef04ccc21664a3801e0e06a227023b9c513a8290')
108+
109+
def test_deterministic_k_extra_entropy_16(self):
110+
extra_entropy = bytearray.fromhex(hex(16).split("x")[1].rjust(64,"0"))[::-1]
111+
k = rfc6979.generate_k(SECP256k1.generator.order(), self.key.private_key.privkey.secret_multiplier, sha256, unhexlify(self.hex_data), 0, extra_entropy)
112+
self.assertEqual(hexlify(util.number_to_string(k, self.key.private_key.privkey.order)), b'f42eeee9d30ec008d58ce23b2ff08fac85127e87390bccccbecc68a537da3d47')
113+
114+
def test_deterministic_k_extra_entropy_255(self):
115+
extra_entropy = bytearray.fromhex(hex(255).split("x")[1].rjust(64,"0"))[::-1]
116+
k = rfc6979.generate_k(SECP256k1.generator.order(), self.key.private_key.privkey.secret_multiplier, sha256, unhexlify(self.hex_data), 0, extra_entropy)
117+
self.assertEqual(hexlify(util.number_to_string(k, self.key.private_key.privkey.order)), b'a2c913d48ca5d18c62126a90059a552f4cafeab85b55e9acdc6848473910f150')
118+
119+
def test_deterministic_k_extra_entropy_256(self):
120+
extra_entropy = bytearray.fromhex(hex(256).split("x")[1].rjust(64,"0"))[::-1]
121+
k = rfc6979.generate_k(SECP256k1.generator.order(), self.key.private_key.privkey.secret_multiplier, sha256, unhexlify(self.hex_data), 0, extra_entropy)
122+
self.assertEqual(hexlify(util.number_to_string(k, self.key.private_key.privkey.order)), b'39c9dc355f042b24fe44184119c31b62ff9d8a3d0c5a26bada674d9595e6988d')
123+
124+
def test_signature_without_low_r(self):
125+
sig = self.key.sign_hex(self.hex_data,False)
106126
self.assertEqual(sig, b'3045022100b633aaa7cd5b7af455211531f193b61d34d20fe5ea19d23dd40d6074126150530220676617cd427db7d85923ebe4426ccecc47fb5826e3e24b60e62244e2a4811086')
107127

128+
def test_signature_with_low_r(self):
129+
sig = self.key.sign_hex(self.hex_data)
130+
self.assertEqual(sig, b'3044022042b9b4d673c85798f226c85f55ea6e114a0805bd5a0efba35f14c05235bb67b2022016333edae230c0ab607e948b48ceaefb5cab07300fb869d9da0a1b0f6bb53f65')
131+
108132
class TestHelpers(unittest.TestCase):
109133
def setUp(self):
110134
self.pin = "123456";

0 commit comments

Comments
 (0)