[pycrypto] ERROR: testRsaUnversionedSignAndVerify failed
Dwayne C. Litzenberger
dlitz at dlitz.net
Thu Aug 20 19:55:43 CST 2009
On Thu, Aug 20, 2009 at 01:42:12PM -0700, Steve Weis wrote:
>Are there advantages to using Pycrypto's Randpool over
>In another Keyczar thread, someone reported that Randpool was a performance
>bottleneck and got a big improvement by switching to SystemRandom.
>I don't know enough about the underlying implementations to make any
>security judgement. If anyone can comment authoritatively, please do.
Quoting myself in https://bugs.launchpad.net/pycrypto/+bug/249765:
RandomPool really really needs to die, at least in its current form.
It's not thread-safe, it's not fork-safe, and if it can't get entropy
from the OS, it silently produces predictable output. What's worse is
that everyone assumes that it's a portable substitute for reading from
/dev/urandom on Linux, but it's actually way too fragile to be safely
used that way.
It's also much slower than just reading from /dev/urandom on Linux. I
don't remember how it compares on Windows.
You could use random.SystemRandom(), which is basically just a wrapper
around reading from /dev/urandom of Windows's CryptGenRandom. That's
better than using RandomPool, but there are still caveats:
- Some systems are adversely affected when you read a lot of data from the
operating system's PRNG. For example, old versions of Linux (I don't
remember how old, but it wasn't too long ago) starved /dev/random if you
had a process continually reading from /dev/urandom.
- Windows XP's (and probably earlier's) PRNG is vulnerable to a
state-extension attack, because it inappropriately uses RC4:
- I'm told that some old *nix's /dev/urandom devices are far less
trustworthy than Linux's.
- Even the security of Linux's /dev/urandom is debated (search lkml.org for
Jean-Luc Cooke & Fortuna).
Why trust them when you can trust me? (Hah!)
Regarding this patch:
>> --- util.py.orig 2009-08-20 10:40:19.248702303 +0200
>> +++ util.py 2009-08-20 10:57:27.765198430 +0200
>> @@ -30,7 +30,12 @@ except ImportError:
>> from sha import sha as sha1
>> from Crypto.Hash.SHA256 import new as sha256
>> -from Crypto.Util import randpool
>> + # Import RandomPoolCompat, if available
>> + from Crypto.Random import RandomPoolCompat as RandomPool
>> +except ImportError:
>> + from Crypto.Util.randpool import RandomPool
>> from pyasn1.codec.der import decoder
>> from pyasn1.codec.der import encoder
>> from pyasn1.type import univ
>> @@ -291,7 +296,7 @@ def TrimBytes(bytes):
>> def RandBytes(n):
>> """Return n random bytes."""
>> - return randpool.RandomPool(512).get_bytes(n)
>> + return RandomPool(512).get_bytes(n)
>> def Hash(digest, *inputs):
>> """Return a SHA-1 hash over a variable number of inputs."""
That will work, but it will perform better if you invoke Random.new() once,
then .read() from the resulting object every time you want random data.
I don't recommend using RandomPoolCompat, and after seeing it used here I
think I will drop it before the next release. RandomPool is *broken*, and
on Windows it is a catastrophic security hole. You should not use it even
to maintain backwards compatibility.
Instead, use os.urandom() if Crypto.Random is not available (but you should
use Crypto.Random if it's available: Crypto.Random performs better than
os.urandom on Linux, and on Windows it provides a workaround for the
weaknesses in Microsoft's RC4-based CryptGenRandom implementation).
You can use this code. I hereby release it into the public domain:
from Crypto import Random
_rng_instance = Random.new()
_rng_instance = RandomStub()
"""Return n random bytes."""
Does that help clarify things?
Dwayne C. Litzenberger <dlitz at dlitz.net>
Key-signing key - 19E1 1FE8 B3CF F273 ED17 4A24 928C EC13 39C2 5CF7
More information about the pycrypto