Include module for desktop build
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# Copyright (c) 2002-2012 Zooko Wilcox-O'Hearn
|
||||
# This file is part of pyutil; see README.rst for licensing terms.
|
||||
|
||||
import warnings
|
||||
|
||||
"""
|
||||
Cryptographically strong pseudo-random number generator based on SHA256.
|
||||
"""
|
||||
|
||||
class SHA256Expander:
|
||||
"""
|
||||
Provide a cryptographically strong pseudo-random number generator based on
|
||||
SHA256. Hopefully this means that no attacker will be able to predict any
|
||||
bit of output that he hasn't seen, given that he doesn't know anything about
|
||||
the seed and given that he can see as many bits of output as he desires
|
||||
except for the bit that he is trying to predict. Further it is hoped that
|
||||
an attacker will not even be able to determine whether a given stream of
|
||||
random bytes was generated by this PRNG or by flipping a coin repeatedly.
|
||||
The safety of this technique has not been verified by a Real Cryptographer.
|
||||
... but it is similar to the PRNG in FIPS-186...
|
||||
|
||||
The seed and counter are encoded in DJB's netstring format so that I
|
||||
don't have to think about the possibility of ambiguity.
|
||||
|
||||
Note: I've since learned more about the theory of secure hash functions
|
||||
and the above is a strong assumption about a secure hash function. Use
|
||||
of this class should be considered deprecated and you should use a more
|
||||
well-analyzed KDF (such as the nascent standard HKDF) or stream cipher or
|
||||
whatever it is that you need.
|
||||
"""
|
||||
def __init__(self, seed=None):
|
||||
warnings.warn("deprecated", DeprecationWarning)
|
||||
if seed is not None:
|
||||
self.seed(seed)
|
||||
|
||||
def seed(self, seed):
|
||||
import hashlib
|
||||
self.starth = hashlib.sha256('24:pyutil hash expansion v2,10:algorithm:,6:SHA256,6:value:,')
|
||||
seedlen = len(seed)
|
||||
seedlenstr = str(seedlen)
|
||||
self.starth.update(seedlenstr)
|
||||
self.starth.update(':')
|
||||
self.starth.update(seed)
|
||||
self.starth.update(',')
|
||||
|
||||
self.avail = ""
|
||||
self.counter = 0
|
||||
|
||||
def get(self, bytes):
|
||||
bytesleft = bytes
|
||||
|
||||
res = []
|
||||
|
||||
while bytesleft > 0:
|
||||
if len(self.avail) == 0:
|
||||
h = self.starth.copy()
|
||||
counterstr = str(self.counter)
|
||||
counterstrlen = len(counterstr)
|
||||
counterstrlenstr = str(counterstrlen)
|
||||
h.update(counterstrlenstr)
|
||||
h.update(':')
|
||||
h.update(counterstr)
|
||||
h.update(',')
|
||||
self.avail = h.digest()
|
||||
self.counter += 1
|
||||
|
||||
numb = min(len(self.avail), bytesleft)
|
||||
|
||||
(chunk, self.avail,) = (self.avail[:numb], self.avail[numb:],)
|
||||
|
||||
res.append(chunk)
|
||||
|
||||
bytesleft = bytesleft - numb
|
||||
|
||||
resstr = ''.join(res)
|
||||
assert len(resstr) == bytes
|
||||
|
||||
return resstr
|
||||
|
||||
def sha256expand(inpstr, expbytes):
|
||||
return SHA256Expander(inpstr).get(expbytes)
|
||||
Reference in New Issue
Block a user