summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@dnspython.org>2008-10-08 09:35:24 +0000
committerBob Halley <halley@dnspython.org>2008-10-08 09:35:24 +0000
commite24a606aea6c97d6a73f658388cfc82319f2fce0 (patch)
treeeb58159911092a52c8799155552dd04793b607c2
parent4976373028e65e793919201477722b5c822cc02c (diff)
downloaddnspython-e24a606aea6c97d6a73f658388cfc82319f2fce0.tar.gz
add entropy module
-rw-r--r--dns/__init__.py1
-rw-r--r--dns/entropy.py95
2 files changed, 96 insertions, 0 deletions
diff --git a/dns/__init__.py b/dns/__init__.py
index ff94406..2d4cfd7 100644
--- a/dns/__init__.py
+++ b/dns/__init__.py
@@ -18,6 +18,7 @@
__all__ = [
'dnssec',
'e164',
+ 'entropy',
'exception',
'flags',
'inet',
diff --git a/dns/entropy.py b/dns/entropy.py
new file mode 100644
index 0000000..a73e5e3
--- /dev/null
+++ b/dns/entropy.py
@@ -0,0 +1,95 @@
+# Copyright (C) 2008 Nominum, Inc.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose with or without fee is hereby granted,
+# provided that the above copyright notice and this permission notice
+# appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import time
+
+class EntropyPool(object):
+ def __init__(self, seed=None):
+ self.pool_index = 0
+ self.digest = None
+ self.next_byte = 0
+ if seed is None:
+ try:
+ r = file('/dev/random')
+ try:
+ seed = r.read(16)
+ finally:
+ r.close()
+ except:
+ seed = str(time.time())
+ try:
+ import hashlib
+ self.hash = hashlib.sha1()
+ self.hash_len = 20
+ except:
+ try:
+ import sha
+ self.hash = sha.new()
+ self.hash_len = 20
+ except:
+ import md5
+ self.hash = md5.new()
+ self.hash_len = 16
+ self.pool = '\0' * self.hash_len
+ self.stir(seed)
+
+ def stir(self, entropy):
+ bytes = [ord(c) for c in self.pool]
+ for c in entropy:
+ if self.pool_index == self.hash_len:
+ self.pool_index = 0
+ b = ord(c) & 0xff
+ bytes[self.pool_index] ^= b
+ self.pool_index += 1
+ self.pool = ''.join([chr(c) for c in bytes])
+
+ def random_8(self):
+ if self.digest is None or self.next_byte == self.hash_len:
+ self.hash.update(self.pool)
+ self.digest = self.hash.digest()
+ self.stir(self.digest)
+ self.next_byte = 0
+ value = ord(self.digest[self.next_byte])
+ self.next_byte += 1
+ return value
+
+ def random_16(self):
+ return self.random_8() * 256 + self.random_8()
+
+ def random_32(self):
+ return self.random_16() * 65536 + self.random_16()
+
+ def random_between(self, first, last):
+ size = last - first + 1
+ if size > 4294967296L:
+ raise ValueError, 'too big'
+ if size > 65536:
+ rand = self.random_32
+ max = 4294967295L
+ elif size > 256:
+ rand = self.random_16
+ max = 65535
+ else:
+ rand = self.random_8
+ max = 255
+ return (first + size * rand() // (max + 1))
+
+pool = EntropyPool()
+
+def random_16():
+ return pool.random_16()
+
+def between(first, last):
+ return pool.random_between(first, last)