Package dns :: Module entropy
[hide private]
[frames] | no frames]

Source Code for Module dns.entropy

 1  # Copyright (C) 2009 Nominum, Inc. 
 2  # 
 3  # Permission to use, copy, modify, and distribute this software and its 
 4  # documentation for any purpose with or without fee is hereby granted, 
 5  # provided that the above copyright notice and this permission notice 
 6  # appear in all copies. 
 7  # 
 8  # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 
 9  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
10  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 
11  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
12  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
13  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 
14  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
15   
16  import time 
17   
18 -class EntropyPool(object):
19 - def __init__(self, seed=None):
20 self.pool_index = 0 21 self.digest = None 22 self.next_byte = 0 23 if seed is None: 24 try: 25 r = file('/dev/random') 26 try: 27 seed = r.read(16) 28 finally: 29 r.close() 30 except: 31 seed = str(time.time()) 32 try: 33 import hashlib 34 self.hash = hashlib.sha1() 35 self.hash_len = 20 36 except: 37 try: 38 import sha 39 self.hash = sha.new() 40 self.hash_len = 20 41 except: 42 import md5 43 self.hash = md5.new() 44 self.hash_len = 16 45 self.pool = '\0' * self.hash_len 46 self.stir(seed)
47
48 - def stir(self, entropy):
49 bytes = [ord(c) for c in self.pool] 50 for c in entropy: 51 if self.pool_index == self.hash_len: 52 self.pool_index = 0 53 b = ord(c) & 0xff 54 bytes[self.pool_index] ^= b 55 self.pool_index += 1 56 self.pool = ''.join([chr(c) for c in bytes])
57
58 - def random_8(self):
59 if self.digest is None or self.next_byte == self.hash_len: 60 self.hash.update(self.pool) 61 self.digest = self.hash.digest() 62 self.stir(self.digest) 63 self.next_byte = 0 64 value = ord(self.digest[self.next_byte]) 65 self.next_byte += 1 66 return value
67
68 - def random_16(self):
69 return self.random_8() * 256 + self.random_8()
70
71 - def random_32(self):
72 return self.random_16() * 65536 + self.random_16()
73
74 - def random_between(self, first, last):
75 size = last - first + 1 76 if size > 4294967296L: 77 raise ValueError, 'too big' 78 if size > 65536: 79 rand = self.random_32 80 max = 4294967295L 81 elif size > 256: 82 rand = self.random_16 83 max = 65535 84 else: 85 rand = self.random_8 86 max = 255 87 return (first + size * rand() // (max + 1))
88 89 pool = EntropyPool() 90
91 -def random_16():
92 return pool.random_16()
93
94 -def between(first, last):
95 return pool.random_between(first, last)
96