Skip to content

Commit 5a5ed01

Browse files
piktomato42
authored andcommitted
change default util.randrange to bit-wise
1 parent fed45a6 commit 5a5ed01

File tree

1 file changed

+11
-28
lines changed

1 file changed

+11
-28
lines changed

src/ecdsa/util.py

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,26 @@ def orderlen(order):
3030

3131
def randrange(order, entropy=None):
3232
"""Return a random integer k such that 1 <= k < order, uniformly
33-
distributed across that range. For simplicity, this only behaves well if
34-
'order' is fairly close (but below) a power of 256. The try-try-again
35-
algorithm we use takes longer and longer time (on average) to complete as
36-
'order' falls, rising to a maximum of avg=512 loops for the worst-case
37-
(256**k)+1 . All of the standard curves behave well. There is a cutoff at
38-
10k loops (which raises RuntimeError) to prevent an infinite loop when
39-
something is really broken like the entropy function not working.
33+
distributed across that range. Worst case should be a mean of 2 loops at (2**k)+2.
4034
4135
Note that this function is not declared to be forwards-compatible: we may
4236
change the behavior in future releases. The entropy= argument (which
4337
should get a callable that behaves like os.urandom) can be used to
4438
achieve stability within a given release (for repeatable unit tests), but
4539
should not be used as a long-term-compatible key generation algorithm.
4640
"""
47-
# we could handle arbitrary orders (even 256**k+1) better if we created
48-
# candidates bit-wise instead of byte-wise, which would reduce the
49-
# worst-case behavior to avg=2 loops, but that would be more complex. The
50-
# change would be to round the order up to a power of 256, subtract one
51-
# (to get 0xffff..), use that to get a byte-long mask for the top byte,
52-
# generate the len-1 entropy bytes, generate one extra byte and mask off
53-
# the top bits, then combine it with the rest. Requires jumping back and
54-
# forth between strings and integers a lot.
55-
41+
assert order > 1
5642
if entropy is None:
5743
entropy = os.urandom
58-
assert order > 1
59-
bytes = orderlen(order)
60-
dont_try_forever = 10000 # gives about 2**-60 failures for worst case
61-
while dont_try_forever > 0:
62-
dont_try_forever -= 1
63-
candidate = string_to_number(entropy(bytes)) + 1
64-
if 1 <= candidate < order:
65-
return candidate
66-
continue
67-
raise RuntimeError("randrange() tried hard but gave up, either something"
68-
" is very wrong or you got realllly unlucky. Order was"
69-
" %x" % order)
44+
upper_2 = (order-2).bit_length() or 1
45+
upper_256 = int(upper_2/8 + 1);
46+
while True: #I don't think we need a counter with bit-wise randrange
47+
ent_256 = entropy(upper_256)
48+
ent_2=''.join(bin(x)[2:].zfill(8) for x in ent_256)
49+
rand_num = int(ent_2[:upper_2], base=2) +1
50+
if 0 < rand_num < order: return rand_num
51+
else:continue
52+
7053

7154

7255
class PRNG:

0 commit comments

Comments
 (0)