[packages/python-Crypto] - added Fedora patches (including CVE-2013-7459,CVE-2018-6594 fixes; excluding python3only patch) -

qboosh qboosh at pld-linux.org
Thu Oct 26 21:26:55 CEST 2023


commit 9e4d51f38787b0da1eee1f513644f76d6cce6227
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date:   Thu Oct 26 21:28:54 2023 +0200

    - added Fedora patches (including CVE-2013-7459,CVE-2018-6594 fixes; excluding python3only patch)
    - added 2to3 patch to fix build after build_py_2to3 removal from setuptools distutils layer

 py38.patch                               |   14 -
 pycrypto-2to3.patch                      |  100 ++
 pycrypto-CVE-2013-7459.patch             |  106 ++
 pycrypto-CVE-2018-6594.patch             |   51 +
 pycrypto-SyntaxWarning.patch             |   11 +
 pycrypto-drop-py2.1-support.patch        |  296 +++++
 pycrypto-fix-pubkey-size-divisions.patch |   46 +
 pycrypto-link.patch                      |   13 +
 pycrypto-no-distutils.patch              |   96 ++
 pycrypto-optflags.patch                  |   31 +
 pycrypto-python3.10.patch                |  289 +++++
 pycrypto-python3.11.patch                |   12 +
 pycrypto-python3.12.patch                |   95 ++
 pycrypto-unbundle-libtomcrypt.patch      |   30 +
 pycrypto-use-os-random.patch             | 1790 ++++++++++++++++++++++++++++++
 python-Crypto.spec                       |   86 +-
 16 files changed, 3033 insertions(+), 33 deletions(-)
---
diff --git a/python-Crypto.spec b/python-Crypto.spec
index f4311df..88ec8fd 100644
--- a/python-Crypto.spec
+++ b/python-Crypto.spec
@@ -1,6 +1,6 @@
 
 # Conditional build:
-%bcond_without	tests	# do not perform "make test"
+%bcond_without	tests	# unit tests
 %bcond_without	python2 # CPython 2.x module
 %bcond_without	python3 # CPython 3.x module
 
@@ -15,13 +15,26 @@ License:	Public Domain and Python
 Group:		Development/Languages/Python
 Source0:	http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-%{version}.tar.gz
 # Source0-md5:	55a61a054aa66812daf5161a0d5d7eda
-Patch0:		py38.patch
+Patch0:		pycrypto-optflags.patch
+Patch1:		pycrypto-CVE-2013-7459.patch
+Patch2:		pycrypto-CVE-2018-6594.patch
+Patch3:		pycrypto-fix-pubkey-size-divisions.patch
+Patch4:		pycrypto-unbundle-libtomcrypt.patch
+Patch5:		pycrypto-link.patch
+Patch6:		pycrypto-use-os-random.patch
+Patch7:		pycrypto-drop-py2.1-support.patch
+Patch8:		pycrypto-python3.10.patch
+Patch9:		pycrypto-python3.11.patch
+Patch10:	pycrypto-python3.12.patch
+Patch11:	pycrypto-no-distutils.patch
+Patch12:	pycrypto-SyntaxWarning.patch
+Patch13:	pycrypto-2to3.patch
 URL:		http://www.dlitz.net/software/pycrypto/
 BuildRequires:	gmp-devel
 %if %{with python2}
-BuildRequires:	python >= 2.2
-BuildRequires:	python-devel >= 2.2
-BuildRequires:	python-modules >= 2.2
+BuildRequires:	python >= 1:2.5
+BuildRequires:	python-devel >= 1:2.5
+BuildRequires:	python-modules >= 1:2.5
 %endif
 %if %{with python3}
 BuildRequires:	python3 >= 1:3.2
@@ -96,6 +109,19 @@ zaimplementowanych dla języka Python 3. Pakiet zawiera między innymi:
 %prep
 %setup -q -n pycrypto-%{version}
 %patch0 -p1
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
 
 %build
 %if %{with python2}
