Skip to content

Commit d297675

Browse files
committed
bytes input for SigningKey.sign_deterministic()
as extra_entropy can be large, and different type than outputs from either bits2octets or number_to_string, do not concatenate them but rather push them to the hmac one by one don't use six.b(), not needed on py2.6 simplify the chained comparison and remove unneeded else after return in rfc5979.generate_k
1 parent f7c08bd commit d297675

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

src/ecdsa/_compat.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,21 @@ def normalise_bytes(buffer_object):
1818
"""Cast the input into array of bytes."""
1919
return buffer(buffer_object)
2020

21+
def hmac_compat(ret):
22+
return ret
2123

2224
else:
25+
if sys.version_info < (3, 4):
26+
# on python 3.3 hmac.hmac.update() accepts only bytes, on newer
27+
# versions it does accept memoryview() also
28+
def hmac_compat(data):
29+
if not isinstance(data, bytes):
30+
return bytes(data)
31+
return data
32+
else:
33+
def hmac_compat(data):
34+
return data
35+
2336
def normalise_bytes(buffer_object):
2437
"""Cast the input into array of bytes."""
2538
return memoryview(buffer_object).cast('B')

src/ecdsa/keys.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,8 @@ def sign_deterministic(self, data, hashfunc=None,
974974
:rtype: bytes or sigencode function dependant type
975975
"""
976976
hashfunc = hashfunc or self.default_hashfunc
977+
data = normalise_bytes(data)
978+
extra_entropy = normalise_bytes(extra_entropy)
977979
digest = hashfunc(data).digest()
978980

979981
return self.sign_digest_deterministic(

src/ecdsa/rfc6979.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import hmac
1313
from binascii import hexlify
1414
from .util import number_to_string, number_to_string_crop, bit_length
15-
from six import b
15+
from ._compat import hmac_compat
1616

1717

1818
# bit_length was defined in this module previously so keep it for backwards
@@ -54,32 +54,41 @@ def generate_k(order, secexp, hash_func, data, retry_gen=0, extra_entropy=b''):
5454
qlen = bit_length(order)
5555
holen = hash_func().digest_size
5656
rolen = (qlen + 7) / 8
57-
bx = number_to_string(secexp, order) + bits2octets(data, order) + \
58-
extra_entropy
57+
bx = (hmac_compat(number_to_string(secexp, order)),
58+
hmac_compat(bits2octets(data, order)),
59+
hmac_compat(extra_entropy))
5960

6061
# Step B
61-
v = b('\x01') * holen
62+
v = b'\x01' * holen
6263

6364
# Step C
64-
k = b('\x00') * holen
65+
k = b'\x00' * holen
6566

6667
# Step D
6768

68-
k = hmac.new(k, v + b('\x00') + bx, hash_func).digest()
69+
k = hmac.new(k, digestmod=hash_func)
70+
k.update(v + b'\x00')
71+
for i in bx:
72+
k.update(i)
73+
k = k.digest()
6974

7075
# Step E
7176
v = hmac.new(k, v, hash_func).digest()
7277

7378
# Step F
74-
k = hmac.new(k, v + b('\x01') + bx, hash_func).digest()
79+
k = hmac.new(k, digestmod=hash_func)
80+
k.update(v + b'\x01')
81+
for i in bx:
82+
k.update(i)
83+
k = k.digest()
7584

7685
# Step G
7786
v = hmac.new(k, v, hash_func).digest()
7887

7988
# Step H
8089
while True:
8190
# Step H1
82-
t = b('')
91+
t = b''
8392

8493
# Step H2
8594
while len(t) < rolen:
@@ -89,11 +98,10 @@ def generate_k(order, secexp, hash_func, data, retry_gen=0, extra_entropy=b''):
8998
# Step H3
9099
secret = bits2int(t, qlen)
91100

92-
if secret >= 1 and secret < order:
101+
if 1 <= secret < order:
93102
if retry_gen <= 0:
94103
return secret
95-
else:
96-
retry_gen -= 1
104+
retry_gen -= 1
97105

98-
k = hmac.new(k, v + b('\x00'), hash_func).digest()
106+
k = hmac.new(k, v + b'\x00', hash_func).digest()
99107
v = hmac.new(k, v, hash_func).digest()

src/ecdsa/test_keys.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def test_array_array_of_bytes_memoryview(self):
178178
sha1 = hashlib.sha1()
179179
sha1.update(data)
180180
data_hash = sha1.digest()
181-
181+
assert isinstance(data_hash, bytes)
182182
sig_raw = sk.sign(data, sigencode=sigencode_string)
183183
assert isinstance(sig_raw, bytes)
184184
sig_der = sk.sign(data, sigencode=sigencode_der)
@@ -272,3 +272,15 @@ def test_SigningKey_from_der(convert):
272272
sk = SigningKey.from_der(key)
273273

274274
assert sk.to_string() == prv_key_bytes
275+
276+
277+
# test SigningKey.sign_deterministic()
278+
extra_entropy=b'\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11'
279+
280+
@pytest.mark.parametrize("convert", converters)
281+
def test_SigningKey_sign_deterministic(convert):
282+
sig = sk.sign_deterministic(
283+
convert(data),
284+
extra_entropy=convert(extra_entropy))
285+
286+
vk.verify(sig, data)

0 commit comments

Comments
 (0)