0,0 → 1,75 |
""" crypto.entropy.pagingEntropy |
|
Uses variations in disk access time to generator entropy. A long string is |
created that is bigger than available memory. Virtual memory access' create |
random variations in retrieval time. |
|
Just an experiment, not recommended for use at this time. |
|
Copyright © (c) 2002 by Paul A. Lambert |
Read LICENSE.txt for license information. |
""" |
import struct |
|
class PagingEntropyCollector: |
""" collect entropy from memory paging """ |
def __init__(self, memSize=500000000L): #? how should this be picked? |
""" Initialize paging entropy collector, |
memSize must be larger than allocated memory """ |
self.size = memSize |
self.memBlock = self.size*chr(0) # long string of length self.size |
self.index = 0 |
import random |
self.rand = random.Random(1555551) |
|
def randomBytes(self, numberOfBytes, secondsPerBit=.05): |
byteString = '' |
for b in range(numberOfBytes): |
aByte = 0 |
for bit in range(8): |
aByte = aByte << 1 |
aByte = aByte ^ self.collectBit(secondsPerBit) |
byteString += chr(aByte) |
return byteString |
|
def collectBit(self, secondsPerBit=1.0): |
""" Collect an entropy bit by jumping around a long string and |
collecting the variation in time and number of samples per |
time interval """ |
t1 = time() |
count = 0 |
while (time()-t1) < secondsPerBit: # seconds per sample |
# use random to sample various virtual memory locations |
sample = self.memBlock[int(self.rand.random()*self.size)] |
count += 1 |
randomBit = intToParity(count)^floatToParity(time()-t1) |
return randomBit |
|
def intToParity(integer): |
s = struct.pack('i',integer) |
parity = 0 |
for character in s: |
byte = ord(character) |
parity = parity^(0x01&(byte^(byte>>1)^(byte>>2)^(byte>>3)^(byte>>4)^(byte>>5)^(byte>>6)^(byte>>7))) |
return parity |
|
def floatToParity(float): |
s = struct.pack('d',float) |
parity = 0 |
for character in s: |
byte = ord(character) |
parity = parity^(0x01&(byte^(byte>>1)^(byte>>2)^(byte>>3)^(byte>>4)^(byte>>5)^(byte>>6)^(byte>>7))) |
return parity |
|
if __name__ == "__main__": |
from binascii import b2a_hex |
e = PagingEntropyCollector() |
for i in range(20): |
e.rand.seed(1) # make each sample set the same to allow examination of statistics |
print b2a_hex( e.randomBytes(16) ) |
|
|
|
|
|
|