[Buildroot] [PATCH v2] package/python-pycrypto: fix python3.8 compatibility

Romain Naour romain.naour at gmail.com
Mon Apr 20 14:07:24 UTC 2020


Apply the patch from Fedora 31 [1][2] to replace the user-space RNG with a
thin wrapper to os.urandom. This allow to fixes compatibility with
Python 3.8 since the code containing time.clock() is removed.

time.clock() was deprecated in Python 3.3 and removed in Python 3.8.

[1] https://src.fedoraproject.org/rpms/python-crypto/c/a5fd7148fb0e9d5526f24feb1bb708bf203480b9?branch=f31
[2] https://src.fedoraproject.org/rpms/python-crypto/blob/f31/f/pycrypto-2.6.1-use-os-random.patch

Fixes:
https://gitlab.com/buildroot.org/buildroot/-/jobs/498144209

Signed-off-by: Romain Naour <romain.naour at gmail.com>
---
This patch would allow to use python2 and python3.
To be backported to Buildroot 2020.02 to fixes the qemu-arm-vexpress-tz defconfig.
---
 ...2-pycrypto-2.6.1-use-os-random.patch.patch | 1904 +++++++++++++++++
 1 file changed, 1904 insertions(+)
 create mode 100644 package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch

diff --git a/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch b/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch
new file mode 100644
index 0000000000..8e78a60d0f
--- /dev/null
+++ b/package/python-pycrypto/0002-pycrypto-2.6.1-use-os-random.patch.patch
@@ -0,0 +1,1904 @@
+From 37c2b6be5e331c215574f4fb34bd96c6e8bba2f6 Mon Sep 17 00:00:00 2001
+From: Romain Naour <romain.naour at gmail.com>
+Date: Mon, 20 Apr 2020 15:35:52 +0200
+Subject: [PATCH] pycrypto-2.6.1-use-os-random.patch
+
+Apply the patch from Fedora 31 [1][2] to replace the user-space RNG with a
+thin wrapper to os.urandom. This allow to fixes compatibility with
+Python 3.8 since the code containing time.clock() is removed.
+
+time.clock() was deprecated in Python 3.3 and removed in Python 3.8.
+
+[1] https://src.fedoraproject.org/rpms/python-crypto/c/a5fd7148fb0e9d5526f24feb1bb708bf203480b9?branch=f31
+[2] https://src.fedoraproject.org/rpms/python-crypto/blob/f31/f/pycrypto-2.6.1-use-os-random.patch
+
+[Romain: git format,  improve commit log]
+Signed-off-by: Romain Naour <romain.naour at gmail.com>
+---
+ lib/Crypto/Random/OSRNG/__init__.py           |  40 --
+ lib/Crypto/Random/OSRNG/fallback.py           |  46 --
+ lib/Crypto/Random/OSRNG/nt.py                 |  74 ---
+ lib/Crypto/Random/OSRNG/posix.py              |  86 ----
+ lib/Crypto/Random/OSRNG/rng_base.py           |  88 ----
+ lib/Crypto/Random/_UserFriendlyRNG.py         | 230 ---------
+ lib/Crypto/Random/__init__.py                 |  40 +-
+ lib/Crypto/SelfTest/Random/OSRNG/__init__.py  |  49 --
+ .../SelfTest/Random/OSRNG/test_fallback.py    |  48 --
+ .../SelfTest/Random/OSRNG/test_generic.py     |  48 --
+ lib/Crypto/SelfTest/Random/OSRNG/test_nt.py   |  48 --
+ .../SelfTest/Random/OSRNG/test_posix.py       |  48 --
+ .../SelfTest/Random/OSRNG/test_winrandom.py   |  48 --
+ lib/Crypto/SelfTest/Random/__init__.py        |   2 -
+ .../SelfTest/Random/test__UserFriendlyRNG.py  | 171 -------
+ lib/Crypto/SelfTest/Util/__init__.py          |   2 -
+ lib/Crypto/SelfTest/Util/test_winrandom.py    |  48 --
+ lib/Crypto/Util/winrandom.py                  |  28 --
+ setup.py                                      |  38 +-
+ src/winrand.c                                 | 472 ------------------
+ 20 files changed, 28 insertions(+), 1626 deletions(-)
+ delete mode 100644 lib/Crypto/Random/OSRNG/__init__.py
+ delete mode 100644 lib/Crypto/Random/OSRNG/fallback.py
+ delete mode 100644 lib/Crypto/Random/OSRNG/nt.py
+ delete mode 100644 lib/Crypto/Random/OSRNG/posix.py
+ delete mode 100644 lib/Crypto/Random/OSRNG/rng_base.py
+ delete mode 100644 lib/Crypto/Random/_UserFriendlyRNG.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/__init__.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
+ delete mode 100644 lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
+ delete mode 100644 lib/Crypto/SelfTest/Util/test_winrandom.py
+ delete mode 100644 lib/Crypto/Util/winrandom.py
+ delete mode 100644 src/winrand.c
+
+diff --git a/lib/Crypto/Random/OSRNG/__init__.py b/lib/Crypto/Random/OSRNG/__init__.py
+deleted file mode 100644
+index 2fbbecb..0000000
+--- a/lib/Crypto/Random/OSRNG/__init__.py
++++ /dev/null
+@@ -1,40 +0,0 @@
+-#
+-#  Random/OSRNG/__init__.py : Platform-independent OS RNG API
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""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
+deleted file mode 100644
+index 5bb6126..0000000
+--- a/lib/Crypto/Random/OSRNG/fallback.py
++++ /dev/null
+@@ -1,46 +0,0 @@
+-#
+-#  Random/OSRNG/fallback.py : Fallback entropy source for systems with os.urandom
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-
+-__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
+deleted file mode 100644
+index c1c2f44..0000000
+--- a/lib/Crypto/Random/OSRNG/nt.py
++++ /dev/null
+@@ -1,74 +0,0 @@
+-#
+-#  Random/OSRNG/nt.py : OS entropy source for MS Windows
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-
+-__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
+deleted file mode 100644
+index ca6ac05..0000000
+--- a/lib/Crypto/Random/OSRNG/posix.py
++++ /dev/null
+@@ -1,86 +0,0 @@
+-#
+-#  Random/OSRNG/posix.py : OS entropy source for POSIX systems
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-
+-__revision__ = "$Id$"
+-__all__ = ['DevURandomRNG']
+-
+-import errno
+-import os
+-import stat
+-
+-from rng_base import BaseRNG
+-from Crypto.Util.py3compat import b
+-
+-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
+-
+-        BaseRNG.__init__(self)
+-
+-    def _close(self):
+-        self.__file.close()
+-
+-    def _read(self, N):
+-        # Starting with Python 3 open with buffering=0 returns a FileIO object.
+-        # FileIO.read behaves like read(2) and not like fread(3) and thus we
+-        # have to handle the case that read returns less data as requested here
+-        # more carefully.
+-        data = b("")
+-        while len(data) < N:
+-            try:
+-                d = self.__file.read(N - len(data))
+-            except IOError, e:
+-                # read(2) has been interrupted by a signal; redo the read
+-                if e.errno == errno.EINTR:
+-                    continue
+-                raise
+-
+-            if d is None:
+-                # __file is in non-blocking mode and no data is available
+-                return data
+-            if len(d) == 0:
+-                # __file is in blocking mode and arrived at EOF
+-                return data
+-
+-            data += d
+-        return data
+-
+-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
+deleted file mode 100644
+index 54c3aa0..0000000
+--- a/lib/Crypto/Random/OSRNG/rng_base.py
++++ /dev/null
+@@ -1,88 +0,0 @@
+-#
+-#  Random/OSRNG/rng_base.py : Base class for OSRNG
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-__revision__ = "$Id$"
+-
+-import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat 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:
+diff --git a/lib/Crypto/Random/_UserFriendlyRNG.py b/lib/Crypto/Random/_UserFriendlyRNG.py
+deleted file mode 100644
+index 957e006..0000000
+--- a/lib/Crypto/Random/_UserFriendlyRNG.py
++++ /dev/null
+@@ -1,230 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  Random/_UserFriendlyRNG.py : A user-friendly random number generator
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-__revision__ = "$Id$"
+-
+-import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+-
+-import os
+-import threading
+-import struct
+-import time
+-from math import floor
+-
+-from Crypto.Random import OSRNG
+-from Crypto.Random.Fortuna import FortunaAccumulator
+-
+-class _EntropySource(object):
+-    def __init__(self, accumulator, src_num):
+-        self._fortuna = accumulator
+-        self._src_num = src_num
+-        self._pool_num = 0
+-
+-    def feed(self, data):
+-        self._fortuna.add_random_event(self._src_num, self._pool_num, data)
+-        self._pool_num = (self._pool_num + 1) & 31
+-
+-class _EntropyCollector(object):
+-
+-    def __init__(self, accumulator):
+-        self._osrng = OSRNG.new()
+-        self._osrng_es = _EntropySource(accumulator, 255)
+-        self._time_es = _EntropySource(accumulator, 254)
+-        self._clock_es = _EntropySource(accumulator, 253)
+-
+-    def reinit(self):
+-        # Add 256 bits to each of the 32 pools, twice.  (For a total of 16384
+-        # bits collected from the operating system.)
+-        for i in range(2):
+-            block = self._osrng.read(32*32)
+-            for p in range(32):
+-                self._osrng_es.feed(block[p*32:(p+1)*32])
+-            block = None
+-        self._osrng.flush()
+-
+-    def collect(self):
+-        # Collect 64 bits of entropy from the operating system and feed it to Fortuna.
+-        self._osrng_es.feed(self._osrng.read(8))
+-
+-        # Add the fractional part of time.time()
+-        t = time.time()
+-        self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
+-
+-        # Add the fractional part of time.clock()
+-        t = time.clock()
+-        self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
+-
+-
+-class _UserFriendlyRNG(object):
+-
+-    def __init__(self):
+-        self.closed = False
+-        self._fa = FortunaAccumulator.FortunaAccumulator()
+-        self._ec = _EntropyCollector(self._fa)
+-        self.reinit()
+-
+-    def reinit(self):
+-        """Initialize the random number generator and seed it with entropy from
+-        the operating system.
+-        """
+-
+-        # Save the pid (helps ensure that Crypto.Random.atfork() gets called)
+-        self._pid = os.getpid()
+-
+-        # Collect entropy from the operating system and feed it to
+-        # FortunaAccumulator
+-        self._ec.reinit()
+-
+-        # Override FortunaAccumulator's 100ms minimum re-seed interval.  This
+-        # is necessary to avoid a race condition between this function and
+-        # self.read(), which that can otherwise cause forked child processes to
+-        # produce identical output.  (e.g. CVE-2013-1445)
+-        #
+-        # Note that if this function can be called frequently by an attacker,
+-        # (and if the bits from OSRNG are insufficiently random) it will weaken
+-        # Fortuna's ability to resist a state compromise extension attack.
+-        self._fa._forget_last_reseed()
+-
+-    def close(self):
+-        self.closed = True
+-        self._osrng = None
+-        self._fa = None
+-
+-    def flush(self):
+-        pass
+-
+-    def read(self, N):
+-        """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")
+-
+-        # Collect some entropy and feed it to Fortuna
+-        self._ec.collect()
+-
+-        # Ask Fortuna to generate some bytes
+-        retval = self._fa.random_data(N)
+-
+-        # Check that we haven't forked in the meantime.  (If we have, we don't
+-        # want to use the data, because it might have been duplicated in the
+-        # parent process.
+-        self._check_pid()
+-
+-        # Return the random data.
+-        return retval
+-
+-    def _check_pid(self):
+-        # Lame fork detection to remind developers to invoke Random.atfork()
+-        # after every call to os.fork().  Note that this check is not reliable,
+-        # since process IDs can be reused on most operating systems.
+-        #
+-        # You need to do Random.atfork() in the child process after every call
+-        # to os.fork() to avoid reusing PRNG state.  If you want to avoid
+-        # leaking PRNG state to child processes (for example, if you are using
+-        # os.setuid()) then you should also invoke Random.atfork() in the
+-        # *parent* process.
+-        if os.getpid() != self._pid:
+-            raise AssertionError("PID check failed. RNG must be re-initialized after fork(). Hint: Try Random.atfork()")
+-
+-
+-class _LockingUserFriendlyRNG(_UserFriendlyRNG):
+-    def __init__(self):
+-        self._lock = threading.Lock()
+-        _UserFriendlyRNG.__init__(self)
+-
+-    def close(self):
+-        self._lock.acquire()
+-        try:
+-            return _UserFriendlyRNG.close(self)
+-        finally:
+-            self._lock.release()
+-
+-    def reinit(self):
+-        self._lock.acquire()
+-        try:
+-            return _UserFriendlyRNG.reinit(self)
+-        finally:
+-            self._lock.release()
+-
+-    def read(self, bytes):
+-        self._lock.acquire()
+-        try:
+-            return _UserFriendlyRNG.read(self, bytes)
+-        finally:
+-            self._lock.release()
+-
+-class RNGFile(object):
+-    def __init__(self, singleton):
+-        self.closed = False
+-        self._singleton = singleton
+-
+-    # PEP 343: Support for the "with" statement
+-    def __enter__(self):
+-        """PEP 343 support"""
+-    def __exit__(self):
+-        """PEP 343 support"""
+-        self.close()
+-
+-    def close(self):
+-        # Don't actually close the singleton, just close this RNGFile instance.
+-        self.closed = True
+-        self._singleton = None
+-
+-    def read(self, bytes):
+-        if self.closed:
+-            raise ValueError("I/O operation on closed file")
+-        return self._singleton.read(bytes)
+-
+-    def flush(self):
+-        if self.closed:
+-            raise ValueError("I/O operation on closed file")
+-
+-_singleton_lock = threading.Lock()
+-_singleton = None
+-def _get_singleton():
+-    global _singleton
+-    _singleton_lock.acquire()
+-    try:
+-        if _singleton is None:
+-            _singleton = _LockingUserFriendlyRNG()
+-        return _singleton
+-    finally:
+-        _singleton_lock.release()
+-
+-def new():
+-    return RNGFile(_get_singleton())
+-
+-def reinit():
+-    _get_singleton().reinit()
+-
+-def get_random_bytes(n):
+-    """Return the specified number of cryptographically-strong random bytes."""
+-    return _get_singleton().read(n)
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/Random/__init__.py b/lib/Crypto/Random/__init__.py
+index 659ffee..a2e241d 100644
+--- a/lib/Crypto/Random/__init__.py
++++ b/lib/Crypto/Random/__init__.py
+@@ -2,8 +2,6 @@
+ #
+ #  Random/__init__.py : PyCrypto random number generation
+ #
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+ # ===================================================================
+ # The contents of this file are dedicated to the public domain.  To
+ # the extent that dedication to the public domain is not available,
+@@ -22,22 +20,38 @@
+ # SOFTWARE.
+ # ===================================================================
+ 
+-__revision__ = "$Id$"
+-__all__ = ['new']
++__all__ = ['new', 'get_random_bytes']
++
++from os import urandom
++
++class _UrandomRNG(object):
++
++    def read(self, n):
++        """Return a random byte string of the desired size."""
++        return urandom(n)
++
++    def flush(self):
++        """Method provided for backward compatibility only."""
++        pass
++
++    def reinit(self):
++        """Method provided for backward compatibility only."""
++        pass
++
++    def close(self):
++        """Method provided for backward compatibility only."""
++        pass
+ 
+-from Crypto.Random import OSRNG
+-from Crypto.Random import _UserFriendlyRNG
+ 
+ def new(*args, **kwargs):
+     """Return a file-like object that outputs cryptographically random bytes."""
+-    return _UserFriendlyRNG.new(*args, **kwargs)
++    return _UrandomRNG()
++
+ 
+ def atfork():
+-    """Call this whenever you call os.fork()"""
+-    _UserFriendlyRNG.reinit()
++        pass
++
+ 
+-def get_random_bytes(n):
+-    """Return the specified number of cryptographically-strong random bytes."""
+-    return _UserFriendlyRNG.get_random_bytes(n)
++#: Function that returns a random byte string of the desired size.
++get_random_bytes = urandom
+ 
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/__init__.py b/lib/Crypto/SelfTest/Random/OSRNG/__init__.py
+deleted file mode 100644
+index 44b3fa1..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/__init__.py
++++ /dev/null
+@@ -1,49 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Random/OSRNG/__init__.py: Self-test for OSRNG modules
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test for Crypto.Random.OSRNG package"""
+-
+-__revision__ = "$Id$"
+-
+-import os
+-
+-def get_tests(config={}):
+-    tests = []
+-    if os.name == 'nt':
+-        from Crypto.SelfTest.Random.OSRNG import test_nt;        tests += test_nt.get_tests(config=config)
+-        from Crypto.SelfTest.Random.OSRNG import test_winrandom; tests += test_winrandom.get_tests(config=config)
+-    elif os.name == 'posix':
+-        from Crypto.SelfTest.Random.OSRNG import test_posix;     tests += test_posix.get_tests(config=config)
+-    if hasattr(os, 'urandom'):
+-        from Crypto.SelfTest.Random.OSRNG import test_fallback;      tests += test_fallback.get_tests(config=config)
+-    from Crypto.SelfTest.Random.OSRNG import test_generic;       tests += test_generic.get_tests(config=config)
+-    return tests
+-
+-if __name__ == '__main__':
+-    import unittest
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py b/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
+deleted file mode 100644
+index 41909b0..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/test_fallback.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_fallback.py: Self-test for the OSRNG.fallback.new() function
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Random.OSRNG.fallback"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class SimpleTest(unittest.TestCase):
+-    def runTest(self):
+-        """Crypto.Random.OSRNG.fallback.new()"""
+-        # Import the OSRNG.nt module and try to use it
+-        import Crypto.Random.OSRNG.fallback
+-        randobj = Crypto.Random.OSRNG.fallback.new()
+-        x = randobj.read(16)
+-        y = randobj.read(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [SimpleTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py b/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
+deleted file mode 100644
+index 2a40974..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/test_generic.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_generic.py: Self-test for the OSRNG.new() function
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Random.OSRNG"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class SimpleTest(unittest.TestCase):
+-    def runTest(self):
+-        """Crypto.Random.OSRNG.new()"""
+-        # Import the OSRNG module and try to use it
+-        import Crypto.Random.OSRNG
+-        randobj = Crypto.Random.OSRNG.new()
+-        x = randobj.read(16)
+-        y = randobj.read(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [SimpleTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py b/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
+deleted file mode 100644
+index a7a8338..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/test_nt.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_generic.py: Self-test for the OSRNG.nt.new() function
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Random.OSRNG.nt"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class SimpleTest(unittest.TestCase):
+-    def runTest(self):
+-        """Crypto.Random.OSRNG.nt.new()"""
+-        # Import the OSRNG.nt module and try to use it
+-        import Crypto.Random.OSRNG.nt
+-        randobj = Crypto.Random.OSRNG.nt.new()
+-        x = randobj.read(16)
+-        y = randobj.read(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [SimpleTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py b/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
+deleted file mode 100644
+index 2224afe..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/test_posix.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_posix.py: Self-test for the OSRNG.posix.new() function
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Random.OSRNG.posix"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class SimpleTest(unittest.TestCase):
+-    def runTest(self):
+-        """Crypto.Random.OSRNG.posix.new()"""
+-        # Import the OSRNG.nt module and try to use it
+-        import Crypto.Random.OSRNG.posix
+-        randobj = Crypto.Random.OSRNG.posix.new()
+-        x = randobj.read(16)
+-        y = randobj.read(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [SimpleTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py b/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
+deleted file mode 100644
+index 3010eb7..0000000
+--- a/lib/Crypto/SelfTest/Random/OSRNG/test_winrandom.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Random.OSRNG.winrandom"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class SimpleTest(unittest.TestCase):
+-    def runTest(self):
+-        """Crypto.Random.OSRNG.winrandom"""
+-        # Import the winrandom module and try to use it
+-        from Crypto.Random.OSRNG import winrandom
+-        randobj = winrandom.new()
+-        x = randobj.get_bytes(16)
+-        y = randobj.get_bytes(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [SimpleTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Random/__init__.py b/lib/Crypto/SelfTest/Random/__init__.py
+index f972bf0..aa8e7de 100644
+--- a/lib/Crypto/SelfTest/Random/__init__.py
++++ b/lib/Crypto/SelfTest/Random/__init__.py
+@@ -29,10 +29,8 @@ __revision__ = "$Id$"
+ def get_tests(config={}):
+     tests = []
+     from Crypto.SelfTest.Random import Fortuna;             tests += Fortuna.get_tests(config=config)
+-    from Crypto.SelfTest.Random import OSRNG;               tests += OSRNG.get_tests(config=config)
+     from Crypto.SelfTest.Random import test_random;         tests += test_random.get_tests(config=config)
+     from Crypto.SelfTest.Random import test_rpoolcompat;    tests += test_rpoolcompat.get_tests(config=config)
+-    from Crypto.SelfTest.Random import test__UserFriendlyRNG; tests += test__UserFriendlyRNG.get_tests(config=config)
+     return tests
+ 
+ if __name__ == '__main__':
+diff --git a/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py b/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
+deleted file mode 100644
+index 771a663..0000000
+--- a/lib/Crypto/SelfTest/Random/test__UserFriendlyRNG.py
++++ /dev/null
+@@ -1,171 +0,0 @@
+-# -*- coding: utf-8 -*-
+-# Self-tests for the user-friendly Crypto.Random interface
+-#
+-# Written in 2013 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for generic Crypto.Random stuff """
+-
+-from __future__ import nested_scopes
+-
+-__revision__ = "$Id$"
+-
+-import binascii
+-import pprint
+-import unittest
+-import os
+-import time
+-import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+-from Crypto.Util.py3compat import *
+-
+-try:
+-    import multiprocessing
+-except ImportError:
+-    multiprocessing = None
+-
+-import Crypto.Random._UserFriendlyRNG
+-import Crypto.Random.random
+-
+-class RNGForkTest(unittest.TestCase):
+-
+-    def _get_reseed_count(self):
+-        """
+-        Get `FortunaAccumulator.reseed_count`, the global count of the
+-        number of times that the PRNG has been reseeded.
+-        """
+-        rng_singleton = Crypto.Random._UserFriendlyRNG._get_singleton()
+-        rng_singleton._lock.acquire()
+-        try:
+-            return rng_singleton._fa.reseed_count
+-        finally:
+-            rng_singleton._lock.release()
+-
+-    def runTest(self):
+-        # Regression test for CVE-2013-1445.  We had a bug where, under the
+-        # right conditions, two processes might see the same random sequence.
+-
+-        if sys.platform.startswith('win'):  # windows can't fork
+-            assert not hasattr(os, 'fork')    # ... right?
+-            return
+-
+-        # Wait 150 ms so that we don't trigger the rate-limit prematurely.
+-        time.sleep(0.15)
+-
+-        reseed_count_before = self._get_reseed_count()
+-
+-        # One or both of these calls together should trigger a reseed right here.
+-        Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
+-        Crypto.Random.get_random_bytes(1)
+-
+-        reseed_count_after = self._get_reseed_count()
+-        self.assertNotEqual(reseed_count_before, reseed_count_after)  # sanity check: test should reseed parent before forking
+-
+-        rfiles = []
+-        for i in range(10):
+-            rfd, wfd = os.pipe()
+-            if os.fork() == 0:
+-                # child
+-                os.close(rfd)
+-                f = os.fdopen(wfd, "wb")
+-
+-                Crypto.Random.atfork()
+-
+-                data = Crypto.Random.get_random_bytes(16)
+-
+-                f.write(data)
+-                f.close()
+-                os._exit(0)
+-            # parent
+-            os.close(wfd)
+-            rfiles.append(os.fdopen(rfd, "rb"))
+-
+-        results = []
+-        results_dict = {}
+-        for f in rfiles:
+-            data = binascii.hexlify(f.read())
+-            results.append(data)
+-            results_dict[data] = 1
+-            f.close()
+-
+-        if len(results) != len(results_dict.keys()):
+-            raise AssertionError("RNG output duplicated across fork():\n%s" %
+-                                 (pprint.pformat(results)))
+-
+-
+-# For RNGMultiprocessingForkTest
+-def _task_main(q):
+-    a = Crypto.Random.get_random_bytes(16)
+-    time.sleep(0.1)     # wait 100 ms
+-    b = Crypto.Random.get_random_bytes(16)
+-    q.put(binascii.b2a_hex(a))
+-    q.put(binascii.b2a_hex(b))
+-    q.put(None)      # Wait for acknowledgment
+-
+-
+-class RNGMultiprocessingForkTest(unittest.TestCase):
+-
+-    def runTest(self):
+-        # Another regression test for CVE-2013-1445.  This is basically the
+-        # same as RNGForkTest, but less compatible with old versions of Python,
+-        # and a little easier to read.
+-
+-        n_procs = 5
+-        manager = multiprocessing.Manager()
+-        queues = [manager.Queue(1) for i in range(n_procs)]
+-
+-        # Reseed the pool
+-        time.sleep(0.15)
+-        Crypto.Random._UserFriendlyRNG._get_singleton().reinit()
+-        Crypto.Random.get_random_bytes(1)
+-
+-        # Start the child processes
+-        pool = multiprocessing.Pool(processes=n_procs, initializer=Crypto.Random.atfork)
+-        map_result = pool.map_async(_task_main, queues)
+-
+-        # Get the results, ensuring that no pool processes are reused.
+-        aa = [queues[i].get(30) for i in range(n_procs)]
+-        bb = [queues[i].get(30) for i in range(n_procs)]
+-        res = list(zip(aa, bb))
+-
+-        # Shut down the pool
+-        map_result.get(30)
+-        pool.close()
+-        pool.join()
+-
+-        # Check that the results are unique
+-        if len(set(aa)) != len(aa) or len(set(res)) != len(res):
+-            raise AssertionError("RNG output duplicated across fork():\n%s" %
+-                                 (pprint.pformat(res),))
+-
+-
+-def get_tests(config={}):
+-    tests = []
+-    tests += [RNGForkTest()]
+-    if multiprocessing is not None:
+-        tests += [RNGMultiprocessingForkTest()]
+-    return tests
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/SelfTest/Util/__init__.py b/lib/Crypto/SelfTest/Util/__init__.py
+index abd640a..e9af4b5 100644
+--- a/lib/Crypto/SelfTest/Util/__init__.py
++++ b/lib/Crypto/SelfTest/Util/__init__.py
+@@ -30,8 +30,6 @@ import os
+ 
+ def get_tests(config={}):
+     tests = []
+-    if os.name == 'nt':
+-        from Crypto.SelfTest.Util import test_winrandom; tests += test_winrandom.get_tests(config=config)
+     from Crypto.SelfTest.Util import test_number; tests += test_number.get_tests(config=config)
+     from Crypto.SelfTest.Util import test_Counter; tests += test_Counter.get_tests(config=config)
+     return tests
+diff --git a/lib/Crypto/SelfTest/Util/test_winrandom.py b/lib/Crypto/SelfTest/Util/test_winrandom.py
+deleted file mode 100644
+index 3fc5145..0000000
+--- a/lib/Crypto/SelfTest/Util/test_winrandom.py
++++ /dev/null
+@@ -1,48 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  SelfTest/Util/test_winrandom.py: Self-test for the winrandom module
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-"""Self-test suite for Crypto.Util.winrandom"""
+-
+-__revision__ = "$Id$"
+-
+-import unittest
+-
+-class WinRandomImportTest(unittest.TestCase):
+-    def runTest(self):
+-        """winrandom: simple test"""
+-        # Import the winrandom module and try to use it
+-        from Crypto.Util import winrandom
+-        randobj = winrandom.new()
+-        x = randobj.get_bytes(16)
+-        y = randobj.get_bytes(16)
+-        self.assertNotEqual(x, y)
+-
+-def get_tests(config={}):
+-    return [WinRandomImportTest()]
+-
+-if __name__ == '__main__':
+-    suite = lambda: unittest.TestSuite(get_tests())
+-    unittest.main(defaultTest='suite')
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/lib/Crypto/Util/winrandom.py b/lib/Crypto/Util/winrandom.py
+deleted file mode 100644
+index 0242815..0000000
+--- a/lib/Crypto/Util/winrandom.py
++++ /dev/null
+@@ -1,28 +0,0 @@
+-#
+-#  Util/winrandom.py : Stub for Crypto.Random.OSRNG.winrandom
+-#
+-# Written in 2008 by Dwayne C. Litzenberger <dlitz at dlitz.net>
+-#
+-# ===================================================================
+-# The contents of this file are dedicated to the public domain.  To
+-# the extent that dedication to the public domain is not available,
+-# everyone is granted a worldwide, perpetual, royalty-free,
+-# non-exclusive license to exercise all rights associated with the
+-# contents of this file for any purpose whatsoever.
+-# No rights are reserved.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+-# SOFTWARE.
+-# ===================================================================
+-
+-__revision__ = "$Id$"
+-
+-from Crypto.Random.OSRNG.winrandom import *
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
+diff --git a/setup.py b/setup.py
+index c546ddb..d3a3b8b 100644
+--- a/setup.py
++++ b/setup.py
+@@ -48,18 +48,6 @@ if sys.version[0:1] == '1':
+     raise RuntimeError ("The Python Cryptography Toolkit requires "
+                          "Python 2.x or 3.x to build.")
+ 
+-if sys.platform == 'win32':
+-    HTONS_LIBS = ['ws2_32']
+-    plat_ext = [
+-                Extension("Crypto.Random.OSRNG.winrandom",
+-                          libraries = HTONS_LIBS + ['advapi32'],
+-                          include_dirs=['src/'],
+-                          sources=["src/winrand.c"])
+-               ]
+-else:
+-    HTONS_LIBS = []
+-    plat_ext = []
+-
+ # For test development: Set this to 1 to build with gcov support.
+ # Use "gcov -p -o build/temp.*/src build/temp.*/src/*.gcda" to build the
+ # .gcov files
+@@ -73,18 +61,6 @@ except ImportError:
+     # Python 2
+     from distutils.command.build_py import build_py
+ 
+-# List of pure Python modules that will be excluded from the binary packages.
+-# The list consists of (package, module_name) tuples
+-if sys.version_info[0] == 2:
+-    EXCLUDE_PY = []
+-else:
+-    EXCLUDE_PY = [
+-        # We don't want Py3k to choke on the 2.x compat code
+-        ('Crypto.Util', 'py21compat'), 
+-    ]
+-    if sys.platform != "win32": # Avoid nt.py, as 2to3 can't fix it w/o winrandom
+-        EXCLUDE_PY += [('Crypto.Random.OSRNG','nt')]
+-
+ # Work around the print / print() issue with Python 2.x and 3.x. We only need
+ # to print at one point of the code, which makes this easy
+ 
+@@ -264,8 +240,6 @@ class PCTBuildPy(build_py):
+         retval = []
+         for item in modules:
+             pkg, module = item[:2]
+-            if (pkg, module) in EXCLUDE_PY:
+-                continue
+             retval.append(item)
+         return retval
+ 
+@@ -330,7 +304,6 @@ kw = {'name':"pycrypto",
+       'packages' : ["Crypto", "Crypto.Hash", "Crypto.Cipher", "Crypto.Util",
+                   "Crypto.Random",
+                   "Crypto.Random.Fortuna",
+-                  "Crypto.Random.OSRNG",
+                   "Crypto.SelfTest",
+                   "Crypto.SelfTest.Cipher",
+                   "Crypto.SelfTest.Hash",
+@@ -338,14 +311,13 @@ kw = {'name':"pycrypto",
+                   "Crypto.SelfTest.PublicKey",
+                   "Crypto.SelfTest.Random",
+                   "Crypto.SelfTest.Random.Fortuna",
+-                  "Crypto.SelfTest.Random.OSRNG",
+                   "Crypto.SelfTest.Util",
+                   "Crypto.SelfTest.Signature",
+                   "Crypto.Protocol",
+                   "Crypto.PublicKey",
+                   "Crypto.Signature"],
+       'package_dir' : { "Crypto": "lib/Crypto" },
+-      'ext_modules': plat_ext + [
++      'ext_modules': [
+             # _fastmath (uses GNU mp library)
+             Extension("Crypto.PublicKey._fastmath",
+                       include_dirs=['src/','/usr/include/'],
+@@ -443,11 +415,3 @@ def touch(path):
+         os.utime(path, (now, now))
+     except os.error:
+         PrintErr("Failed to update timestamp of "+path)
+-
+-# PY3K: Workaround for winrandom.pyd not existing during the first pass.
+-# It needs to be there for 2to3 to fix the import in nt.py
+-if (sys.platform == 'win32' and sys.version_info[0] == 3 and
+-    'build' in sys.argv[1:]):
+-    PrintErr("\nSecond pass to allow 2to3 to fix nt.py. No cause for alarm.\n")
+-    touch("./lib/Crypto/Random/OSRNG/nt.py")
+-    core.setup(**kw)
+diff --git a/src/winrand.c b/src/winrand.c
+deleted file mode 100644
+index d505e54..0000000
+--- a/src/winrand.c
++++ /dev/null
+@@ -1,472 +0,0 @@
+-/* -*- C -*- */
+-/*
+- * Uses Windows CryptoAPI CryptGenRandom to get random bytes.
+- * The "new" method returns an object, whose "get_bytes" method
+- * can be called repeatedly to get random bytes, seeded by the
+- * OS.  See the description in the comment at the end.
+- * 
+- * If you have the Intel Security Driver header files (icsp4ms.h)
+- * for their hardware random number generator in the 810 and 820 chipsets,
+- * then define HAVE_INTEL_RNG.
+- *
+- * =======================================================================
+- * The contents of this file are dedicated to the public domain.  To the
+- * extent that dedication to the public domain is not available, everyone
+- * is granted a worldwide, perpetual, royalty-free, non-exclusive license
+- * to exercise all rights associated with the contents of this file for
+- * any purpose whatsoever.  No rights are reserved.
+- *
+- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+- * SOFTWARE.
+- * =======================================================================
+- *
+- */
+-
+-/* Author: Mark Moraes */
+-
+-#include "Python.h"
+-#include "pycrypto_compat.h"
+-
+-#ifdef MS_WIN32
+-
+-#define _WIN32_WINNT 0x400
+-#define WINSOCK
+-
+-#include <windows.h>
+-#include <wincrypt.h>
+-
+-#ifdef HAVE_INTEL_RNG
+-# include "icsp4ms.h"
+-#else
+-# define PROV_INTEL_SEC 22
+-# define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
+-#endif
+-
+-/* To-Do: store provider name and type for print/repr? */
+-
+-typedef struct
+-{
+-    PyObject_HEAD
+-    HCRYPTPROV hcp;
+-} WRobject;
+-
+-/* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C.
+- * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize
+- */
+-#ifdef IS_PY3K
+-static PyTypeObject WRtype;
+-#define is_WRobject(v) (Py_TYPE(v) == &WRtype)
+-#else
+-staticforward PyTypeObject WRtype;
+-#define is_WRobject(v) ((v)->ob_type == &WRtype)
+-#define PyLong_FromLong PyInt_FromLong /* for Python 2.x */
+-#endif
+-
+-static void
+-WRdealloc(PyObject *ptr)
+-{		
+-	WRobject *o = (WRobject *)ptr;
+-
+-	if (! is_WRobject(ptr)) {
+-		PyErr_Format(PyExc_TypeError,
+-		    "WinRandom trying to dealloc non-WinRandom object");
+-		return;
+-	}
+-	if (! CryptReleaseContext(o->hcp, 0)) {
+-		PyErr_Format(PyExc_SystemError,
+-			     "CryptReleaseContext failed, error 0x%x",
+-			     (unsigned int) GetLastError());
+-		return;
+-	}
+-	/* Overwrite the contents of the object */
+-	o->hcp = 0;
+-	PyObject_Del(ptr);
+-}
+-
+-static char winrandom__doc__[] =
+-"new([provider], [provtype]): Returns an object handle to Windows\n\
+-CryptoAPI that can be used to access a cryptographically strong\n\
+-pseudo-random generator that uses OS-gathered entropy.\n\
+-Provider is a string that specifies the Cryptographic Service Provider\n\
+-to use, default is the default OS CSP.\n\
+-provtype is an integer specifying the provider type to use, default\n\
+-is 1 (PROV_RSA_FULL)";
+-
+-static char WR_get_bytes__doc__[] =
+-"get_bytes(nbytes, [userdata]]): Returns nbytes of random data\n\
+-from Windows CryptGenRandom.\n\
+-userdata is a string with any additional entropic data that the\n\
+-user wishes to provide.";
+-
+-static WRobject *
+-winrandom_new(PyObject *self, PyObject *args, PyObject *kwdict)
+-{
+-	HCRYPTPROV hcp = 0;
+-	WRobject *res;
+-	char *provname = NULL;
+-	int provtype = PROV_RSA_FULL;
+-	static char *kwlist[] = { "provider", "provtype", NULL};
+-	
+-	if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|si", kwlist,
+-					 &provname, &provtype)) {
+-		return NULL;
+-	}
+-	if (! CryptAcquireContext(&hcp, NULL, (LPCTSTR) provname,
+-				  (DWORD) provtype,
+-				  CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+-		PyErr_Format(PyExc_SystemError,
+-			     "CryptAcquireContext for provider \"%s\" type %i failed, error 0x%x",
+-			     provname? provname : "(null)", provtype,
+-			     (unsigned int) GetLastError());
+-		return NULL;
+-	}
+-	res = PyObject_New(WRobject, &WRtype);
+-	res->hcp = hcp;
+-	return res;
+-}
+-
+-static PyObject *
+-WR_get_bytes(WRobject *self, PyObject *args)
+-{
+-	int n, nbytes, len = 0;
+-	PyObject *res;
+-	char *buf, *str = NULL;
+-	
+-	if (! is_WRobject(self)) {
+-		PyErr_Format(PyExc_TypeError,
+-		    "WinRandom trying to get_bytes with non-WinRandom object");
+-		return NULL;
+-	}
+-	if (!PyArg_ParseTuple(args, "i|s#", &n, &str, &len)) {
+-		return NULL;
+-	}
+-	if (n <= 0) {
+-		PyErr_SetString(PyExc_ValueError, "nbytes must be positive number");
+-		return NULL;
+-	}
+-	/* Just in case char != BYTE, or userdata > desired result */
+-	nbytes = (((n > len) ? n : len) * sizeof(char)) / sizeof(BYTE) + 1;
+-	if ((buf = (char *) PyMem_Malloc(nbytes)) == NULL)
+-	    return PyErr_NoMemory();
+-	if (len > 0)
+-		memcpy(buf, str, len);
+-	/*
+-	 * if userdata > desired result, we end up getting
+-	 * more bytes than we really needed to return.  No
+-	 * easy way to avoid that: we prefer that
+-	 * CryptGenRandom does the distillation of userdata
+-	 * down to entropy, rather than trying to do it
+-	 * ourselves.  Since the extra bytes presumably come
+-	 * from an RC4 stream, they should be relatively
+-	 * cheap.
+-	 */
+-
+-	if (! CryptGenRandom(self->hcp, (DWORD) nbytes, (BYTE *) buf)) {
+-		PyErr_Format(PyExc_SystemError,
+-			     "CryptGenRandom failed, error 0x%x",
+-			     (unsigned int) GetLastError());
+-		PyMem_Free(buf);
+-		return NULL;
+-	}
+-
+-	res = PyBytes_FromStringAndSize(buf, n);
+-	PyMem_Free(buf);
+-	return res;
+-}
+-
+-/* WinRandom object methods */
+-
+-static PyMethodDef WRmethods[] =
+-{
+-	{"get_bytes", (PyCFunction) WR_get_bytes, METH_VARARGS,
+-		WR_get_bytes__doc__},
+-	{NULL, NULL}			/* sentinel */
+-};
+-
+-/* winrandom module methods */
+-
+-static PyMethodDef WR_mod_methods[] = {
+-        {"new", (PyCFunction) winrandom_new, METH_VARARGS|METH_KEYWORDS,
+-		winrandom__doc__},
+-	{NULL,      NULL}        /* Sentinel */
+-};
+-
+-static PyObject *
+-#ifdef IS_PY3K
+-WRgetattro(PyObject *s, PyObject *attr)
+-#else
+-WRgetattr(PyObject *s, char *name)
+-#endif
+-{
+-	WRobject *self = (WRobject*)s;
+-	if (! is_WRobject(self)) {
+-		PyErr_Format(PyExc_TypeError,
+-		    "WinRandom trying to getattr with non-WinRandom object");
+-		return NULL;
+-	}
+-#ifdef IS_PY3K
+-	if (!PyUnicode_Check(attr))
+-		goto generic;
+-	if (PyUnicode_CompareWithASCIIString(attr, "hcp") == 0)
+-#else
+-	if (strcmp(name, "hcp") == 0)
+-#endif
+-		return PyLong_FromLong((long) self->hcp);
+-#ifdef IS_PY3K
+-  generic:
+-	return PyObject_GenericGetAttr(s, attr);
+-#else
+-	return Py_FindMethod(WRmethods, (PyObject *) self, name);
+-#endif
+-}
+-
+-static PyTypeObject WRtype =
+- {
+- #ifdef IS_PY3K
+-	PyVarObject_HEAD_INIT(NULL, 0)  /* deferred type init for compilation on Windows, type will be filled in at runtime */
+-#else
+-	PyObject_HEAD_INIT(NULL)
+-	0,			/*ob_size*/
+-#endif
+- 	"winrandom.WinRandom",	/*tp_name*/
+- 	sizeof(WRobject),	/*tp_size*/
+- 	0,			/*tp_itemsize*/
+- 	/* methods */
+-	(destructor) WRdealloc,		/*tp_dealloc*/
+-	0,				/*tp_print*/
+-#ifndef IS_PY3K
+-	WRgetattr,		/*tp_getattr*/
+-#else
+-	0,				/*tp_getattr*/
+-	0,				/*tp_setattr*/
+-	0,				/*tp_compare*/
+-	0,				/*tp_repr*/
+-	0,				/*tp_as_number */
+-	0,				/*tp_as_sequence */
+-	0,				/*tp_as_mapping */
+-	0,				/*tp_hash*/
+-	0,				/*tp_call*/
+-	0,				/*tp_str*/
+-	WRgetattro,		/*tp_getattro*/
+-	0,				/*tp_setattro*/
+-	0,				/*tp_as_buffer*/
+-	Py_TPFLAGS_DEFAULT,		/*tp_flags*/
+-	0,				/*tp_doc*/
+-	0,				/*tp_traverse*/
+-	0,				/*tp_clear*/
+-	0,				/*tp_richcompare*/
+-	0,				/*tp_weaklistoffset*/
+-	0,				/*tp_iter*/
+-	0,				/*tp_iternext*/
+-	WRmethods,		/*tp_methods*/
+-#endif
+-};
+-
+-#ifdef IS_PY3K
+-static struct PyModuleDef moduledef = {
+-	PyModuleDef_HEAD_INIT,
+-	"winrandom",
+-	NULL,
+-	-1,
+-	WR_mod_methods,
+-	NULL,
+-	NULL,
+-	NULL,
+-	NULL
+- };
+-#endif
+-
+-#ifdef IS_PY3K
+-PyMODINIT_FUNC
+-PyInit_winrandom()
+-#else
+-void
+-initwinrandom()
+-#endif
+-{
+-	PyObject *m;
+-#ifdef IS_PY3K
+-	/* PyType_Ready automatically fills in ob_type with &PyType_Type if it's not already set */
+-	if (PyType_Ready(&WRtype) < 0)
+-		return NULL;
+-    /* Initialize the module */
+-    m = PyModule_Create(&moduledef);
+-    if (m == NULL)
+-        return NULL;
+-#else
+-	WRtype.ob_type = &PyType_Type;
+-	m = Py_InitModule("winrandom", WR_mod_methods);
+-#endif
+-
+-	/* define Windows CSP Provider Types */
+-#ifdef PROV_RSA_FULL
+-	PyModule_AddIntConstant(m, "PROV_RSA_FULL", PROV_RSA_FULL);
+-#endif
+-#ifdef PROV_RSA_SIG
+-	PyModule_AddIntConstant(m, "PROV_RSA_SIG", PROV_RSA_SIG);
+-#endif
+-#ifdef PROV_DSS
+-	PyModule_AddIntConstant(m, "PROV_DSS", PROV_DSS);
+-#endif
+-#ifdef PROV_FORTEZZA
+-	PyModule_AddIntConstant(m, "PROV_FORTEZZA", PROV_FORTEZZA);
+-#endif
+-#ifdef PROV_MS_EXCHANGE
+-	PyModule_AddIntConstant(m, "PROV_MS_EXCHANGE", PROV_MS_EXCHANGE);
+-#endif
+-#ifdef PROV_SSL
+-	PyModule_AddIntConstant(m, "PROV_SSL", PROV_SSL);
+-#endif
+-#ifdef PROV_RSA_SCHANNEL
+-	PyModule_AddIntConstant(m, "PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL);
+-#endif
+-#ifdef PROV_DSS_DH
+-	PyModule_AddIntConstant(m, "PROV_DSS_DH", PROV_DSS_DH);
+-#endif
+-#ifdef PROV_EC_ECDSA_SIG
+-	PyModule_AddIntConstant(m, "PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG);
+-#endif
+-#ifdef PROV_EC_ECNRA_SIG
+-	PyModule_AddIntConstant(m, "PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG);
+-#endif
+-#ifdef PROV_EC_ECDSA_FULL
+-	PyModule_AddIntConstant(m, "PROV_EC_ECDSA_FULL", PROV_EC_ECDSA_FULL);
+-#endif
+-#ifdef PROV_EC_ECNRA_FULL
+-	PyModule_AddIntConstant(m, "PROV_EC_ECNRA_FULL", PROV_EC_ECNRA_FULL);
+-#endif
+-#ifdef PROV_SPYRUS_LYNKS
+-	PyModule_AddIntConstant(m, "PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS);
+-#endif
+-#ifdef PROV_INTEL_SEC
+-	PyModule_AddIntConstant(m, "PROV_INTEL_SEC", PROV_INTEL_SEC);
+-#endif
+-
+-	/* Define Windows CSP Provider Names */
+-#ifdef MS_DEF_PROV
+-	PyModule_AddStringConstant(m, "MS_DEF_PROV", MS_DEF_PROV);
+-#endif
+-#ifdef MS_ENHANCED_PROV
+-	PyModule_AddStringConstant(m, "MS_ENHANCED_PROV", MS_ENHANCED_PROV);
+-#endif
+-#ifdef MS_DEF_RSA_SIG_PROV
+-	PyModule_AddStringConstant(m, "MS_DEF_RSA_SIG_PROV",
+-				   MS_DEF_RSA_SIG_PROV);
+-#endif
+-#ifdef MS_DEF_RSA_SCHANNEL_PROV
+-	PyModule_AddStringConstant(m, "MS_DEF_RSA_SCHANNEL_PROV",
+-				   MS_DEF_RSA_SCHANNEL_PROV);
+-#endif
+-#ifdef MS_ENHANCED_RSA_SCHANNEL_PROV
+-	PyModule_AddStringConstant(m, "MS_ENHANCED_RSA_SCHANNEL_PROV",
+-				   MS_ENHANCED_RSA_SCHANNEL_PROV);
+-#endif
+-#ifdef MS_DEF_DSS_PROV
+-	PyModule_AddStringConstant(m, "MS_DEF_DSS_PROV", MS_DEF_DSS_PROV);
+-#endif
+-#ifdef MS_DEF_DSS_DH_PROV
+-	PyModule_AddStringConstant(m, "MS_DEF_DSS_DH_PROV",
+-				   MS_DEF_DSS_DH_PROV);
+-#endif
+-#ifdef INTEL_DEF_PROV
+-	PyModule_AddStringConstant(m, "INTEL_DEF_PROV", INTEL_DEF_PROV);
+-#endif
+-
+-	if (PyErr_Occurred())
+-		Py_FatalError("can't initialize module winrandom");
+-
+-#ifdef IS_PY3K
+-	return m;
+-#endif
+-}
+-/*
+-
+-CryptGenRandom usage is described in
+-http://msdn.microsoft.com/library/en-us/security/security/cryptgenrandom.asp
+-and many associated pages on Windows Cryptographic Service
+-Providers, which say:
+-
+-	With Microsoft CSPs, CryptGenRandom uses the same
+-	random number generator used by other security
+-	components. This allows numerous processes to
+-	contribute to a system-wide seed. CryptoAPI stores
+-	an intermediate random seed with every user. To form
+-	the seed for the random number generator, a calling
+-	application supplies bits it might havefor instance,
+-	mouse or keyboard timing inputthat are then added to
+-	both the stored seed and various system data and
+-	user data such as the process ID and thread ID, the
+-	system clock, the system time, the system counter,
+-	memory status, free disk clusters, the hashed user
+-	environment block. This result is SHA-1 hashed, and
+-	the output is used to seed an RC4 stream, which is
+-	then used as the random stream and used to update
+-	the stored seed.
+-
+-The only other detailed description I've found of the
+-sources of randomness for CryptGenRandom is this excerpt
+-from a posting
+-http://www.der-keiler.de/Newsgroups/comp.security.ssh/2002-06/0169.html
+-
+-From: Jon McClelland (dowot69 at hotmail.com) 
+-Date: 06/12/02 
+-... 
+- 
+-Windows, call a function such as CryptGenRandom, which has two of 
+-the properties of a good random number generator, unpredictability and 
+-even value distribution. This function, declared in Wincrypt.h, is 
+-available on just about every Windows platform, including Windows 95 
+-with Internet Explorer 3.02 or later, Windows 98, Windows Me, Windows 
+-CE v3, Windows NT 4, Windows 2000, and Windows XP. 
+- 
+-CryptGenRandom gets its randomness, also known as entropy, from many 
+-sources in Windows 2000, including the following: 
+-The current process ID (GetCurrentProcessID). 
+-The current thread ID (GetCurrentThreadID). 
+-The ticks since boot (GetTickCount). 
+-The current time (GetLocalTime). 
+-Various high-precision performance counters (QueryPerformanceCounter). 
+-A Message Digest 4 (MD4) hash of the user's environment block, which 
+-includes username, computer name, and search path. 
+- 
+-High-precision internal CPU counters, such as RDTSC, RDMSR, RDPMC (x86 
+-only-more information about these counters is at 
+-developer.intel.com/software/idap/resources/technical_collateral/pentiumii/RDTSCPM1.HTM 
+-<http://developer.intel.com>). 
+- 
+-Low-level system information, such as idle time, kernel time, 
+-interrupt times, commit limit, page read count, cache read count, 
+-nonpaged pool allocations, alignment fixup count, operating system 
+-lookaside information. 
+- 
+-Such information is added to a buffer, which is hashed using MD4 and 
+-used as the key to modify a buffer, using RC4, provided by the user. 
+-(Refer to the CryptGenRandom documentation in the Platform SDK for 
+-more information about the user-provided buffer.) Hence, if the user 
+-provides additional data in the buffer, this is used as an element in 
+-the witches brew to generate the random data. The result is a 
+-cryptographically random number generator. 
+-Also, note that if you plan to sell your software to the United States 
+-federal government, you'll need to use FIPS 140-1-approved algorithms. 
+-The default versions of CryptGenRandom in Microsoft Windows CE v3, 
+-Windows 95, Windows 98, Windows Me, Windows 2000, and Windows XP are 
+-FIPS-approved. Obviously FIPS-140 compliance is necessary but not 
+-sufficient to provide a properly secure source of random data. 
+- 
+-*/
+-/*
+-[Update: 2007-11-13]
+-CryptGenRandom does not necessarily provide forward secrecy or reverse
+-secrecy.  See the paper by Leo Dorrendorf and Zvi Gutterman and Benny
+-Pinkas, _Cryptanalysis of the Random Number Generator of the Windows
+-Operating System_, Cryptology ePrint Archive, Report 2007/419,
+-http://eprint.iacr.org/2007/419
+-*/
+-
+-#endif /* MS_WIN32 */
+-- 
+2.25.3
+
-- 
2.25.3



More information about the buildroot mailing list