summaryrefslogtreecommitdiff
path: root/lib/Crypto/Random/OSRNG
diff options
context:
space:
mode:
authorDwayne C. Litzenberger <dlitz@dlitz.net>2009-02-28 13:14:53 -0500
committerDwayne C. Litzenberger <dlitz@dlitz.net>2009-02-28 13:14:53 -0500
commitff8a657a8dd688551c59b4bbf7be33510992ee46 (patch)
treefee3a96bc95fdfda34c18c2714a75105a713ad50 /lib/Crypto/Random/OSRNG
parentd1c4875e1f220652fe7ff8358f56dee3b2aba31b (diff)
downloadpycrypto-ff8a657a8dd688551c59b4bbf7be33510992ee46.tar.gz
cleanup: Move modules to "lib/Crypto" subdirectory.
This will avoid the previous situation where scripts like the old "test.py" get included accidentally in a release. It also frees us to put additional build scripts in the top-level directory of the source tree.
Diffstat (limited to 'lib/Crypto/Random/OSRNG')
-rw-r--r--lib/Crypto/Random/OSRNG/__init__.py43
-rw-r--r--lib/Crypto/Random/OSRNG/fallback.py48
-rw-r--r--lib/Crypto/Random/OSRNG/nt.py76
-rw-r--r--lib/Crypto/Random/OSRNG/posix.py65
-rw-r--r--lib/Crypto/Random/OSRNG/rng_base.py89
5 files changed, 321 insertions, 0 deletions
diff --git a/lib/Crypto/Random/OSRNG/__init__.py b/lib/Crypto/Random/OSRNG/__init__.py
new file mode 100644
index 0000000..c7def0f
--- /dev/null
+++ b/lib/Crypto/Random/OSRNG/__init__.py
@@ -0,0 +1,43 @@
+#
+# Random/OSRNG/__init__.py : Platform-independent OS RNG API
+#
+# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# =======================================================================
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =======================================================================
+
+"""Provides a platform-independent interface to the random number generators
+supplied by various operating systems."""
+
+__revision__ = "$Id$"
+
+import os
+
+if os.name == 'posix':
+ from Crypto.Random.OSRNG.posix import new
+elif os.name == 'nt':
+ from Crypto.Random.OSRNG.nt import new
+elif hasattr(os, 'urandom'):
+ from Crypto.Random.OSRNG.fallback import new
+else:
+ raise ImportError("Not implemented")
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/Random/OSRNG/fallback.py b/lib/Crypto/Random/OSRNG/fallback.py
new file mode 100644
index 0000000..dceaf69
--- /dev/null
+++ b/lib/Crypto/Random/OSRNG/fallback.py
@@ -0,0 +1,48 @@
+#
+# Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
+#
+# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# =======================================================================
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =======================================================================
+
+__revision__ = "$Id$"
+__all__ = ['PythonOSURandomRNG']
+
+import os
+
+from rng_base import BaseRNG
+
+class PythonOSURandomRNG(BaseRNG):
+
+ name = "<os.urandom>"
+
+ def __init__(self):
+ self._read = os.urandom
+ BaseRNG.__init__(self)
+
+ def _close(self):
+ self._read = None
+
+def new(*args, **kwargs):
+ return PythonOSURandomRNG(*args, **kwargs)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/Random/OSRNG/nt.py b/lib/Crypto/Random/OSRNG/nt.py
new file mode 100644
index 0000000..06f6fec
--- /dev/null
+++ b/lib/Crypto/Random/OSRNG/nt.py
@@ -0,0 +1,76 @@
+#
+# Random/OSRNG/nt.py : OS entropy source for MS Windows
+#
+# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# =======================================================================
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =======================================================================
+
+__revision__ = "$Id$"
+__all__ = ['WindowsRNG']
+
+import winrandom
+from rng_base import BaseRNG
+
+class WindowsRNG(BaseRNG):
+
+ name = "<CryptGenRandom>"
+
+ def __init__(self):
+ self.__winrand = winrandom.new()
+ BaseRNG.__init__(self)
+
+ def flush(self):
+ """Work around weakness in Windows RNG.
+
+ The CryptGenRandom mechanism in some versions of Windows allows an
+ attacker to learn 128 KiB of past and future output. As a workaround,
+ this function reads 128 KiB of 'random' data from Windows and discards
+ it.
+
+ For more information about the weaknesses in CryptGenRandom, see
+ _Cryptanalysis of the Random Number Generator of the Windows Operating
+ System_, by Leo Dorrendorf and Zvi Gutterman and Benny Pinkas
+ http://eprint.iacr.org/2007/419
+ """
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+ data = self.__winrand.get_bytes(128*1024)
+ assert (len(data) == 128*1024)
+ BaseRNG.flush(self)
+
+ def _close(self):
+ self.__winrand = None
+
+ def _read(self, N):
+ # Unfortunately, research shows that CryptGenRandom doesn't provide
+ # forward secrecy and fails the next-bit test unless we apply a
+ # workaround, which we do here. See http://eprint.iacr.org/2007/419
+ # for information on the vulnerability.
+ self.flush()
+ data = self.__winrand.get_bytes(N)
+ self.flush()
+ return data
+
+def new(*args, **kwargs):
+ return WindowsRNG(*args, **kwargs)
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/Random/OSRNG/posix.py b/lib/Crypto/Random/OSRNG/posix.py
new file mode 100644
index 0000000..08d22c8
--- /dev/null
+++ b/lib/Crypto/Random/OSRNG/posix.py
@@ -0,0 +1,65 @@
+#
+# Random/OSRNG/posix.py : OS entropy source for POSIX systems
+#
+# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# =======================================================================
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =======================================================================
+
+__revision__ = "$Id$"
+__all__ = ['DevURandomRNG']
+
+import os
+import stat
+
+from rng_base import BaseRNG
+
+class DevURandomRNG(BaseRNG):
+
+ def __init__(self, devname=None):
+ if devname is None:
+ self.name = "/dev/urandom"
+ else:
+ self.name = devname
+
+ # Test that /dev/urandom is a character special device
+ f = open(self.name, "rb", 0)
+ fmode = os.fstat(f.fileno())[stat.ST_MODE]
+ if not stat.S_ISCHR(fmode):
+ f.close()
+ raise TypeError("%r is not a character special device" % (self.name,))
+
+ self.__file = f
+ self._read = f.read
+
+ BaseRNG.__init__(self)
+
+ def _close(self):
+ self.__file.close()
+
+ def _read(self, N):
+ return self.__file.read(N)
+
+def new(*args, **kwargs):
+ return DevURandomRNG(*args, **kwargs)
+
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/lib/Crypto/Random/OSRNG/rng_base.py b/lib/Crypto/Random/OSRNG/rng_base.py
new file mode 100644
index 0000000..8e08dc9
--- /dev/null
+++ b/lib/Crypto/Random/OSRNG/rng_base.py
@@ -0,0 +1,89 @@
+#
+# Random/OSRNG/rng_base.py : Base class for OSRNG
+#
+# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net>
+#
+# =======================================================================
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =======================================================================
+
+__revision__ = "$Id$"
+
+from Crypto.Util.python_compat import *
+
+class BaseRNG(object):
+
+ def __init__(self):
+ self.closed = False
+ self._selftest()
+
+ def __del__(self):
+ self.close()
+
+ def _selftest(self):
+ # Test that urandom can return data
+ data = self.read(16)
+ if len(data) != 16:
+ raise AssertionError("read truncated")
+
+ # Test that we get different data every time (if we don't, the RNG is
+ # probably malfunctioning)
+ data2 = self.read(16)
+ if data == data2:
+ raise AssertionError("OS RNG returned duplicate data")
+
+ # PEP 343: Support for the "with" statement
+ def __enter__(self):
+ pass
+ def __exit__(self):
+ """PEP 343 support"""
+ self.close()
+
+ def close(self):
+ if not self.closed:
+ self._close()
+ self.closed = True
+
+ def flush(self):
+ pass
+
+ def read(self, N=-1):
+ """Return N bytes from the RNG."""
+ if self.closed:
+ raise ValueError("I/O operation on closed file")
+ if not isinstance(N, (long, int)):
+ raise TypeError("an integer is required")
+ if N < 0:
+ raise ValueError("cannot read to end of infinite stream")
+ elif N == 0:
+ return ""
+ data = self._read(N)
+ if len(data) != N:
+ raise AssertionError("%s produced truncated output (requested %d, got %d)" % (self.name, N, len(data)))
+ return data
+
+ def _close(self):
+ raise NotImplementedError("child class must implement this")
+
+ def _read(self, N):
+ raise NotImplementedError("child class must implement this")
+
+
+# vim:set ts=4 sw=4 sts=4 expandtab: