SHA-based subclass for random module

Josiah Carlson jcarlson at nospam.uci.edu
Tue Mar 23 23:28:45 EST 2004


> This would be easy to implement with Mersenne Twister too.  Though it 
> would involve some rewriting.
> 
> Do you think this is worthwhile?

I don't know, but I'm leaning towards not really.

     def getrandstring(self, n):
         out = [struct.pack('>L', self.getrandbits(32)) \
                for i in xrange(0, n, 4)]
         out.extend([chr(self.getrandbits(4)) for i in xrange(n%4)])
         return ''.join(out)

You have your getrandstring for any class that provides getrandbits, and 
is relatively optimized to deal with very long output strings.

     def getrandbits(self, n):
         out = 0
         for i in xrange(0, n+16, 16):
             out = out << 16 + struct.unpack('>H', self.getrandstring(2))
	return out >> (16-(n%16))

Now you have getrandbits for any method that provides getrandstring, and 
it is optimized to deal with a Python long internal representation.

  - Josiah


On a relatively unrelated note, I'm leaning toward trying to get the 
benefits of both SHA and MT with the following, though I lack the heavy 
mathematical background to prove whether it is better than either.

class SHARandom(Random):
     def random(self, tofloat = 1.0 / 2 ** 53, divint = 2**64):
         grb = self.getrandbits
         plaintxt = struct.pack("<QQL", grb(64), grb(64), grb(32))
         ciphertext = sha.new(plaintxt+self.sha_state).digest()
         randint = unpack('<Q', ciphertxt[:8])[0] >> 11 # grab 53 bits
         self.sha_state = ciphertext[7:] #keep hidden state
         return randint * tofloat

     #deal with state initialization and seeding
     def __init__(self, x=None, y=None):
         self.seed(x,y)
     def seed(self, x=None, y=None):
         Random.seed(x)
         self.sha_state = sha.new(str(y)).digest()[7:]

     #deal with state persistency
     def getstate(self):
         return (Random.getstate(self), self.sha_state)
     def setstate(self, state):
         Random.setstate(state[0])
         self.sha_state = state[1]



More information about the Python-list mailing list