33import os
44import math
55import binascii
6+ import sys
67from hashlib import sha256
78from six import PY3 , int2byte , b , next
89from . import der
1617oid_ecPublicKey = (1 , 2 , 840 , 10045 , 2 , 1 )
1718encoded_oid_ecPublicKey = der .encode_oid (* oid_ecPublicKey )
1819
20+ if sys .version > '3' :
21+ def entropy_to_bits (ent_256 ):
22+ """Convert a bytestring to string of 0's and 1's"""
23+ return bin (int .from_bytes (ent_256 , 'big' ))[2 :].zfill (len (ent_256 )* 8 )
24+ else :
25+ def entropy_to_bits (ent_256 ):
26+ """Convert a bytestring to string of 0's and 1's"""
27+ return '' .join (bin (ord (x ))[2 :].zfill (8 ) for x in ent_256 )
1928
20- def bit_length (num ):
21- # http://docs.python.org/dev/library/stdtypes.html#int.bit_length
22- s = bin (num ) # binary representation: bin(-37) --> '-0b100101'
23- s = s .lstrip ('-0b' ) # remove leading zeros and minus sign
24- return len (s ) # len('100101') --> 6
29+
30+ if sys .version < '2.7' : #Can't add a method to a built-in type so we are stuck with this
31+ def bit_length (x ):
32+ return len (bin (x )) - 2
33+ else :
34+ def bit_length (x ):
35+ return x .bit_length () or 1
2536
2637
2738def orderlen (order ):
@@ -30,43 +41,26 @@ def orderlen(order):
3041
3142def randrange (order , entropy = None ):
3243 """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.
44+ distributed across that range. Worst case should be a mean of 2 loops at
45+ (2**k)+2.
4046
4147 Note that this function is not declared to be forwards-compatible: we may
4248 change the behavior in future releases. The entropy= argument (which
4349 should get a callable that behaves like os.urandom) can be used to
4450 achieve stability within a given release (for repeatable unit tests), but
4551 should not be used as a long-term-compatible key generation algorithm.
4652 """
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-
53+ assert order > 1
5654 if entropy is None :
5755 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 )
56+ upper_2 = bit_length (order - 2 )
57+ upper_256 = upper_2 // 8 + 1
58+ while True : # I don't think this needs a counter with bit-wise randrange
59+ ent_256 = entropy (upper_256 )
60+ ent_2 = entropy_to_bits (ent_256 )
61+ rand_num = int (ent_2 [:upper_2 ], base = 2 ) + 1
62+ if 0 < rand_num < order :
63+ return rand_num
7064
7165
7266class PRNG :
0 commit comments