Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

0.12.3dev: Improved `hex_entropy()` to use `os.urandom()` if it is av…

…ailable, and improved the fallback so that different processes don't generate the same sequence.

Closes #10397.


git-svn-id: http://trac.edgewall.org/intertrac/log:/branches/0.12-stable@10834 af82e41b-90c4-0310-8c96-b1721e28e2e2
  • Loading branch information...
commit 79d4dbe0d4aff9314c5e6cd86aa59adb017942f9 1 parent c177bde
rblank authored
Showing with 35 additions and 3 deletions.
  1. +18 −3 trac/util/__init__.py
  2. +17 −0 trac/util/tests/__init__.py
View
21 trac/util/__init__.py
@@ -555,12 +555,27 @@ def normalize(attr):
# -- crypto utils
-_entropy = random.Random()
+try:
+ os.urandom(16)
+ urandom = os.urandom
-def hex_entropy(bytes=32):
- return sha1(str(_entropy.random())).hexdigest()[:bytes]
+except NotImplementedError:
+ _entropy = random.Random()
+
+ def urandom(n):
+ result = []
+ hasher = sha1(str(os.getpid()) + str(time.time()))
+ while len(result) * hasher.digest_size < n:
+ hasher.update(str(_entropy.random()))
+ result.append(hasher.digest())
+ result = ''.join(result)
+ return len(result) > n and result[:n] or result
+def hex_entropy(bytes=32):
+ result = ''.join('%.2x' % ord(v) for v in urandom((bytes + 1) // 2))
+ return len(result) > bytes and result[:bytes] or result
+
# Original license for md5crypt:
# Based on FreeBSD src/lib/libcrypt/crypt.c 1.2
#
View
17 trac/util/tests/__init__.py
@@ -113,7 +113,24 @@ def setUp(self):
def tearDown(self):
random.setstate(self.state)
+ def test_urandom(self):
+ """urandom() returns random bytes"""
+ for i in xrange(129):
+ self.assertEqual(i, len(util.urandom(i)))
+ # For a large enough sample, each value should appear at least once
+ entropy = util.urandom(65536)
+ values = set(ord(c) for c in entropy)
+ self.assertEqual(256, len(values))
+
def test_hex_entropy(self):
+ """hex_entropy() returns random hex digits"""
+ hex_digits = set('0123456789abcdef')
+ for i in xrange(129):
+ entropy = util.hex_entropy(i)
+ self.assertEqual(i, len(entropy))
+ self.assertEqual(set(), set(entropy) - hex_digits)
+
+ def test_hex_entropy_global_state(self):
"""hex_entropy() not affected by global random generator state"""
random.seed(0)
data = util.hex_entropy(64)
Please sign in to comment.
Something went wrong with that request. Please try again.