[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