@@ -133,20 +159,27 @@ rm -rf $RPM_BUILD_ROOT
 %dir %{py_sitedir}/%{module}
 %{py_sitedir}/%{module}/*.py[co]
 %dir %{py_sitedir}/%{module}/Cipher
+%attr(755,root,root) %{py_sitedir}/%{module}/Cipher/_*.so
+%{py_sitedir}/%{module}/Cipher/*.py[co]
 %dir %{py_sitedir}/%{module}/Hash
+%attr(755,root,root) %{py_sitedir}/%{module}/Hash/_*.so
+%{py_sitedir}/%{module}/Hash/*.py[co]
 %dir %{py_sitedir}/%{module}/Protocol
+%{py_sitedir}/%{module}/Protocol/*.py[co]
 %dir %{py_sitedir}/%{module}/PublicKey
+%attr(755,root,root) %{py_sitedir}/%{module}/PublicKey/_fastmath.so
+%{py_sitedir}/%{module}/PublicKey/*.py[co]
 %dir %{py_sitedir}/%{module}/Random
+%{py_sitedir}/%{module}/Random/*.py[co]
 %dir %{py_sitedir}/%{module}/Random/Fortuna
-%dir %{py_sitedir}/%{module}/Random/OSRNG
+%{py_sitedir}/%{module}/Random/Fortuna/*.py[co]
 %dir %{py_sitedir}/%{module}/Signature
+%{py_sitedir}/%{module}/Signature/*.py[co]
 %dir %{py_sitedir}/%{module}/Util
-%attr(755,root,root) %{py_sitedir}/%{module}/*/*.so
-%{py_sitedir}/%{module}/*/*.py[co]
-%{py_sitedir}/%{module}/*/*/*.py[co]
-%if "%{py_ver}" > "2.4"
-%{py_sitedir}/pycrypto-*.egg-info
-%endif
+%attr(755,root,root) %{py_sitedir}/%{module}/Util/_counter.so
+%attr(755,root,root) %{py_sitedir}/%{module}/Util/strxor.so
+%{py_sitedir}/%{module}/Util/*.py[co]
+%{py_sitedir}/pycrypto-%{version}-py*.egg-info
 %endif
 
 %if %{with python3}
@@ -157,18 +190,33 @@ rm -rf $RPM_BUILD_ROOT
 %{py3_sitedir}/%{module}/*.py
 %{py3_sitedir}/%{module}/__pycache__
 %dir %{py3_sitedir}/%{module}/Cipher
+%attr(755,root,root) %{py3_sitedir}/%{module}/Cipher/_*.cpython-*.so
+%{py3_sitedir}/%{module}/Cipher/*.py
+%{py3_sitedir}/%{module}/Cipher/__pycache__
 %dir %{py3_sitedir}/%{module}/Hash
+%attr(755,root,root) %{py3_sitedir}/%{module}/Hash/_*.cpython-*.so
+%{py3_sitedir}/%{module}/Hash/*.py
+%{py3_sitedir}/%{module}/Hash/__pycache__
 %dir %{py3_sitedir}/%{module}/Protocol
+%{py3_sitedir}/%{module}/Protocol/*.py
+%{py3_sitedir}/%{module}/Protocol/__pycache__
 %dir %{py3_sitedir}/%{module}/PublicKey
+%attr(755,root,root) %{py3_sitedir}/%{module}/PublicKey/_fastmath.cpython-*.so
+%{py3_sitedir}/%{module}/PublicKey/*.py
+%{py3_sitedir}/%{module}/PublicKey/__pycache__
 %dir %{py3_sitedir}/%{module}/Random
+%{py3_sitedir}/%{module}/Random/*.py
+%{py3_sitedir}/%{module}/Random/__pycache__
 %dir %{py3_sitedir}/%{module}/Random/Fortuna
-%dir %{py3_sitedir}/%{module}/Random/OSRNG
+%{py3_sitedir}/%{module}/Random/Fortuna/*.py
+%{py3_sitedir}/%{module}/Random/Fortuna/__pycache__
 %dir %{py3_sitedir}/%{module}/Signature
+%{py3_sitedir}/%{module}/Signature/*.py
+%{py3_sitedir}/%{module}/Signature/__pycache__
 %dir %{py3_sitedir}/%{module}/Util
-%attr(755,root,root) %{py3_sitedir}/%{module}/*/*.so
-%{py3_sitedir}/%{module}/*/*.py
-%{py3_sitedir}/%{module}/*/__pycache__
-%{py3_sitedir}/%{module}/*/*/*.py
-%{py3_sitedir}/%{module}/*/*/__pycache__
-%{py3_sitedir}/pycrypto-*.egg-info
+%attr(755,root,root) %{py3_sitedir}/%{module}/Util/_counter.cpython-*.so
+%attr(755,root,root) %{py3_sitedir}/%{module}/Util/strxor.cpython-*.so
+%{py3_sitedir}/%{module}/Util/*.py
+%{py3_sitedir}/%{module}/Util/__pycache__
+%{py3_sitedir}/pycrypto-%{version}-py*.egg-info
 %endif
diff --git a/py38.patch b/py38.patch
deleted file mode 100644
index 24d1c43..0000000
--- a/py38.patch
+++ /dev/null
@@ -1,14 +0,0 @@
---- pycrypto-2.6.1/lib/Crypto/Random/_UserFriendlyRNG.py.org	2019-10-29 15:53:40.311134311 +0100
-+++ pycrypto-2.6.1/lib/Crypto/Random/_UserFriendlyRNG.py	2019-10-29 15:55:46.281436245 +0100
-@@ -74,7 +74,10 @@ class _EntropyCollector(object):
-         self._time_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
- 
-         # Add the fractional part of time.clock()
--        t = time.clock()
-+        try:
-+            t = time.clock()
-+        except AttributeError:
-+            t = time.process_time()
-         self._clock_es.feed(struct.pack("@I", int(2**30 * (t - floor(t)))))
- 
- 
diff --git a/pycrypto-2to3.patch b/pycrypto-2to3.patch
new file mode 100644
index 0000000..2c73f32
--- /dev/null
+++ b/pycrypto-2to3.patch
@@ -0,0 +1,100 @@
+--- pycrypto-2.6.1/setup.py.orig	2023-10-26 21:03:02.214676533 +0200
++++ pycrypto-2.6.1/setup.py	2023-10-26 21:06:02.467033356 +0200
+@@ -55,6 +55,85 @@ USE_GCOV = 0
+ 
+ from setuptools.command.build_py import build_py
+ 
++if sys.version_info[0] == 3:
++    # from python3.10 distutils/util.py
++    def run_2to3(files, fixer_names=None, options=None, explicit=None):
++        """Invoke 2to3 on a list of Python files.
++        The files should all come from the build area, as the
++        modification is done in-place. To reduce the build time,
++        only files modified since the last invocation of this
++        function should be passed in the files argument."""
++    
++        if not files:
++            return
++    
++        # Make this class local, to delay import of 2to3
++        from lib2to3.refactor import RefactoringTool, get_fixers_from_package
++        from distutils import log
++        class DistutilsRefactoringTool(RefactoringTool):
++            def log_error(self, msg, *args, **kw):
++                log.error(msg, *args)
++    
++            def log_message(self, msg, *args):
++                log.info(msg, *args)
++    
++            def log_debug(self, msg, *args):
++                log.debug(msg, *args)
++    
++        if fixer_names is None:
++            fixer_names = get_fixers_from_package('lib2to3.fixes')
++        r = DistutilsRefactoringTool(fixer_names, options=options)
++        r.refactor(files, write=True)
++    
++    class Mixin2to3:
++        '''Mixin class for commands that run 2to3.
++        To configure 2to3, setup scripts may either change
++        the class variables, or inherit from individual commands
++        to override how 2to3 is invoked.'''
++    
++        # provide list of fixers to run;
++        # defaults to all from lib2to3.fixers
++        fixer_names = None
++    
++        # options dictionary
++        options = None
++    
++        # list of fixers to invoke even though they are marked as explicit
++        explicit = None
++    
++        def run_2to3(self, files):
++            return run_2to3(files, self.fixer_names, self.options, self.explicit)
++    
++    # from python3.10 distutils/command/build_py.py
++    class build_py_2to3(build_py, Mixin2to3):
++        def run(self):
++            self.updated_files = []
++    
++            # Base class code
++            if self.py_modules:
++                self.build_modules()
++            if self.packages:
++                self.build_packages()
++                self.build_package_data()
++    
++            # 2to3
++            self.run_2to3(self.updated_files)
++    
++            # Remaining base class code
++            self.byte_compile(self.get_outputs(include_bytecode=0))
++    
++        def build_module(self, module, module_file, package):
++            res = build_py.build_module(self, module, module_file, package)
++            if res[1]:
++                # file was copied
++                self.updated_files.append(res[0])
++            return res
++
++    build_py_base = build_py_2to3
++else:
++    build_py_base = build_py
++
++
+ # 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
+ 
+@@ -225,9 +303,9 @@ class PCTBuildConfigure(Command):
+             if os.system(cmd) != 0:
+                 raise RuntimeError("autoconf error")
+ 
+-class PCTBuildPy(build_py):
++class PCTBuildPy(build_py_base):
+     def find_package_modules(self, package, package_dir, *args, **kwargs):
+-        modules = build_py.find_package_modules(self, package, package_dir,
++        modules = build_py_base.find_package_modules(self, package, package_dir,
+             *args, **kwargs)
+ 
+         # Exclude certain modules
diff --git a/pycrypto-CVE-2013-7459.patch b/pycrypto-CVE-2013-7459.patch
new file mode 100644
index 0000000..db1f740
--- /dev/null
+++ b/pycrypto-CVE-2013-7459.patch
@@ -0,0 +1,106 @@
+From 8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4 Mon Sep 17 00:00:00 2001
+From: Legrandin <helderijs at gmail.com>
+Date: Sun, 22 Dec 2013 22:24:46 +0100
+Subject: [PATCH] Throw exception when IV is used with ECB or CTR
+
+The IV parameter is currently ignored when initializing
+a cipher in ECB or CTR mode.
+
+For CTR mode, it is confusing: it takes some time to see
+that a different parameter is needed (the counter).
+
+For ECB mode, it is outright dangerous.
+
+This patch forces an exception to be raised.
+---
+ lib/Crypto/SelfTest/Cipher/common.py | 31 +++++++++++++++++++++++--------
+ src/block_template.c                 | 11 +++++++++++
+ 2 files changed, 34 insertions(+), 8 deletions(-)
+
+diff --git a/lib/Crypto/SelfTest/Cipher/common.py b/lib/Crypto/SelfTest/Cipher/common.py
+index 420b6ff..a5f8a88 100644
+--- a/lib/Crypto/SelfTest/Cipher/common.py
++++ b/lib/Crypto/SelfTest/Cipher/common.py
+@@ -239,16 +239,30 @@ class RoundtripTest(unittest.TestCase):
+         return """%s .decrypt() output of .encrypt() should not be garbled""" % (self.module_name,)
+ 
+     def runTest(self):
+-        for mode in (self.module.MODE_ECB, self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB, self.module.MODE_OPENPGP):
++
++        ## ECB mode
++        mode = self.module.MODE_ECB
++        encryption_cipher = self.module.new(a2b_hex(self.key), mode)
++        ciphertext = encryption_cipher.encrypt(self.plaintext)
++        decryption_cipher = self.module.new(a2b_hex(self.key), mode)
++        decrypted_plaintext = decryption_cipher.decrypt(ciphertext)
++        self.assertEqual(self.plaintext, decrypted_plaintext)
++
++        ## OPENPGP mode
++        mode = self.module.MODE_OPENPGP
++        encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
++        eiv_ciphertext = encryption_cipher.encrypt(self.plaintext)
++        eiv = eiv_ciphertext[:self.module.block_size+2]
++        ciphertext = eiv_ciphertext[self.module.block_size+2:]
++        decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv)
++        decrypted_plaintext = decryption_cipher.decrypt(ciphertext)
++        self.assertEqual(self.plaintext, decrypted_plaintext)
++
++        ## All other non-AEAD modes (but CTR)
++        for mode in (self.module.MODE_CBC, self.module.MODE_CFB, self.module.MODE_OFB):
+             encryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
+             ciphertext = encryption_cipher.encrypt(self.plaintext)
+-            
+-            if mode != self.module.MODE_OPENPGP:
+-                decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
+-            else:
+-                eiv = ciphertext[:self.module.block_size+2]
+-                ciphertext = ciphertext[self.module.block_size+2:]
+-                decryption_cipher = self.module.new(a2b_hex(self.key), mode, eiv)
++            decryption_cipher = self.module.new(a2b_hex(self.key), mode, self.iv)
+             decrypted_plaintext = decryption_cipher.decrypt(ciphertext)
+             self.assertEqual(self.plaintext, decrypted_plaintext)
+ 
+diff --git a/src/block_template.c b/src/block_template.c
+index f940e0e..d555ceb 100644
+--- a/src/block_template.c
++++ b/src/block_template.c
+@@ -170,6 +170,17 @@ ALGnew(PyObject *self, PyObject *args, PyObject *kwdict)
+ 				"Key cannot be the null string");
+ 		return NULL;
+ 	}
++	if (IVlen != 0 && mode == MODE_ECB)
++	{
++		PyErr_Format(PyExc_ValueError, "ECB mode does not use IV");
++		return NULL;
++	}
++	if (IVlen != 0 && mode == MODE_CTR)
++	{
++		PyErr_Format(PyExc_ValueError,
++			"CTR mode needs counter parameter, not IV");
++		return NULL;
++	}
+ 	if (IVlen != BLOCK_SIZE && mode != MODE_ECB && mode != MODE_CTR)
+ 	{
+ 		PyErr_Format(PyExc_ValueError,
+From 58de28a5d32bc10e15766e5a59f41b07397cc6cb Mon Sep 17 00:00:00 2001
+From: Richard Mitchell <richard.j.mitchell at gmail.com>
+Date: Mon, 28 Apr 2014 16:58:27 +0100
+Subject: [PATCH] Fix speedtest run for ECB modes.
+
+---
+ pct-speedtest.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/pct-speedtest.py b/pct-speedtest.py
+index 4ce18be..c7b893a 100644
+--- a/pct-speedtest.py
++++ b/pct-speedtest.py
+@@ -121,6 +121,8 @@ class Benchmark:
+         blocks = self.random_blocks(16384, 1000)
+         if mode is None:
+             cipher = module.new(key)
++        elif mode==module.MODE_ECB:
++            cipher = module.new(key, module.MODE_ECB)
+         else:
+             cipher = module.new(key, mode, iv)
+ 
diff --git a/pycrypto-CVE-2018-6594.patch b/pycrypto-CVE-2018-6594.patch
new file mode 100644
index 0000000..8e8c558
--- /dev/null
+++ b/pycrypto-CVE-2018-6594.patch
@@ -0,0 +1,51 @@
+--- a/lib/Crypto/PublicKey/ElGamal.py
++++ b/lib/Crypto/PublicKey/ElGamal.py
+@@ -153,33 +153,33 @@ def generate(bits, randfunc, progress_fu
+         if number.isPrime(obj.p, randfunc=randfunc):
+             break
+     # Generate generator g
+-    # See Algorithm 4.80 in Handbook of Applied Cryptography
+-    # Note that the order of the group is n=p-1=2q, where q is prime
+     if progress_func:
+         progress_func('g\n')
+     while 1:
++        # Choose a square residue; it will generate a cyclic group of order q.
++        obj.g = pow(number.getRandomRange(2, obj.p, randfunc), 2, obj.p)
++
+         # We must avoid g=2 because of Bleichenbacher's attack described
+         # in "Generating ElGamal signatures without knowning the secret key",
+         # 1996
+-        #
+-        obj.g = number.getRandomRange(3, obj.p, randfunc)
+-        safe = 1
+-        if pow(obj.g, 2, obj.p)==1:
+-            safe=0
+-        if safe and pow(obj.g, q, obj.p)==1:
+-            safe=0
++        if obj.g in (1, 2):
++            continue
++
+         # Discard g if it divides p-1 because of the attack described
+         # in Note 11.67 (iii) in HAC
+-        if safe and divmod(obj.p-1, obj.g)[1]==0:
+-            safe=0
++        if (obj.p - 1) % obj.g == 0:
++            continue
++
+         # g^{-1} must not divide p-1 because of Khadir's attack
+         # described in "Conditions of the generator for forging ElGamal
+         # signature", 2011
+         ginv = number.inverse(obj.g, obj.p)
+-        if safe and divmod(obj.p-1, ginv)[1]==0:
+-            safe=0
+-        if safe:
+-            break
++        if (obj.p - 1) % ginv == 0:
++            continue
++
++        # Found
++        break
++
+     # Generate private key x
+     if progress_func:
+         progress_func('x\n')
diff --git a/pycrypto-SyntaxWarning.patch b/pycrypto-SyntaxWarning.patch
new file mode 100644
index 0000000..2b77634
--- /dev/null
+++ b/pycrypto-SyntaxWarning.patch
@@ -0,0 +1,11 @@
+--- a/lib/Crypto/SelfTest/Random/test_random.py
++++ b/lib/Crypto/SelfTest/Random/test_random.py
+@@ -102,7 +102,7 @@ class SimpleTest(unittest.TestCase):
+         for i in range(10):
+             self.assertEqual(random.choice((1,2,3)) in (1,2,3), True)
+         self.assertEqual(random.choice([1,2,3]) in [1,2,3], True)
+-        if sys.version_info[0] is 3:
++        if sys.version_info[0] == 3:
+             self.assertEqual(random.choice(bytearray(b('123'))) in bytearray(b('123')), True)
+         self.assertEqual(1, random.choice([1]))
+         self.assertRaises(IndexError, random.choice, [])
diff --git a/pycrypto-drop-py2.1-support.patch b/pycrypto-drop-py2.1-support.patch
new file mode 100644
index 0000000..94a3387
--- /dev/null
+++ b/pycrypto-drop-py2.1-support.patch
@@ -0,0 +1,296 @@
+--- a/lib/Crypto/Cipher/blockalgo.py
++++ b/lib/Crypto/Cipher/blockalgo.py
+@@ -22,8 +22,6 @@
+ """Module with definitions common to all block ciphers."""
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ #: *Electronic Code Book (ECB)*.
+--- a/lib/Crypto/PublicKey/DSA.py
++++ b/lib/Crypto/PublicKey/DSA.py
+@@ -82,8 +82,6 @@ __revision__ = "$Id$"
+ __all__ = ['generate', 'construct', 'error', 'DSAImplementation', '_DSAobj']
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ 
+ from Crypto.PublicKey import _DSA, _slowmath, pubkey
+ from Crypto import Random
+--- a/lib/Crypto/PublicKey/RSA.py
++++ b/lib/Crypto/PublicKey/RSA.py
+@@ -68,8 +68,6 @@ __revision__ = "$Id$"
+ __all__ = ['generate', 'construct', 'error', 'importKey', 'RSAImplementation', '_RSAobj']
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ #from Crypto.Util.python_compat import *
+ from Crypto.Util.number import getRandomRange, bytes_to_long, long_to_bytes
+--- a/lib/Crypto/PublicKey/_slowmath.py
++++ b/lib/Crypto/PublicKey/_slowmath.py
+@@ -30,8 +30,6 @@ __all__ = ['rsa_construct']
+ 
+ import sys
+ 
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.number import size, inverse, GCD
+ 
+ class error(Exception):
+--- a/lib/Crypto/Random/Fortuna/FortunaAccumulator.py
++++ b/lib/Crypto/Random/Fortuna/FortunaAccumulator.py
+@@ -25,8 +25,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+     
+ from binascii import b2a_hex
+--- a/lib/Crypto/Random/Fortuna/FortunaGenerator.py
++++ b/lib/Crypto/Random/Fortuna/FortunaGenerator.py
+@@ -25,8 +25,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] is 2 and  sys.version_info[1] is 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import struct
+--- a/lib/Crypto/Random/Fortuna/SHAd256.py
++++ b/lib/Crypto/Random/Fortuna/SHAd256.py
+@@ -32,8 +32,6 @@ __revision__ = "$Id$"
+ __all__ = ['new', 'digest_size']
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ from binascii import b2a_hex
+--- a/lib/Crypto/Random/random.py
++++ b/lib/Crypto/Random/random.py
+@@ -29,8 +29,6 @@ __all__ = ['StrongRandom', 'getrandbits'
+ 
+ from Crypto import Random
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ 
+ class StrongRandom(object):
+     def __init__(self, rng=None, randfunc=None):
+--- a/lib/Crypto/SelfTest/PublicKey/test_DSA.py
++++ b/lib/Crypto/SelfTest/PublicKey/test_DSA.py
+@@ -28,8 +28,6 @@ __revision__ = "$Id$"
+ 
+ import sys
+ import os
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import unittest
+--- a/lib/Crypto/SelfTest/PublicKey/test_RSA.py
++++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py
+@@ -28,8 +28,6 @@ __revision__ = "$Id$"
+ 
+ import sys
+ import os
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import unittest
+--- a/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py
++++ b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py
+@@ -27,8 +27,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import unittest
+--- a/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py
++++ b/lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py
+@@ -27,8 +27,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import unittest
+--- a/lib/Crypto/SelfTest/Random/test_random.py
++++ b/lib/Crypto/SelfTest/Random/test_random.py
+@@ -28,8 +28,6 @@ __revision__ = "$Id$"
+ 
+ import unittest
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ class SimpleTest(unittest.TestCase):
+--- a/lib/Crypto/SelfTest/st_common.py
++++ b/lib/Crypto/SelfTest/st_common.py
+@@ -29,8 +29,6 @@ __revision__ = "$Id$"
+ import unittest
+ import binascii
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ class _list_testloader(unittest.TestLoader):
+--- a/lib/Crypto/SelfTest/Util/test_Counter.py
++++ b/lib/Crypto/SelfTest/Util/test_Counter.py
+@@ -27,8 +27,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ import unittest
+--- a/lib/Crypto/SelfTest/Util/test_number.py
++++ b/lib/Crypto/SelfTest/Util/test_number.py
+@@ -27,8 +27,6 @@
+ __revision__ = "$Id$"
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ 
+ import unittest
+ 
+--- a/lib/Crypto/Signature/PKCS1_PSS.py
++++ b/lib/Crypto/Signature/PKCS1_PSS.py
+@@ -67,8 +67,6 @@ __revision__ = "$Id$"
+ __all__ = [ 'new', 'PSS_SigScheme' ]
+ 
+ from Crypto.Util.py3compat import *
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ import Crypto.Util.number
+ from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes
+ from Crypto.Util.strxor import strxor
+--- a/lib/Crypto/Util/Counter.py
++++ b/lib/Crypto/Util/Counter.py
+@@ -52,8 +52,6 @@ An example of usage is the following:
+ :undocumented: __package__
+ """
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ from Crypto.Util.py3compat import *
+ 
+ from Crypto.Util import _counter
+--- a/lib/Crypto/Util/_number_new.py
++++ b/lib/Crypto/Util/_number_new.py
+@@ -28,8 +28,6 @@ __revision__ = "$Id$"
+ __all__ = ['ceil_shift', 'ceil_div', 'floor_div', 'exact_log2', 'exact_div']
+ 
+ import sys
+-if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+-    from Crypto.Util.py21compat import *
+ 
+ def ceil_shift(n, b):
+     """Return ceil(n / 2**b) without performing any floating-point or division operations.
+--- a/lib/Crypto/Util/py21compat.py
++++ /dev/null
+@@ -1,84 +0,0 @@
+-# -*- coding: utf-8 -*-
+-#
+-#  Util/py21compat.py : Compatibility code for Python 2.1
+-#
+-# 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.
+-# ===================================================================
+-
+-"""Compatibility code for Python 2.1
+-
+-Currently, this just defines:
+-    - True and False
+-    - object
+-    - isinstance
+-"""
+-
+-__revision__ = "$Id$"
+-__all__ = []
+-
+-import sys
+-import __builtin__
+-
+-# 'True' and 'False' aren't defined in Python 2.1.  Define them.
+-try:
+-    True, False
+-except NameError:
+-    (True, False) = (1, 0)
+-    __all__ += ['True', 'False']
+-
+-# New-style classes were introduced in Python 2.2.  Defining "object" in Python
+-# 2.1 lets us use new-style classes in versions of Python that support them,
+-# while still maintaining backward compatibility with old-style classes
+-try:
+-    object
+-except NameError:
+-    class object: pass
+-    __all__ += ['object']
+-
+-# Starting with Python 2.2, isinstance allows a tuple for the second argument.
+-# Also, builtins like "tuple", "list", "str", "unicode", "int", and "long"
+-# became first-class types, rather than functions.  We want to support
+-# constructs like:
+-#   isinstance(x, (int, long))
+-# So we hack it for Python 2.1.
+-try:
+-    isinstance(5, (int, long))
+-except TypeError:
+-    __all__ += ['isinstance']
+-    _builtin_type_map = {
+-        tuple: type(()),
+-        list: type([]),
+-        str: type(""),
+-        unicode: type(u""),
+-        int: type(0),
+-        long: type(0L),
+-    }
+-    def isinstance(obj, t):
+-        if not __builtin__.isinstance(t, type(())):
+-            # t is not a tuple
+-            return __builtin__.isinstance(obj, _builtin_type_map.get(t, t))
+-        else:
+-            # t is a tuple
+-            for typ in t:
+-                if __builtin__.isinstance(obj, _builtin_type_map.get(typ, typ)):
+-                    return True
+-            return False
+-
+-# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/pycrypto-fix-pubkey-size-divisions.patch b/pycrypto-fix-pubkey-size-divisions.patch
new file mode 100644
index 0000000..9f3323b
--- /dev/null
+++ b/pycrypto-fix-pubkey-size-divisions.patch
@@ -0,0 +1,46 @@
+setup.py for Python 3 doesn't invoke 2to3 on pct-speedtest.py, which runs
+into problems:
+
+Traceback (most recent call last):
+  File "pct-speedtest.py", line 218, in <module>
+    Benchmark().run()
+  File "pct-speedtest.py", line 200, in run
+    self.test_pubkey_setup(pubkey_name, module, key_bytes)
+  File "pct-speedtest.py", line 85, in test_pubkey_setup
+    keys = self.random_keys(key_bytes)[:5]
+  File "pct-speedtest.py", line 49, in random_keys
+    return self.random_blocks(bytes, 10**5)     # 100k
+  File "pct-speedtest.py", line 53, in random_blocks
+    data = self.random_data(bytes)
+  File "pct-speedtest.py", line 62, in random_data
+    self.__random_data = self._random_bytes(bytes)
+  File "pct-speedtest.py", line 73, in _random_bytes
+    return os.urandom(b)
+  File "/usr/lib64/python3.2/os.py", line 777, in urandom
+    bs += read(_urandomfd, n - len(bs))
+TypeError: integer argument expected, got float
+
+This is due to the divisions in the pubkey_specs table, which in Python 3 is
+true division, returning a float.
+
+As it happens, 2to3 can't convert these divisions, see:
+http://bugs.python.org/issue12831
+
+Change them to explicitly be floor divisions (supported in Python 2.2
+onwards; see PEP 0238)
+
+--- pycrypto/pct-speedtest.py
++++ pycrypto/pct-speedtest.py
+@@ -165,9 +165,9 @@
+ 
+     def run(self):
+         pubkey_specs = [
+-            ("RSA(1024)", RSA, 1024/8),
+-            ("RSA(2048)", RSA, 2048/8),
+-            ("RSA(4096)", RSA, 4096/8),
++            ("RSA(1024)", RSA, 1024//8),
++            ("RSA(2048)", RSA, 2048//8),
++            ("RSA(4096)", RSA, 4096//8),
+             ]
+         block_specs = [
+             ("DES", DES, 8),
diff --git a/pycrypto-link.patch b/pycrypto-link.patch
new file mode 100644
index 0000000..8f896a2
--- /dev/null
+++ b/pycrypto-link.patch
@@ -0,0 +1,13 @@
+log() function not available in libgmp, need libm too
+
+--- a/setup.py
++++ b/setup.py
+@@ -349,7 +349,7 @@ kw = {'name':"pycrypto",
+             # _fastmath (uses GNU mp library)
+             Extension("Crypto.PublicKey._fastmath",
+                       include_dirs=['src/','/usr/include/'],
+-                      libraries=['gmp'],
++                      libraries=['gmp','m'],
+                       sources=["src/_fastmath.c"]),
+ 
+             # Hash functions
diff --git a/pycrypto-no-distutils.patch b/pycrypto-no-distutils.patch
new file mode 100644
index 0000000..8b4c9c6
--- /dev/null
+++ b/pycrypto-no-distutils.patch
@@ -0,0 +1,96 @@
+--- a/lib/Crypto/SelfTest/PublicKey/test_DSA.py
++++ b/lib/Crypto/SelfTest/PublicKey/test_DSA.py
+@@ -223,7 +223,7 @@ def get_tests(config={}):
+         from Crypto.PublicKey import _fastmath
+         tests += list_test_cases(DSAFastMathTest)
+     except ImportError:
+-        from distutils.sysconfig import get_config_var
++        from sysconfig import get_config_var
+         import inspect
+         _fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
+             inspect.getfile(inspect.currentframe())))
+--- a/lib/Crypto/SelfTest/PublicKey/test_RSA.py
++++ b/lib/Crypto/SelfTest/PublicKey/test_RSA.py
+@@ -393,7 +393,7 @@ def get_tests(config={}):
+         from Crypto.PublicKey import _fastmath
+         tests += list_test_cases(RSAFastMathTest)
+     except ImportError:
+-        from distutils.sysconfig import get_config_var
++        from sysconfig import get_config_var
+         import inspect
+         _fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
+             inspect.getfile(inspect.currentframe())))
+--- a/lib/Crypto/Util/number.py
++++ b/lib/Crypto/Util/number.py
+@@ -41,7 +41,7 @@ except ImportError:
+     # see an exception raised if _fastmath exists but cannot be imported,
+     # uncomment the below
+     #
+-    # from distutils.sysconfig import get_config_var
++    # from sysconfig import get_config_var
+     # import inspect, os
+     # _fm_path = os.path.normpath(os.path.dirname(os.path.abspath(
+         # inspect.getfile(inspect.currentframe())))
+--- pycrypto-2.6.1/setup.py.orig	2023-10-25 12:37:34.607044249 +0200
++++ pycrypto-2.6.1/setup.py	2023-10-25 22:05:36.932404453 +0200
+@@ -1,6 +1,6 @@
+ #! /usr/bin/env python
+ #
+-#  setup.py : Distutils setup script
++#  setup.py : setuptools setup script
+ #
+ #  Part of the Python Cryptography Toolkit
+ #
+@@ -36,11 +36,10 @@
+ 
+ __revision__ = "$Id$"
+ 
+-from distutils import core
+-from distutils.ccompiler import new_compiler
+-from distutils.core import Extension, Command
+-from distutils.command.build import build
+-from distutils.command.build_ext import build_ext
++from setuptools import setup
++from setuptools.command.build_ext import new_compiler
++from setuptools import Extension, Command
++from setuptools.command.build_ext import build_ext
+ import os, sys, re
+ import struct
+ 
+@@ -54,12 +53,7 @@ if sys.version[0:1] == '1':
+ USE_GCOV = 0
+ 
+ 
+-try:
+-    # Python 3
+-    from distutils.command.build_py import build_py_2to3 as build_py
+-except ImportError:
+-    # Python 2
+-    from distutils.command.build_py import build_py
++from setuptools.command.build_py import build_py
+ 
+ # 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
+@@ -391,9 +385,7 @@ kw = {'name':"pycrypto",
+ }
+ 
+ # If we're running Python 2.3, add extra information
+-if hasattr(core, 'setup_keywords'):
+-    if 'classifiers' in core.setup_keywords:
+-        kw['classifiers'] = [
++kw['classifiers'] = [
+           'Development Status :: 5 - Production/Stable',
+           'License :: Public Domain',
+           'Intended Audience :: Developers',
+@@ -403,9 +395,9 @@ if hasattr(core, 'setup_keywords'):
+           'Topic :: Security :: Cryptography',
+           'Programming Language :: Python :: 2',
+           'Programming Language :: Python :: 3',
+-          ]
++]
+ 
+-core.setup(**kw)
++setup(**kw)
+ 
+ def touch(path):
+     import os, time
diff --git a/pycrypto-optflags.patch b/pycrypto-optflags.patch
new file mode 100644
index 0000000..c0f57ce
--- /dev/null
+++ b/pycrypto-optflags.patch
@@ -0,0 +1,31 @@
+--- pycrypto/setup.py
++++ pycrypto/setup.py
+@@ -165,28 +165,6 @@
+             # Make assert() statements always work
+             self.__remove_compiler_option("-DNDEBUG")
+ 
+-            # Choose our own optimization options
+-            for opt in ["-O", "-O0", "-O1", "-O2", "-O3", "-Os"]:
+-                self.__remove_compiler_option(opt)
+-            if self.debug:
+-                # Basic optimization is still needed when debugging to compile
+-                # the libtomcrypt code.
+-                self.__add_compiler_option("-O")
+-            else:
+-                # Speed up execution by tweaking compiler options.  This
+-                # especially helps the DES modules.
+-                self.__add_compiler_option("-O3")
+-                self.__add_compiler_option("-fomit-frame-pointer")
+-                # Don't include debug symbols unless debugging
+-                self.__remove_compiler_option("-g")
+-                # Don't include profiling information (incompatible with
+-                # -fomit-frame-pointer)
+-                self.__remove_compiler_option("-pg")
+-            if USE_GCOV:
+-                self.__add_compiler_option("-fprofile-arcs")
+-                self.__add_compiler_option("-ftest-coverage")
+-                self.compiler.libraries += ['gcov']
+-
+         # Call the superclass's build_extensions method
+         build_ext.build_extensions(self)
+ 
diff --git a/pycrypto-python3.10.patch b/pycrypto-python3.10.patch
new file mode 100644
index 0000000..30f1218
--- /dev/null
+++ b/pycrypto-python3.10.patch
@@ -0,0 +1,289 @@
+--- a/src/AES.c
++++ b/src/AES.c
+@@ -26,6 +26,7 @@
+ 
+ #include <assert.h>
+ #include <stdlib.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ #define MODULE_NAME _AES
+--- a/src/ARC2.c
++++ b/src/ARC2.c
+@@ -42,6 +42,7 @@
+  */
+ 
+ #include <string.h>  
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ #define MODULE_NAME _ARC2
+--- a/src/block_template.c
++++ b/src/block_template.c
+@@ -33,6 +33,7 @@
+ #include <string.h>
+ #endif
+ 
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ #include "modsupport.h" 
+@@ -123,7 +124,8 @@ ALGnew(PyObject *self, PyObject *args, P
+ {
+ 	unsigned char *key, *IV;
+ 	ALGobject * new=NULL;
+-	int keylen, IVlen=0, mode=MODE_ECB, segment_size=0;
++	Py_ssize_t keylen, IVlen=0;
++	int mode=MODE_ECB, segment_size=0;
+ 	PyObject *counter = NULL;
+ 	int counter_shortcut = 0;
+ #ifdef PCT_ARC2_MODULE
+@@ -161,7 +163,7 @@ ALGnew(PyObject *self, PyObject *args, P
+ 	{
+ 		PyErr_Format(PyExc_ValueError,
+ 			     "Key must be %i bytes long, not %i",
+-			     KEY_SIZE, keylen);
++			     KEY_SIZE, (int)keylen);
+ 		return NULL;
+ 	}
+ 	if (KEY_SIZE==0 && keylen==0)
+@@ -242,7 +244,7 @@ ALGnew(PyObject *self, PyObject *args, P
+         new->st.effective_keylen = effective_keylen;
+ #endif
+ 
+-	block_init(&(new->st), key, keylen);
++	block_init(&(new->st), key, (int)keylen);
+ 	if (PyErr_Occurred())
+ 	{
+ 		Py_DECREF(new);
+@@ -250,7 +252,7 @@ ALGnew(PyObject *self, PyObject *args, P
+ 	}
+ 	memset(new->IV, 0, BLOCK_SIZE);
+ 	memset(new->oldCipher, 0, BLOCK_SIZE);
+-	memcpy(new->IV, IV, IVlen);
++	memcpy(new->IV, IV, (size_t)IVlen);
+ 	new->mode = mode;
+ 	new->count=BLOCK_SIZE;   /* stores how many bytes in new->oldCipher have been used */
+ 	return new;
+@@ -264,7 +266,8 @@ ALG_Encrypt(ALGobject *self, PyObject *a
+ {
+ 	unsigned char *buffer, *str;
+ 	unsigned char temp[BLOCK_SIZE];
+-	int i, j, len;
++	int i, j;
++	Py_ssize_t len;
+ 	PyObject *result;
+   
+ 	if (!PyArg_Parse(args, "s#", &str, &len))
+@@ -292,7 +295,7 @@ ALG_Encrypt(ALGobject *self, PyObject *a
+ 		return NULL;
+ 	}
+ 
+-	buffer=malloc(len);
++	buffer=malloc((size_t)len);
+ 	if (buffer==NULL) 
+ 	{
+ 		PyErr_SetString(PyExc_MemoryError, 
+@@ -496,7 +499,8 @@ ALG_Decrypt(ALGobject *self, PyObject *a
+ {
+ 	unsigned char *buffer, *str;
+ 	unsigned char temp[BLOCK_SIZE];
+-	int i, j, len;
++	int i, j;
++	Py_ssize_t len;
+ 	PyObject *result;
+ 
+ 	/* CTR mode decryption is identical to encryption */
+@@ -525,7 +529,7 @@ ALG_Decrypt(ALGobject *self, PyObject *a
+ 			     self->segment_size/8);
+ 		return NULL;
+ 	}
+-	buffer=malloc(len);
++	buffer=malloc((size_t)len);
+ 	if (buffer==NULL) 
+ 	{
+ 		PyErr_SetString(PyExc_MemoryError, 
+--- a/src/Blowfish.c
++++ b/src/Blowfish.c
+@@ -36,6 +36,7 @@
+ #endif
+ #include <assert.h>
+ #include <string.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ #include "Blowfish-tables.h"
+--- a/src/CAST.c
++++ b/src/CAST.c
+@@ -42,6 +42,7 @@
+ 
+ */
+ 
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ #define MODULE_NAME _CAST
+--- a/src/DES.c
++++ b/src/DES.c
+@@ -34,6 +34,7 @@
+ #undef DES  /* this is needed because tomcrypt_custom.h defines DES to an empty string */
+ 
+ #include <assert.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ typedef struct {
+--- a/src/hash_template.c
++++ b/src/hash_template.c
+@@ -30,6 +30,7 @@
+ #ifdef _HAVE_STDC_HEADERS
+ #include <string.h>
+ #endif
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ 
+@@ -163,7 +164,7 @@ static PyObject *
+ ALG_update(ALGobject *self, PyObject *args)
+ {
+ 	unsigned char *cp;
+-	int len;
++	Py_ssize_t len;
+ 
+ 	if (!PyArg_ParseTuple(args, "s#", &cp, &len))
+ 		return NULL;
+@@ -273,7 +274,7 @@ ALG_new(PyObject *self, PyObject *args)
+ {
+         ALGobject *new;
+ 	unsigned char *cp = NULL;
+-	int len;
++	Py_ssize_t len;
+ 	
+ 	if ((new = newALGobject()) == NULL)
+ 		return NULL;
+--- a/src/MD2.c
++++ b/src/MD2.c
+@@ -28,6 +28,7 @@
+   
+ 
+ #include <string.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ 
+--- a/src/MD4.c
++++ b/src/MD4.c
+@@ -28,6 +28,7 @@
+   
+ 
+ #include <string.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ 
+--- a/src/RIPEMD160.c
++++ b/src/RIPEMD160.c
+@@ -54,6 +54,7 @@
+ 
+ #include <assert.h>
+ #include <string.h>
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ 
+--- a/src/stream_template.c
++++ b/src/stream_template.c
+@@ -33,6 +33,7 @@
+ #include <string.h>
+ #endif
+ 
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycrypto_compat.h"
+ #include "modsupport.h"
+@@ -100,7 +101,7 @@ ALGnew(PyObject *self, PyObject *args, P
+ {
+ 	unsigned char *key;
+ 	ALGobject * new;
+-	int keylen;
++	Py_ssize_t keylen;
+ 
+ 	new = newALGobject();
+ 	if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#", kwlist, 
+@@ -124,7 +125,7 @@ ALGnew(PyObject *self, PyObject *args, P
+ 				"the null string (0 bytes long)");
+ 		return NULL;
+ 	}
+-	stream_init(&(new->st), key, keylen);
++	stream_init(&(new->st), key, (int)keylen);
+ 	if (PyErr_Occurred())
+ 	{
+ 		Py_DECREF(new);
+@@ -140,7 +141,7 @@ static PyObject *
+ ALG_Encrypt(ALGobject *self, PyObject *args)
+ {
+ 	unsigned char *buffer, *str;
+-	int len;
++	Py_ssize_t len;
+ 	PyObject *result;
+ 
+ 	if (!PyArg_Parse(args, "s#", &str, &len))
+@@ -149,7 +150,7 @@ ALG_Encrypt(ALGobject *self, PyObject *a
+ 	{
+ 		return PyBytes_FromStringAndSize(NULL, 0);
+ 	}
+-	buffer = malloc(len);
++	buffer = malloc((size_t)len);
+ 	if (buffer == NULL)
+ 	{
+ 		PyErr_SetString(PyExc_MemoryError, "No memory available in "
+@@ -157,8 +158,8 @@ ALG_Encrypt(ALGobject *self, PyObject *a
+ 		return NULL;
+ 	}
+ 	Py_BEGIN_ALLOW_THREADS;
+-	memcpy(buffer, str, len);
+-	stream_encrypt(&(self->st), buffer, len);
++	memcpy(buffer, str, (size_t)len);
++	stream_encrypt(&(self->st), buffer, (int)len);
+ 	Py_END_ALLOW_THREADS;
+ 	result = PyBytes_FromStringAndSize((char *)buffer, len);
+ 	free(buffer);
+@@ -172,7 +173,7 @@ static PyObject *
+ ALG_Decrypt(ALGobject *self, PyObject *args)
+ {
+ 	unsigned char *buffer, *str;
+-	int len;
++	Py_ssize_t len;
+ 	PyObject *result;
+ 
+ 	if (!PyArg_Parse(args, "s#", &str, &len))
+@@ -181,7 +182,7 @@ ALG_Decrypt(ALGobject *self, PyObject *a
+ 	{
+ 		return PyBytes_FromStringAndSize(NULL, 0);
+ 	}
+-	buffer = malloc(len);
++	buffer = malloc((size_t)len);
+ 	if (buffer == NULL)
+ 	{
+ 		PyErr_SetString(PyExc_MemoryError, "No memory available in "
+@@ -189,8 +190,8 @@ ALG_Decrypt(ALGobject *self, PyObject *a
+ 		return NULL;
+ 	}
+ 	Py_BEGIN_ALLOW_THREADS;
+-	memcpy(buffer, str, len);
+-	stream_decrypt(&(self->st), buffer, len);
++	memcpy(buffer, str, (size_t)len);
++	stream_decrypt(&(self->st), buffer, (int)len);
+ 	Py_END_ALLOW_THREADS;
+ 	result = PyBytes_FromStringAndSize((char *)buffer, len);
+ 	free(buffer);
+--- a/src/XOR.c
++++ b/src/XOR.c
+@@ -24,6 +24,7 @@
+  * =======================================================================
+  */
+ 
++#define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ 
+ #define MODULE_NAME _XOR
diff --git a/pycrypto-python3.11.patch b/pycrypto-python3.11.patch
new file mode 100644
index 0000000..ff1a67b
--- /dev/null
+++ b/pycrypto-python3.11.patch
@@ -0,0 +1,12 @@
+--- a/src/_fastmath.c
++++ b/src/_fastmath.c
+@@ -30,7 +30,9 @@
+ #include <string.h>
+ #include "Python.h"
+ #include "pycrypto_compat.h"
++#if PY_VERSION_HEX < 0x030B0000
+ #include <longintrepr.h>				/* for conversions */
++#endif
+ #include "config.h"
+ #if HAVE_LIBGMP
+ # include <gmp.h>
diff --git a/pycrypto-python3.12.patch b/pycrypto-python3.12.patch
new file mode 100644
index 0000000..631741d
--- /dev/null
+++ b/pycrypto-python3.12.patch
@@ -0,0 +1,95 @@
+--- a/src/_fastmath.c
++++ b/src/_fastmath.c
+@@ -58,6 +58,20 @@
+ #define INLINE inline
+ #endif
+ 
++#if PY_VERSION_HEX >= 0x030C0000
++/* Code cribbed from python's internal/pycore_long.h */
++/* Long value tag bits:
++ *  * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
++ *   * 2: Reserved for immortality bit
++ *    * 3+ Unsigned digit count
++ *     */
++#define SIGN_MASK 3
++#define SIGN_ZERO 1
++#define SIGN_NEGATIVE 2
++#define NON_SIZE_BITS 3
++#define TAG_FROM_SIGN_AND_SIZE(sign, size) ((1 - (sign)) | ((size) << NON_SIZE_BITS))
++#endif
++
+ static unsigned int sieve_base[10000];
+ static int rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc);
+ 
+@@ -70,13 +84,24 @@ longObjToMPZ (mpz_t m, PyLongObject * p)
+ 	mpz_init (temp);
+ 	mpz_init (temp2);
+ #ifdef IS_PY3K
+-	if (p->ob_base.ob_size > 0) {
+-		size = p->ob_base.ob_size;
++#if PY_VERSION_HEX < 0x030C0000
++	if (Py_SIZE(p) > 0) {
++		size = Py_SIZE(p);
+ 		negative = 1;
+ 	} else {
+-		size = -p->ob_base.ob_size;
++		size = -Py_SIZE(p);
++		negative = -1;
++	}
++#else
++	size = p->long_value.lv_tag >> NON_SIZE_BITS;
++	if ((p->long_value.lv_tag & SIGN_MASK) == SIGN_NEGATIVE) {
+ 		negative = -1;
++	} else if ((p->long_value.lv_tag & SIGN_MASK) == SIGN_ZERO) {
++		negative = 0;
++	} else {
++		negative = 1;
+ 	}
++#endif
+ #else
+ 	if (p->ob_size > 0) {
+ 		size = p->ob_size;
+@@ -89,7 +114,11 @@ longObjToMPZ (mpz_t m, PyLongObject * p)
+ 	mpz_set_ui (m, 0);
+ 	for (i = 0; i < size; i++)
+ 	{
++#if PY_VERSION_HEX < 0x030C0000
+ 		mpz_set_ui (temp, p->ob_digit[i]);
++#else
++		mpz_set_ui (temp, p->long_value.ob_digit[i]);
++#endif
+ #ifdef IS_PY3K
+ 		mpz_mul_2exp (temp2, temp, PyLong_SHIFT * i);
+ #else
+@@ -123,7 +152,11 @@ mpzToLongObj (mpz_t m)
+ 	for (i = 0; i < size; i++)
+ 	{
+ #ifdef IS_PY3K
++#if PY_VERSION_HEX < 0x030C0000
+ 		l->ob_digit[i] = (digit) (mpz_get_ui (temp) & PyLong_MASK);
++#else
++		l->long_value.ob_digit[i] = (digit) (mpz_get_ui (temp) & PyLong_MASK);
++#endif
+ 		mpz_fdiv_q_2exp (temp, temp, PyLong_SHIFT);
+ #else
+ 		l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
+@@ -131,11 +164,19 @@ mpzToLongObj (mpz_t m)
+ #endif
+ 	}
+ 	i = size;
++#if PY_VERSION_HEX < 0x030C0000
+ 	while ((i > 0) && (l->ob_digit[i - 1] == 0))
++#else
++	while ((i > 0) && (l->long_value.ob_digit[i - 1] == 0))
++#endif
+ 		i--;
+ #ifdef IS_PY3K
++#if PY_VERSION_HEX < 0x030C0000
+ 	l->ob_base.ob_size = i * sgn;
+ #else
++	l->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sgn, (size_t)i);
++#endif
++#else
+ 	l->ob_size = i * sgn;
+ #endif
+ 	mpz_clear (temp);
diff --git a/pycrypto-unbundle-libtomcrypt.patch b/pycrypto-unbundle-libtomcrypt.patch
new file mode 100644
index 0000000..52e0700
--- /dev/null
+++ b/pycrypto-unbundle-libtomcrypt.patch
@@ -0,0 +1,30 @@
+--- a/setup.py
++++ b/setup.py
+@@ -390,10 +390,12 @@ kw = {'name':"pycrypto",
+                       include_dirs=['src/'],
+                       sources=["src/CAST.c"]),
+             Extension("Crypto.Cipher._DES",
+-                      include_dirs=['src/', 'src/libtom/'],
++                      include_dirs=['src/'],
++                      libraries=['tomcrypt'],
+                       sources=["src/DES.c"]),
+             Extension("Crypto.Cipher._DES3",
+-                      include_dirs=['src/', 'src/libtom/'],
++                      include_dirs=['src/'],
++                      libraries=['tomcrypt'],
+                       sources=["src/DES3.c"]),
+ 
+             # Stream ciphers
+--- a/src/DES.c
++++ b/src/DES.c
+@@ -28,8 +28,8 @@
+  * assert-like LTC_ARGCHK macro fails. */
+ #define ARGTYPE 4
+ 
+-/* Include the actial DES implementation */
+-#include "libtom/tomcrypt_des.c"
++/* Access the actual DES implementation */
++#include "tomcrypt.h"
+ 
+ #undef DES  /* this is needed because tomcrypt_custom.h defines DES to an empty string */
+ 
diff --git a/pycrypto-use-os-random.patch b/pycrypto-use-os-random.patch
new file mode 100644
index 0000000..08d115e
--- /dev/null
+++ b/pycrypto-use-os-random.patch
@@ -0,0 +1,1790 @@
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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__':
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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:
+--- 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
+--- 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:
+--- 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:
+--- 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)
+--- 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 */
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/python-Crypto.git/commitdiff/9e4d51f38787b0da1eee1f513644f76d6cce6227



More information about the pld-cvs-commit mailing list