From b37425d20991bc147932d1eddea01e1d929ceb5d Mon Sep 17 00:00:00 2001 From: Bob Halley Date: Fri, 13 Nov 2009 03:16:09 +0900 Subject: Try using os.urandom() to get the seed. Lock access to the entropy pool to avoid races in multithreaded situations. If a seed wasn't supplied, don't do the seeding operation until someone actually wants to get random numbers. --- dns/entropy.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'dns/entropy.py') diff --git a/dns/entropy.py b/dns/entropy.py index fa448d1..9e10d12 100644 --- a/dns/entropy.py +++ b/dns/entropy.py @@ -13,6 +13,7 @@ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import os import time try: import threading as _threading @@ -25,15 +26,6 @@ class EntropyPool(object): self.digest = None self.next_byte = 0 self.lock = _threading.Lock() - if seed is None: - try: - r = file('/dev/random', 'r', 0) - try: - seed = r.read(16) - finally: - r.close() - except: - seed = str(time.time()) try: import hashlib self.hash = hashlib.sha1() @@ -48,7 +40,11 @@ class EntropyPool(object): self.hash = md5.new() self.hash_len = 16 self.pool = '\0' * self.hash_len - self.stir(seed) + if not seed is None: + self.stir(seed) + self.seeded = True + else: + self.seeded = False def stir(self, entropy, already_locked=False): if not already_locked: @@ -66,8 +62,25 @@ class EntropyPool(object): if not already_locked: self.lock.release() + def _maybe_seed(self): + if not self.seeded: + try: + seed = os.urandom(16) + except: + try: + r = file('/dev/urandom', 'r', 0) + try: + seed = r.read(16) + finally: + r.close() + except: + seed = str(time.time()) + self.seeded = True + self.stir(seed, True) + def random_8(self): self.lock.acquire() + self._maybe_seed() try: if self.digest is None or self.next_byte == self.hash_len: self.hash.update(self.pool) -- cgit v1.2.1