commit 7cd4162bf163d904e72c69bfd545f1b179c971db Author: tigro Date: Wed Oct 4 12:40:27 2023 +0300 import python-crypto-2.6.1-42.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e7fe54 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/pycrypto-2.6.1.tar.gz diff --git a/.python-crypto.metadata b/.python-crypto.metadata new file mode 100644 index 0000000..3c3dd83 --- /dev/null +++ b/.python-crypto.metadata @@ -0,0 +1 @@ +aeda3ed41caf1766409d4efc689b9ca30ad6aeb2 SOURCES/pycrypto-2.6.1.tar.gz diff --git a/SOURCES/pycrypto-2.6.1-CVE-2013-7459.patch b/SOURCES/pycrypto-2.6.1-CVE-2013-7459.patch new file mode 100644 index 0000000..db1f740 --- /dev/null +++ b/SOURCES/pycrypto-2.6.1-CVE-2013-7459.patch @@ -0,0 +1,106 @@ +From 8dbe0dc3eea5c689d4f76b37b93fe216cf1f00d4 Mon Sep 17 00:00:00 2001 +From: Legrandin +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 +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/SOURCES/pycrypto-2.6.1-CVE-2018-6594.patch b/SOURCES/pycrypto-2.6.1-CVE-2018-6594.patch new file mode 100644 index 0000000..22c3719 --- /dev/null +++ b/SOURCES/pycrypto-2.6.1-CVE-2018-6594.patch @@ -0,0 +1,51 @@ +--- lib/Crypto/PublicKey/ElGamal.py ++++ 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/SOURCES/pycrypto-2.6.1-drop-py2.1-support.patch b/SOURCES/pycrypto-2.6.1-drop-py2.1-support.patch new file mode 100644 index 0000000..682a2aa --- /dev/null +++ b/SOURCES/pycrypto-2.6.1-drop-py2.1-support.patch @@ -0,0 +1,296 @@ +--- lib/Crypto/Cipher/blockalgo.py ++++ 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)*. +--- lib/Crypto/PublicKey/DSA.py ++++ 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 +--- lib/Crypto/PublicKey/RSA.py ++++ 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 +--- lib/Crypto/PublicKey/_slowmath.py ++++ 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): +--- lib/Crypto/Random/Fortuna/FortunaAccumulator.py ++++ 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 +--- lib/Crypto/Random/Fortuna/FortunaGenerator.py ++++ 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 +--- lib/Crypto/Random/Fortuna/SHAd256.py ++++ 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 +--- lib/Crypto/Random/random.py ++++ 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): +--- lib/Crypto/SelfTest/PublicKey/test_DSA.py ++++ 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 +--- lib/Crypto/SelfTest/PublicKey/test_RSA.py ++++ 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 +--- lib/Crypto/SelfTest/Random/Fortuna/test_FortunaAccumulator.py ++++ 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 +--- lib/Crypto/SelfTest/Random/Fortuna/test_FortunaGenerator.py ++++ 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 +--- lib/Crypto/SelfTest/Random/test_random.py ++++ 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): +--- lib/Crypto/SelfTest/st_common.py ++++ 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): +--- lib/Crypto/SelfTest/Util/test_Counter.py ++++ 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 +--- lib/Crypto/SelfTest/Util/test_number.py ++++ 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 + +--- lib/Crypto/Signature/PKCS1_PSS.py ++++ 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 +--- lib/Crypto/Util/Counter.py ++++ 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 +--- lib/Crypto/Util/_number_new.py ++++ 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. +--- 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 +-# +-# =================================================================== +-# 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/SOURCES/pycrypto-2.6.1-unbundle-libtomcrypt.patch b/SOURCES/pycrypto-2.6.1-unbundle-libtomcrypt.patch new file mode 100644 index 0000000..00c7676 --- /dev/null +++ b/SOURCES/pycrypto-2.6.1-unbundle-libtomcrypt.patch @@ -0,0 +1,30 @@ +--- setup.py ++++ 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 +--- src/DES.c ++++ 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/SOURCES/pycrypto-2.6.1-use-os-random.patch b/SOURCES/pycrypto-2.6.1-use-os-random.patch new file mode 100644 index 0000000..c7a4e24 --- /dev/null +++ b/SOURCES/pycrypto-2.6.1-use-os-random.patch @@ -0,0 +1,1790 @@ +--- lib/Crypto/Random/__init__.py ++++ lib/Crypto/Random/__init__.py +@@ -2,8 +2,6 @@ + # + # Random/__init__.py : PyCrypto random number generation + # +-# Written in 2008 by Dwayne C. Litzenberger +-# + # =================================================================== + # 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: +--- 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 +-# +-# =================================================================== +-# 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 = "" +- +- 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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 = "" +- +- 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- lib/Crypto/SelfTest/Random/__init__.py ++++ 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__': +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- lib/Crypto/SelfTest/Util/__init__.py ++++ 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 +--- 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 +-# +-# =================================================================== +-# 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: +--- 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 +-# +-# =================================================================== +-# 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: +--- setup.py ++++ 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) +--- 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 +-#include +- +-#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@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 +-). +- +-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 */ diff --git a/SOURCES/python-crypto-2.4-fix-pubkey-size-divisions.patch b/SOURCES/python-crypto-2.4-fix-pubkey-size-divisions.patch new file mode 100644 index 0000000..9f3323b --- /dev/null +++ b/SOURCES/python-crypto-2.4-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 + 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/SOURCES/python-crypto-2.4-optflags.patch b/SOURCES/python-crypto-2.4-optflags.patch new file mode 100644 index 0000000..c0f57ce --- /dev/null +++ b/SOURCES/python-crypto-2.4-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/SOURCES/python-crypto-2.6.1-SyntaxWarning.patch b/SOURCES/python-crypto-2.6.1-SyntaxWarning.patch new file mode 100644 index 0000000..6adaeec --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-SyntaxWarning.patch @@ -0,0 +1,11 @@ +--- lib/Crypto/SelfTest/Random/test_random.py ++++ 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/SOURCES/python-crypto-2.6.1-link.patch b/SOURCES/python-crypto-2.6.1-link.patch new file mode 100644 index 0000000..7fe65b5 --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-link.patch @@ -0,0 +1,13 @@ +log() function not available in libgmp, need libm too + +--- setup.py ++++ 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/SOURCES/python-crypto-2.6.1-no-distutils.patch b/SOURCES/python-crypto-2.6.1-no-distutils.patch new file mode 100644 index 0000000..1d1f6c3 --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-no-distutils.patch @@ -0,0 +1,78 @@ +--- lib/Crypto/SelfTest/PublicKey/test_DSA.py ++++ 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()))) +--- lib/Crypto/SelfTest/PublicKey/test_RSA.py ++++ 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()))) +--- lib/Crypto/Util/number.py ++++ 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()))) +--- setup.py ++++ setup.py +@@ -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 + +@@ -53,8 +52,7 @@ if sys.version[0:1] != '3': + # .gcov files + USE_GCOV = 0 + +- +-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 +@@ -385,7 +383,7 @@ kw = {'name':"pycrypto", + ] + } + +-core.setup(**kw) ++setup(**kw) + + def touch(path): + import os, time diff --git a/SOURCES/python-crypto-2.6.1-python3.10.patch b/SOURCES/python-crypto-2.6.1-python3.10.patch new file mode 100644 index 0000000..a655c94 --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-python3.10.patch @@ -0,0 +1,289 @@ +--- src/AES.c ++++ src/AES.c +@@ -26,6 +26,7 @@ + + #include + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + #define MODULE_NAME _AES +--- src/ARC2.c ++++ src/ARC2.c +@@ -42,6 +42,7 @@ + */ + + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + #define MODULE_NAME _ARC2 +--- src/block_template.c ++++ src/block_template.c +@@ -33,6 +33,7 @@ + #include + #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, +--- src/Blowfish.c ++++ src/Blowfish.c +@@ -36,6 +36,7 @@ + #endif + #include + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + #include "Blowfish-tables.h" +--- src/CAST.c ++++ src/CAST.c +@@ -42,6 +42,7 @@ + + */ + ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + #define MODULE_NAME _CAST +--- src/DES.c ++++ src/DES.c +@@ -34,6 +34,7 @@ + #undef DES /* this is needed because tomcrypt_custom.h defines DES to an empty string */ + + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + typedef struct { +--- src/hash_template.c ++++ src/hash_template.c +@@ -30,6 +30,7 @@ + #ifdef _HAVE_STDC_HEADERS + #include + #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; +--- src/MD2.c ++++ src/MD2.c +@@ -28,6 +28,7 @@ + + + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + #include "pycrypto_compat.h" + +--- src/MD4.c ++++ src/MD4.c +@@ -28,6 +28,7 @@ + + + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + #include "pycrypto_compat.h" + +--- src/RIPEMD160.c ++++ src/RIPEMD160.c +@@ -54,6 +54,7 @@ + + #include + #include ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + #include "pycrypto_compat.h" + +--- src/stream_template.c ++++ src/stream_template.c +@@ -33,6 +33,7 @@ + #include + #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); +--- src/XOR.c ++++ src/XOR.c +@@ -24,6 +24,7 @@ + * ======================================================================= + */ + ++#define PY_SSIZE_T_CLEAN + #include "Python.h" + + #define MODULE_NAME _XOR diff --git a/SOURCES/python-crypto-2.6.1-python3.11.patch b/SOURCES/python-crypto-2.6.1-python3.11.patch new file mode 100644 index 0000000..c52b1f7 --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-python3.11.patch @@ -0,0 +1,10 @@ +--- src/_fastmath.c ++++ src/_fastmath.c +@@ -30,7 +30,6 @@ + #include + #include "Python.h" + #include "pycrypto_compat.h" +-#include /* for conversions */ + #include "config.h" + #if HAVE_LIBGMP + # include diff --git a/SOURCES/python-crypto-2.6.1-python3only.patch b/SOURCES/python-crypto-2.6.1-python3only.patch new file mode 100644 index 0000000..730ca99 --- /dev/null +++ b/SOURCES/python-crypto-2.6.1-python3only.patch @@ -0,0 +1,2279 @@ +--- lib/Crypto/Cipher/ARC2.py ++++ lib/Crypto/Cipher/ARC2.py +@@ -126,5 +126,5 @@ MODE_OPENPGP = 7 + #: Size of a data block (in bytes) + block_size = 8 + #: Size of a key (in bytes) +-key_size = xrange(1,16+1) ++key_size = range(1,16+1) + +--- lib/Crypto/Cipher/ARC4.py ++++ lib/Crypto/Cipher/ARC4.py +@@ -116,5 +116,5 @@ def new(key, *args, **kwargs): + #: Size of a data block (in bytes) + block_size = 1 + #: Size of a key (in bytes) +-key_size = xrange(1,256+1) ++key_size = range(1,256+1) + +--- lib/Crypto/Cipher/Blowfish.py ++++ lib/Crypto/Cipher/Blowfish.py +@@ -117,5 +117,5 @@ MODE_OPENPGP = 7 + #: Size of a data block (in bytes) + block_size = 8 + #: Size of a key (in bytes) +-key_size = xrange(4,56+1) ++key_size = range(4,56+1) + +--- lib/Crypto/Cipher/CAST.py ++++ lib/Crypto/Cipher/CAST.py +@@ -120,4 +120,4 @@ MODE_OPENPGP = 7 + #: Size of a data block (in bytes) + block_size = 8 + #: Size of a key (in bytes) +-key_size = xrange(5,16+1) ++key_size = range(5,16+1) +--- lib/Crypto/Cipher/PKCS1_OAEP.py ++++ lib/Crypto/Cipher/PKCS1_OAEP.py +@@ -49,7 +49,7 @@ the RSA key: + .. __: http://www.rsa.com/rsalabs/node.asp?id=2125. + """ + +-from __future__ import nested_scopes ++ + + __revision__ = "$Id$" + __all__ = [ 'new', 'PKCS1OAEP_Cipher' ] +--- lib/Crypto/Cipher/PKCS1_v1_5.py ++++ lib/Crypto/Cipher/PKCS1_v1_5.py +@@ -132,7 +132,7 @@ class PKCS115_Cipher: + def __call__(self, c): + while bord(c)==0x00: c=self.rf(1)[0] + return c +- ps = tobytes(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3))) ++ ps = tobytes(list(map(nonZeroRandByte(randFunc), randFunc(k-mLen-3)))) + # Step 2b + em = b('\x00\x02') + ps + bchr(0x00) + message + # Step 3a (OS2IP), step 3b (RSAEP), part of step 3c (I2OSP) +--- lib/Crypto/Cipher/XOR.py ++++ lib/Crypto/Cipher/XOR.py +@@ -82,5 +82,5 @@ def new(key, *args, **kwargs): + #: Size of a data block (in bytes) + block_size = 1 + #: Size of a key (in bytes) +-key_size = xrange(1,32+1) ++key_size = range(1,32+1) + +--- lib/Crypto/Hash/HMAC.py ++++ lib/Crypto/Hash/HMAC.py +@@ -98,7 +98,7 @@ class HMAC: + A hash module or object instantiated from `Crypto.Hash` + """ + if digestmod is None: +- import MD5 ++ from . import MD5 + digestmod = MD5 + + self.digestmod = digestmod +--- lib/Crypto/Protocol/AllOrNothing.py ++++ lib/Crypto/Protocol/AllOrNothing.py +@@ -48,6 +48,7 @@ import operator + import sys + from Crypto.Util.number import bytes_to_long, long_to_bytes + from Crypto.Util.py3compat import * ++from functools import reduce + + def isInt(x): + test = 0 +@@ -186,11 +187,11 @@ class AllOrNothing: + # better have at least 2 blocks, for the padbytes package and the hash + # block accumulator + if len(blocks) < 2: +- raise ValueError, "List must be at least length 2." ++ raise ValueError("List must be at least length 2.") + + # blocks is a list of strings. We need to deal with them as long + # integers +- blocks = map(bytes_to_long, blocks) ++ blocks = list(map(bytes_to_long, blocks)) + + # Calculate the well-known key, to which the hash blocks are + # encrypted, and create the hash cipher. +@@ -271,15 +272,15 @@ Where: + + def usage(code, msg=None): + if msg: +- print msg +- print usagemsg % {'program': sys.argv[0], +- 'ciphermodule': ciphermodule} ++ print(msg) ++ print(usagemsg % {'program': sys.argv[0], ++ 'ciphermodule': ciphermodule}) + sys.exit(code) + + try: + opts, args = getopt.getopt(sys.argv[1:], + 'c:l', ['cipher=', 'aslong']) +- except getopt.error, msg: ++ except getopt.error as msg: + usage(1, msg) + + if args: +@@ -297,23 +298,23 @@ Where: + module = __import__('Crypto.Cipher.'+ciphermodule, None, None, ['new']) + + x = AllOrNothing(module) +- print 'Original text:\n==========' +- print __doc__ +- print '==========' ++ print('Original text:\n==========') ++ print(__doc__) ++ print('==========') + msgblocks = x.digest(b(__doc__)) +- print 'message blocks:' +- for i, blk in zip(range(len(msgblocks)), msgblocks): ++ print('message blocks:') ++ for i, blk in zip(list(range(len(msgblocks))), msgblocks): + # base64 adds a trailing newline +- print ' %3d' % i, ++ print(' %3d' % i, end=' ') + if aslong: +- print bytes_to_long(blk) ++ print(bytes_to_long(blk)) + else: +- print base64.encodestring(blk)[:-1] ++ print(base64.encodestring(blk)[:-1]) + # + # get a new undigest-only object so there's no leakage + y = AllOrNothing(module) + text = y.undigest(msgblocks) + if text == b(__doc__): +- print 'They match!' ++ print('They match!') + else: +- print 'They differ!' ++ print('They differ!') +--- lib/Crypto/Protocol/Chaffing.py ++++ lib/Crypto/Protocol/Chaffing.py +@@ -106,9 +106,9 @@ class Chaff: + """ + + if not (0.0<=factor<=1.0): +- raise ValueError, "'factor' must be between 0.0 and 1.0" ++ raise ValueError("'factor' must be between 0.0 and 1.0") + if blocksper < 0: +- raise ValueError, "'blocksper' must be zero or more" ++ raise ValueError("'blocksper' must be zero or more") + + self.__factor = factor + self.__blocksper = blocksper +@@ -139,8 +139,8 @@ class Chaff: + # number of chaff blocks to add per message block that is being + # chaffed. + count = len(blocks) * self.__factor +- blocksper = range(self.__blocksper) +- for i, wheat in zip(range(len(blocks)), blocks): ++ blocksper = list(range(self.__blocksper)) ++ for i, wheat in zip(list(range(len(blocks))), blocks): + # it shouldn't matter which of the n blocks we add chaff to, so for + # ease of implementation, we'll just add them to the first count + # blocks +@@ -185,9 +185,9 @@ abolish it, and to institute new Governm + principles and organizing its powers in such form, as to them shall seem most + likely to effect their Safety and Happiness. + """ +- print 'Original text:\n==========' +- print text +- print '==========' ++ print('Original text:\n==========') ++ print(text) ++ print('==========') + + # first transform the text into packets + blocks = [] ; size = 40 +@@ -195,7 +195,7 @@ likely to effect their Safety and Happin + blocks.append( text[i:i+size] ) + + # now get MACs for all the text blocks. The key is obvious... +- print 'Calculating MACs...' ++ print('Calculating MACs...') + from Crypto.Hash import HMAC, SHA + key = 'Jefferson' + macs = [HMAC.new(key, block, digestmod=SHA).digest() +@@ -205,13 +205,13 @@ likely to effect their Safety and Happin + + # put these into a form acceptable as input to the chaffing procedure + source = [] +- m = zip(range(len(blocks)), blocks, macs) +- print m ++ m = list(zip(list(range(len(blocks))), blocks, macs)) ++ print(m) + for i, data, mac in m: + source.append((i, data, mac)) + + # now chaff these +- print 'Adding chaff...' ++ print('Adding chaff...') + c = Chaff(factor=0.5, blocksper=2) + chaffed = c.chaff(source) + +@@ -221,7 +221,7 @@ likely to effect their Safety and Happin + # the chaff + + wheat = [] +- print 'chaffed message blocks:' ++ print('chaffed message blocks:') + for i, data, mac in chaffed: + # do the authentication + h = HMAC.new(key, data, digestmod=SHA) +@@ -232,14 +232,14 @@ likely to effect their Safety and Happin + else: + tag = ' ' + # base64 adds a trailing newline +- print tag, '%3d' % i, \ +- repr(data), encodestring(mac)[:-1] ++ print(tag, '%3d' % i, \ ++ repr(data), encodestring(mac)[:-1]) + + # now decode the message packets and check it against the original text +- print 'Undigesting wheat...' ++ print('Undigesting wheat...') + # PY3K: This is meant to be text, do not change to bytes (data) + newtext = "".join(wheat) + if newtext == text: +- print 'They match!' ++ print('They match!') + else: +- print 'They differ!' ++ print('They differ!') +--- lib/Crypto/Protocol/KDF.py ++++ lib/Crypto/Protocol/KDF.py +@@ -79,7 +79,7 @@ def PBKDF1(password, salt, dkLen, count= + raise ValueError("Selected hash algorithm has a too short digest (%d bytes)." % digest) + if len(salt)!=8: + raise ValueError("Salt is not 8 bytes long.") +- for i in xrange(count-1): ++ for i in range(count-1): + pHash = pHash.new(pHash.digest()) + return pHash.digest()[:dkLen] + +@@ -114,7 +114,7 @@ def PBKDF2(password, salt, dkLen=16, cou + i = 1 + while len(key)I", i)) +- for j in xrange(count-1): ++ for j in range(count-1): + previousU = t = prf(password,previousU) + U = strxor(U,t) + key += U +--- lib/Crypto/PublicKey/_DSA.py ++++ lib/Crypto/PublicKey/_DSA.py +@@ -50,7 +50,7 @@ def generateQ(randfunc): + q=q*256+c + while (not isPrime(q)): + q=q+2 +- if pow(2,159L) < q < pow(2,160L): ++ if pow(2,159) < q < pow(2,160): + return S, q + raise RuntimeError('Bad q value generated') + +@@ -80,7 +80,7 @@ def generate_py(bits, randfunc, progress + V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest()) + W=V[n] % powb + for k in range(n-1, -1, -1): +- W=(W<<160L)+V[k] ++ W=(W<<160)+V[k] + X=W+powL1 + p=X-(X%(2*obj.q)-1) + if powL1<=p and isPrime(p): +--- lib/Crypto/PublicKey/DSA.py ++++ lib/Crypto/PublicKey/DSA.py +@@ -217,7 +217,7 @@ class _DSAobj(pubkey.pubkey): + self.implementation = DSAImplementation() + t = [] + for k in self.keydata: +- if not d.has_key(k): ++ if k not in d: + break + t.append(d[k]) + self.key = self.implementation._math.dsa_construct(*tuple(t)) +--- lib/Crypto/PublicKey/pubkey.py ++++ lib/Crypto/PublicKey/pubkey.py +@@ -45,7 +45,7 @@ class pubkey: + restoration.""" + d=self.__dict__ + for key in self.keydata: +- if d.has_key(key): d[key]=long(d[key]) ++ if key in d: d[key]=int(d[key]) + return d + + def __setstate__(self, d): +@@ -53,7 +53,7 @@ class pubkey: + number representation being used, whether that is Python long + integers, MPZ objects, or whatever.""" + for key in self.keydata: +- if d.has_key(key): self.__dict__[key]=bignum(d[key]) ++ if key in d: self.__dict__[key]=bignum(d[key]) + + def encrypt(self, plaintext, K): + """Encrypt a piece of data. +@@ -68,9 +68,9 @@ integers, MPZ objects, or whatever.""" + plaintext (string or long). + """ + wasString=0 +- if isinstance(plaintext, types.StringType): ++ if isinstance(plaintext, bytes): + plaintext=bytes_to_long(plaintext) ; wasString=1 +- if isinstance(K, types.StringType): ++ if isinstance(K, bytes): + K=bytes_to_long(K) + ciphertext=self._encrypt(plaintext, K) + if wasString: return tuple(map(long_to_bytes, ciphertext)) +@@ -86,9 +86,9 @@ integers, MPZ objects, or whatever.""" + of byte strings. A long otherwise. + """ + wasString=0 +- if not isinstance(ciphertext, types.TupleType): ++ if not isinstance(ciphertext, tuple): + ciphertext=(ciphertext,) +- if isinstance(ciphertext[0], types.StringType): ++ if isinstance(ciphertext[0], bytes): + ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1 + plaintext=self._decrypt(ciphertext) + if wasString: return long_to_bytes(plaintext) +@@ -107,8 +107,8 @@ integers, MPZ objects, or whatever.""" + """ + if (not self.has_private()): + raise TypeError('Private key not available in this object') +- if isinstance(M, types.StringType): M=bytes_to_long(M) +- if isinstance(K, types.StringType): K=bytes_to_long(K) ++ if isinstance(M, bytes): M=bytes_to_long(M) ++ if isinstance(K, bytes): K=bytes_to_long(K) + return self._sign(M, K) + + def verify (self, M, signature): +@@ -122,7 +122,7 @@ integers, MPZ objects, or whatever.""" + + :Return: True if the signature is correct, False otherwise. + """ +- if isinstance(M, types.StringType): M=bytes_to_long(M) ++ if isinstance(M, bytes): M=bytes_to_long(M) + return self._verify(M, signature) + + # alias to compensate for the old validate() name +@@ -142,9 +142,9 @@ integers, MPZ objects, or whatever.""" + :Return: A byte string if M was so. A long otherwise. + """ + wasString=0 +- if isinstance(M, types.StringType): ++ if isinstance(M, bytes): + M=bytes_to_long(M) ; wasString=1 +- if isinstance(B, types.StringType): B=bytes_to_long(B) ++ if isinstance(B, bytes): B=bytes_to_long(B) + blindedmessage=self._blind(M, B) + if wasString: return long_to_bytes(blindedmessage) + else: return blindedmessage +@@ -159,9 +159,9 @@ integers, MPZ objects, or whatever.""" + :Type B: byte string or long + """ + wasString=0 +- if isinstance(M, types.StringType): ++ if isinstance(M, bytes): + M=bytes_to_long(M) ; wasString=1 +- if isinstance(B, types.StringType): B=bytes_to_long(B) ++ if isinstance(B, bytes): B=bytes_to_long(B) + unblindedmessage=self._unblind(M, B) + if wasString: return long_to_bytes(unblindedmessage) + else: return unblindedmessage +--- lib/Crypto/PublicKey/_RSA.py ++++ lib/Crypto/PublicKey/_RSA.py +@@ -37,12 +37,12 @@ def generate_py(bits, randfunc, progress + if present, to display the progress of the key generation. + """ + obj=RSAobj() +- obj.e = long(e) ++ obj.e = int(e) + + # Generate the prime factors of n + if progress_func: + progress_func('p,q\n') +- p = q = 1L ++ p = q = 1 + while number.size(p*q) < bits: + # Note that q might be one bit longer than p if somebody specifies an odd + # number of bits for the key. (Why would anyone do that? You don't get +--- lib/Crypto/PublicKey/RSA.py ++++ lib/Crypto/PublicKey/RSA.py +@@ -286,7 +286,7 @@ class _RSAobj(pubkey.pubkey): + self.implementation = RSAImplementation() + t = [] + for k in self.keydata: +- if not d.has_key(k): ++ if k not in d: + break + t.append(d[k]) + self.key = self.implementation._math.rsa_construct(*tuple(t)) +@@ -580,7 +580,7 @@ class RSAImplementation(object): + if privateKey.isType('OCTET STRING'): + return self._importKeyDER(privateKey.payload) + +- except ValueError, IndexError: ++ except ValueError as IndexError: + pass + + raise ValueError("RSA key format is not supported") +--- lib/Crypto/PublicKey/_slowmath.py ++++ lib/Crypto/PublicKey/_slowmath.py +@@ -79,12 +79,12 @@ class _RSAKey(object): + + def rsa_construct(n, e, d=None, p=None, q=None, u=None): + """Construct an RSAKey object""" +- assert isinstance(n, long) +- assert isinstance(e, long) +- assert isinstance(d, (long, type(None))) +- assert isinstance(p, (long, type(None))) +- assert isinstance(q, (long, type(None))) +- assert isinstance(u, (long, type(None))) ++ assert isinstance(n, int) ++ assert isinstance(e, int) ++ assert isinstance(d, (int, type(None))) ++ assert isinstance(p, (int, type(None))) ++ assert isinstance(q, (int, type(None))) ++ assert isinstance(u, (int, type(None))) + obj = _RSAKey() + obj.n = n + obj.e = e +@@ -149,7 +149,7 @@ class _DSAKey(object): + # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because that's the API. + if not self.has_private(): + raise TypeError("No private key") +- if not (1L < k < self.q): ++ if not (1 < k < self.q): + raise ValueError("k is not between 2 and q-1") + inv_k = inverse(k, self.q) # Compute k**-1 mod q + r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q +@@ -167,11 +167,11 @@ class _DSAKey(object): + return v == r + + def dsa_construct(y, g, p, q, x=None): +- assert isinstance(y, long) +- assert isinstance(g, long) +- assert isinstance(p, long) +- assert isinstance(q, long) +- assert isinstance(x, (long, type(None))) ++ assert isinstance(y, int) ++ assert isinstance(g, int) ++ assert isinstance(p, int) ++ assert isinstance(q, int) ++ assert isinstance(x, (int, type(None))) + obj = _DSAKey() + obj.y = y + obj.g = g +--- lib/Crypto/Random/Fortuna/FortunaAccumulator.py ++++ lib/Crypto/Random/Fortuna/FortunaAccumulator.py +@@ -32,9 +32,9 @@ import time + import warnings + + from Crypto.pct_warnings import ClockRewindWarning +-import SHAd256 ++from . import SHAd256 + +-import FortunaGenerator ++from . import FortunaGenerator + + class FortunaPool(object): + """Fortuna pool type +@@ -87,7 +87,7 @@ def which_pools(r): + retval.append(i) + else: + break # optimization. once this fails, it always fails +- mask = (mask << 1) | 1L ++ mask = (mask << 1) | 1 + return retval + + class FortunaAccumulator(object): +--- lib/Crypto/Random/Fortuna/FortunaGenerator.py ++++ lib/Crypto/Random/Fortuna/FortunaGenerator.py +@@ -33,7 +33,7 @@ from Crypto.Util.number import ceil_shif + from Crypto.Util import Counter + from Crypto.Cipher import AES + +-import SHAd256 ++from . import SHAd256 + + class AESGenerator(object): + """The Fortuna "generator" +@@ -88,7 +88,7 @@ class AESGenerator(object): + remainder = bytes & ((1<<20)-1) + + retval = [] +- for i in xrange(num_full_blocks): ++ for i in range(num_full_blocks): + retval.append(self._pseudo_random_data(1<<20)) + retval.append(self._pseudo_random_data(remainder)) + +@@ -121,7 +121,7 @@ class AESGenerator(object): + raise AssertionError("generator must be seeded before use") + assert 0 <= num_blocks <= self.max_blocks_per_request + retval = [] +- for i in xrange(num_blocks >> 12): # xrange(num_blocks / 4096) ++ for i in range(num_blocks >> 12): # xrange(num_blocks / 4096) + retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros)) + remaining_bytes = (num_blocks & 4095) << self.block_size_shift # (num_blocks % 4095) * self.block_size + retval.append(self._cipher.encrypt(self._four_kiblocks_of_zeros[:remaining_bytes])) +--- lib/Crypto/Random/random.py ++++ lib/Crypto/Random/random.py +@@ -45,7 +45,7 @@ class StrongRandom(object): + """Return a python long integer with k random bits.""" + if self._randfunc is None: + self._randfunc = Random.new().read +- mask = (1L << k) - 1 ++ mask = (1 << k) - 1 + return mask & bytes_to_long(self._randfunc(ceil_div(k, 8))) + + def randrange(self, *args): +@@ -62,9 +62,9 @@ class StrongRandom(object): + step = 1 + else: + raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),)) +- if (not isinstance(start, (int, long)) +- or not isinstance(stop, (int, long)) +- or not isinstance(step, (int, long))): ++ if (not isinstance(start, int) ++ or not isinstance(stop, int) ++ or not isinstance(step, int)): + raise TypeError("randrange requires integer arguments") + if step == 0: + raise ValueError("randrange step argument must not be zero") +@@ -84,7 +84,7 @@ class StrongRandom(object): + + def randint(self, a, b): + """Return a random integer N such that a <= N <= b.""" +- if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): ++ if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("randint requires integer arguments") + N = self.randrange(a, b+1) + assert a <= N <= b +@@ -106,7 +106,7 @@ class StrongRandom(object): + + # Choose a random item (without replacement) until all the items have been + # chosen. +- for i in xrange(len(x)): ++ for i in range(len(x)): + x[i] = items.pop(self.randrange(len(items))) + + def sample(self, population, k): +@@ -118,9 +118,9 @@ class StrongRandom(object): + + retval = [] + selected = {} # we emulate a set using a dict here +- for i in xrange(k): ++ for i in range(k): + r = None +- while r is None or selected.has_key(r): ++ while r is None or r in selected: + r = self.randrange(num_choices) + retval.append(population[r]) + selected[r] = 1 +--- lib/Crypto/SelfTest/Cipher/common.py ++++ lib/Crypto/SelfTest/Cipher/common.py +@@ -97,9 +97,9 @@ class CipherSelfTest(unittest.TestCase): + from Crypto.Util import Counter + ctr_class = _extract(params, 'ctr_class', Counter.new) + ctr_params = _extract(params, 'ctr_params', {}).copy() +- if ctr_params.has_key('prefix'): ctr_params['prefix'] = a2b_hex(b(ctr_params['prefix'])) +- if ctr_params.has_key('suffix'): ctr_params['suffix'] = a2b_hex(b(ctr_params['suffix'])) +- if not ctr_params.has_key('nbits'): ++ if 'prefix' in ctr_params: ctr_params['prefix'] = a2b_hex(b(ctr_params['prefix'])) ++ if 'suffix' in ctr_params: ctr_params['suffix'] = a2b_hex(b(ctr_params['suffix'])) ++ if 'nbits' not in ctr_params: + ctr_params['nbits'] = 8*(self.module.block_size - len(ctr_params.get('prefix', '')) - len(ctr_params.get('suffix', ''))) + params['counter'] = ctr_class(**ctr_params) + +@@ -202,7 +202,7 @@ class CTRWraparoundTest(unittest.TestCas + + for disable_shortcut in (0, 1): # (False, True) Test CTR-mode shortcut and PyObject_CallObject code paths + for little_endian in (0, 1): # (False, True) Test both endiannesses +- ctr = Counter.new(8*self.module.block_size, initial_value=2L**(8*self.module.block_size)-1, little_endian=little_endian, disable_shortcut=disable_shortcut) ++ ctr = Counter.new(8*self.module.block_size, initial_value=2**(8*self.module.block_size)-1, little_endian=little_endian, disable_shortcut=disable_shortcut) + cipher = self.module.new(a2b_hex(self.key), self.module.MODE_CTR, counter=ctr) + block = b("\x00") * self.module.block_size + cipher.encrypt(block) +@@ -361,12 +361,12 @@ def make_block_tests(module, module_name + tests.append(CipherStreamingSelfTest(module, params)) + + # When using CTR mode, test the non-shortcut code path. +- if p_mode == 'CTR' and not params.has_key('ctr_class'): ++ if p_mode == 'CTR' and 'ctr_class' not in params: + params2 = params.copy() + params2['description'] += " (shortcut disabled)" + ctr_params2 = params.get('ctr_params', {}).copy() + params2['ctr_params'] = ctr_params2 +- if not params2['ctr_params'].has_key('disable_shortcut'): ++ if 'disable_shortcut' not in params2['ctr_params']: + params2['ctr_params']['disable_shortcut'] = 1 + tests.append(CipherSelfTest(module, params2)) + return tests +--- lib/Crypto/SelfTest/Cipher/test_AES.py ++++ lib/Crypto/SelfTest/Cipher/test_AES.py +@@ -26,7 +26,7 @@ + + __revision__ = "$Id$" + +-from common import dict # For compatibility with Python 2.1 and 2.2 ++from .common import dict # For compatibility with Python 2.1 and 2.2 + from Crypto.Util.py3compat import * + from binascii import hexlify + +@@ -1422,7 +1422,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Cipher import AES +- from common import make_block_tests ++ from .common import make_block_tests + return make_block_tests(AES, "AES", test_data) + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_ARC2.py ++++ lib/Crypto/SelfTest/Cipher/test_ARC2.py +@@ -26,7 +26,7 @@ + + __revision__ = "$Id$" + +-from common import dict # For compatibility with Python 2.1 and 2.2 ++from .common import dict # For compatibility with Python 2.1 and 2.2 + + import unittest + from Crypto.Util.py3compat import * +@@ -109,7 +109,7 @@ class BufferOverflowTest(unittest.TestCa + + def get_tests(config={}): + from Crypto.Cipher import ARC2 +- from common import make_block_tests ++ from .common import make_block_tests + + tests = make_block_tests(ARC2, "ARC2", test_data) + tests.append(BufferOverflowTest()) +--- lib/Crypto/SelfTest/Cipher/test_ARC4.py ++++ lib/Crypto/SelfTest/Cipher/test_ARC4.py +@@ -70,7 +70,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Cipher import ARC4 +- from common import make_stream_tests ++ from .common import make_stream_tests + return make_stream_tests(ARC4, "ARC4", test_data) + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_Blowfish.py ++++ lib/Crypto/SelfTest/Cipher/test_Blowfish.py +@@ -102,7 +102,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Cipher import Blowfish +- from common import make_block_tests ++ from .common import make_block_tests + return make_block_tests(Blowfish, "Blowfish", test_data) + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_CAST.py ++++ lib/Crypto/SelfTest/Cipher/test_CAST.py +@@ -46,7 +46,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Cipher import CAST +- from common import make_block_tests ++ from .common import make_block_tests + return make_block_tests(CAST, "CAST", test_data) + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_DES3.py ++++ lib/Crypto/SelfTest/Cipher/test_DES3.py +@@ -26,7 +26,7 @@ + + __revision__ = "$Id$" + +-from common import dict # For compatibility with Python 2.1 and 2.2 ++from .common import dict # For compatibility with Python 2.1 and 2.2 + from Crypto.Util.py3compat import * + from binascii import hexlify + +@@ -322,7 +322,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Cipher import DES3 +- from common import make_block_tests ++ from .common import make_block_tests + return make_block_tests(DES3, "DES3", test_data) + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_DES.py ++++ lib/Crypto/SelfTest/Cipher/test_DES.py +@@ -26,7 +26,7 @@ + + __revision__ = "$Id$" + +-from common import dict # For compatibility with Python 2.1 and 2.2 ++from .common import dict # For compatibility with Python 2.1 and 2.2 + from Crypto.Util.py3compat import * + import unittest + +@@ -328,7 +328,7 @@ class RonRivestTest(unittest.TestCase): + + def get_tests(config={}): + from Crypto.Cipher import DES +- from common import make_block_tests ++ from .common import make_block_tests + return make_block_tests(DES, "DES", test_data) + [RonRivestTest()] + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Cipher/test_pkcs1_15.py ++++ lib/Crypto/SelfTest/Cipher/test_pkcs1_15.py +@@ -41,7 +41,7 @@ def t2b(t): + """Convert a text string with bytes in hex form to a byte string""" + clean = b(rws(t)) + if len(clean)%2 == 1: +- print clean ++ print(clean) + raise ValueError("Even number of characters expected") + return a2b_hex(clean) + +@@ -154,7 +154,7 @@ HKukWBcq9f/UOmS0oEhai/6g+Uf7VHJdWaeO5Lzu + def testEncryptVerify1(self): + # Encrypt/Verify messages of length [0..RSAlen-11] + # and therefore padding [8..117] +- for pt_len in xrange(0,128-11+1): ++ for pt_len in range(0,128-11+1): + pt = self.rng(pt_len) + cipher = PKCS.new(self.key1024) + ct = cipher.encrypt(pt) +--- lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py ++++ lib/Crypto/SelfTest/Cipher/test_pkcs1_oaep.py +@@ -20,7 +20,7 @@ + # SOFTWARE. + # =================================================================== + +-from __future__ import nested_scopes ++ + + __revision__ = "$Id$" + +@@ -269,7 +269,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase + # Verify encryption using all test vectors + for test in self._testData: + # Build the key +- comps = [ long(rws(test[0][x]),16) for x in ('n','e') ] ++ comps = [ int(rws(test[0][x]),16) for x in ('n','e') ] + key = RSA.construct(comps) + # RNG that takes its random numbers from a pool given + # at initialization +@@ -297,7 +297,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase + # Verify decryption using all test vectors + for test in self._testData: + # Build the key +- comps = [ long(rws(test[0][x]),16) for x in ('n','e','d') ] ++ comps = [ int(rws(test[0][x]),16) for x in ('n','e','d') ] + key = RSA.construct(comps) + # The real test + cipher = PKCS.new(key, test[4]) +@@ -312,7 +312,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase + + def testEncryptDecrypt1(self): + # Encrypt/Decrypt messages of length [0..128-2*20-2] +- for pt_len in xrange(0,128-2*20-2): ++ for pt_len in range(0,128-2*20-2): + pt = self.rng(pt_len) + ct = PKCS.encrypt(pt, self.key1024) + pt2 = PKCS.decrypt(ct, self.key1024) +@@ -335,7 +335,7 @@ class PKCS1_OAEP_Tests(unittest.TestCase + cipher = PKCS.new(self.key1024, hashmod) + ct = cipher.encrypt(pt) + self.assertEqual(cipher.decrypt(ct), pt) +- self.failUnless(asked > hashmod.digest_size) ++ self.assertTrue(asked > hashmod.digest_size) + + def testEncryptDecrypt2(self): + # Verify that OAEP supports labels +--- lib/Crypto/SelfTest/Cipher/test_XOR.py ++++ lib/Crypto/SelfTest/Cipher/test_XOR.py +@@ -61,7 +61,7 @@ class TruncationSelfTest(unittest.TestCa + def get_tests(config={}): + global XOR + from Crypto.Cipher import XOR +- from common import make_stream_tests ++ from .common import make_stream_tests + return make_stream_tests(XOR, "XOR", test_data) + [TruncationSelfTest()] + + if __name__ == '__main__': +--- lib/Crypto/SelfTest/Hash/common.py ++++ lib/Crypto/SelfTest/Hash/common.py +@@ -53,11 +53,11 @@ class HashDigestSizeSelfTest(unittest.Te + return self.description + + def runTest(self): +- self.failUnless(hasattr(self.hashmod, "digest_size")) +- self.assertEquals(self.hashmod.digest_size, self.expected) ++ self.assertTrue(hasattr(self.hashmod, "digest_size")) ++ self.assertEqual(self.hashmod.digest_size, self.expected) + h = self.hashmod.new() +- self.failUnless(hasattr(h, "digest_size")) +- self.assertEquals(h.digest_size, self.expected) ++ self.assertTrue(hasattr(h, "digest_size")) ++ self.assertEqual(h.digest_size, self.expected) + + + class HashSelfTest(unittest.TestCase): +@@ -133,7 +133,7 @@ class MACSelfTest(unittest.TestCase): + return self.description + + def runTest(self): +- for hashname in self.expected_dict.keys(): ++ for hashname in list(self.expected_dict.keys()): + hashmod = self.hashmods[hashname] + key = binascii.a2b_hex(b(self.key)) + data = binascii.a2b_hex(b(self.input)) +@@ -171,7 +171,7 @@ def make_hash_tests(module, module_name, + tests = [] + for i in range(len(test_data)): + row = test_data[i] +- (expected, input) = map(b,row[0:2]) ++ (expected, input) = list(map(b,row[0:2])) + if len(row) < 3: + description = repr(input) + else: +--- lib/Crypto/SelfTest/Hash/test_HMAC.py ++++ lib/Crypto/SelfTest/Hash/test_HMAC.py +@@ -26,7 +26,7 @@ + + __revision__ = "$Id$" + +-from common import dict # For compatibility with Python 2.1 and 2.2 ++from .common import dict # For compatibility with Python 2.1 and 2.2 + from Crypto.Util.py3compat import * + + # This is a list of (key, data, results, description) tuples. +@@ -204,7 +204,7 @@ hashlib_test_data = [ + def get_tests(config={}): + global test_data + from Crypto.Hash import HMAC, MD5, SHA as SHA1, SHA256 +- from common import make_mac_tests ++ from .common import make_mac_tests + hashmods = dict(MD5=MD5, SHA1=SHA1, SHA256=SHA256, default=None) + try: + from Crypto.Hash import SHA224, SHA384, SHA512 +--- lib/Crypto/SelfTest/Hash/test_MD2.py ++++ lib/Crypto/SelfTest/Hash/test_MD2.py +@@ -51,7 +51,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import MD2 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(MD2, "MD2", test_data, + digest_size=16, + oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02") +--- lib/Crypto/SelfTest/Hash/test_MD4.py ++++ lib/Crypto/SelfTest/Hash/test_MD4.py +@@ -51,7 +51,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import MD4 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(MD4, "MD4", test_data, + digest_size=16, + oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04") +--- lib/Crypto/SelfTest/Hash/test_MD5.py ++++ lib/Crypto/SelfTest/Hash/test_MD5.py +@@ -51,7 +51,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import MD5 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(MD5, "MD5", test_data, + digest_size=16, + oid="\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05") +--- lib/Crypto/SelfTest/Hash/test_RIPEMD.py ++++ lib/Crypto/SelfTest/Hash/test_RIPEMD.py +@@ -60,7 +60,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import RIPEMD +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(RIPEMD, "RIPEMD", test_data, + digest_size=20, + oid="\x06\x05\x2b\x24\x03\02\x01") +--- lib/Crypto/SelfTest/Hash/test_SHA224.py ++++ lib/Crypto/SelfTest/Hash/test_SHA224.py +@@ -52,7 +52,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import SHA224 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(SHA224, "SHA224", test_data, + digest_size=28, + oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04') +--- lib/Crypto/SelfTest/Hash/test_SHA256.py ++++ lib/Crypto/SelfTest/Hash/test_SHA256.py +@@ -36,13 +36,13 @@ class LargeSHA256Test(unittest.TestCase) + zeros = bchr(0x00) * (1024*1024) + + h = SHA256.new(zeros) +- for i in xrange(511): ++ for i in range(511): + h.update(zeros) + + # This test vector is from PyCrypto's old testdata.py file. + self.assertEqual('9acca8e8c22201155389f65abbf6bc9723edc7384ead80503839f49dcc56d767', h.hexdigest()) # 512 MiB + +- for i in xrange(8): ++ for i in range(8): + h.update(zeros) + + # This test vector is from PyCrypto's old testdata.py file. +@@ -78,7 +78,7 @@ def get_tests(config={}): + ] + + from Crypto.Hash import SHA256 +- from common import make_hash_tests ++ from .common import make_hash_tests + tests = make_hash_tests(SHA256, "SHA256", test_data, + digest_size=32, + oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") +--- lib/Crypto/SelfTest/Hash/test_SHA384.py ++++ lib/Crypto/SelfTest/Hash/test_SHA384.py +@@ -50,7 +50,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import SHA384 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(SHA384, "SHA384", test_data, + digest_size=48, + oid='\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02') +--- lib/Crypto/SelfTest/Hash/test_SHA512.py ++++ lib/Crypto/SelfTest/Hash/test_SHA512.py +@@ -47,7 +47,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import SHA512 +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(SHA512, "SHA512", test_data, + digest_size=64, + oid="\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") +--- lib/Crypto/SelfTest/Hash/test_SHA.py ++++ lib/Crypto/SelfTest/Hash/test_SHA.py +@@ -51,7 +51,7 @@ test_data = [ + + def get_tests(config={}): + from Crypto.Hash import SHA +- from common import make_hash_tests ++ from .common import make_hash_tests + return make_hash_tests(SHA, "SHA", test_data, + digest_size=20, + oid="\x06\x05\x2B\x0E\x03\x02\x1A") +--- lib/Crypto/SelfTest/__init__.py ++++ lib/Crypto/SelfTest/__init__.py +@@ -32,7 +32,7 @@ __revision__ = "$Id$" + + import sys + import unittest +-from StringIO import StringIO ++from io import StringIO + + class SelfTestError(Exception): + def __init__(self, message, result): +--- lib/Crypto/SelfTest/Protocol/test_KDF.py ++++ lib/Crypto/SelfTest/Protocol/test_KDF.py +@@ -78,7 +78,7 @@ class PBKDF2_Tests(unittest.TestCase): + def prf(p,s): + return HMAC.new(p,s,SHA1).digest() + +- for i in xrange(len(self._testData)): ++ for i in range(len(self._testData)): + v = self._testData[i] + res = PBKDF2(v[0], t2b(v[1]), v[2], v[3]) + res2 = PBKDF2(v[0], t2b(v[1]), v[2], v[3], prf) +--- lib/Crypto/SelfTest/PublicKey/test_ElGamal.py ++++ lib/Crypto/SelfTest/PublicKey/test_ElGamal.py +@@ -105,8 +105,8 @@ class ElGamalTest(unittest.TestCase): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + ct = key.encrypt(d['pt'], d['k']) +- self.assertEquals(ct[0], d['ct1']) +- self.assertEquals(ct[1], d['ct2']) ++ self.assertEqual(ct[0], d['ct1']) ++ self.assertEqual(ct[1], d['ct2']) + + def test_decryption(self): + for tv in self.tve: +@@ -114,7 +114,7 @@ class ElGamalTest(unittest.TestCase): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + pt = key.decrypt((d['ct1'], d['ct2'])) +- self.assertEquals(pt, d['pt']) ++ self.assertEqual(pt, d['pt']) + + def test_signing(self): + for tv in self.tvs: +@@ -122,8 +122,8 @@ class ElGamalTest(unittest.TestCase): + d = self.convert_tv(tv, as_longs) + key = ElGamal.construct(d['key']) + sig1, sig2 = key.sign(d['h'], d['k']) +- self.assertEquals(sig1, d['sig1']) +- self.assertEquals(sig2, d['sig2']) ++ self.assertEqual(sig1, d['sig1']) ++ self.assertEqual(sig2, d['sig2']) + + def test_verification(self): + for tv in self.tvs: +@@ -132,17 +132,17 @@ class ElGamalTest(unittest.TestCase): + key = ElGamal.construct(d['key']) + # Positive test + res = key.verify( d['h'], (d['sig1'],d['sig2']) ) +- self.failUnless(res) ++ self.assertTrue(res) + # Negative test + res = key.verify( d['h'], (d['sig1']+1,d['sig2']) ) +- self.failIf(res) ++ self.assertFalse(res) + + def convert_tv(self, tv, as_longs=0): + """Convert a test vector from textual form (hexadecimal ascii + to either integers or byte strings.""" + key_comps = 'p','g','y','x' + tv2 = {} +- for c in tv.keys(): ++ for c in list(tv.keys()): + tv2[c] = a2b_hex(tv[c]) + if as_longs or c in key_comps or c in ('sig1','sig2'): + tv2[c] = bytes_to_long(tv2[c]) +@@ -163,41 +163,41 @@ class ElGamalTest(unittest.TestCase): + def _check_private_key(self, elgObj): + + # Check capabilities +- self.failUnless(elgObj.has_private()) +- self.failUnless(elgObj.can_sign()) +- self.failUnless(elgObj.can_encrypt()) ++ self.assertTrue(elgObj.has_private()) ++ self.assertTrue(elgObj.can_sign()) ++ self.assertTrue(elgObj.can_encrypt()) + + # Sanity check key data +- self.failUnless(1 (1L << bits-1)-1, 1) +- self.assertEqual(x < (1L << bits), 1) ++ self.assertEqual(x > (1 << bits-1)-1, 1) ++ self.assertEqual(x < (1 << bits), 1) + e = 2**16+1 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD(x-1, e), 1) + self.assertNotEqual(x % 2, 0) +- self.assertEqual(x > (1L << bits-1)-1, 1) +- self.assertEqual(x < (1L << bits), 1) ++ self.assertEqual(x > (1 << bits-1)-1, 1) ++ self.assertEqual(x < (1 << bits), 1) + e = 2**16+2 + x = number.getStrongPrime(bits, e) + self.assertEqual(number.GCD((x-1)>>1, e), 1) + self.assertNotEqual(x % 2, 0) +- self.assertEqual(x > (1L << bits-1)-1, 1) +- self.assertEqual(x < (1L << bits), 1) ++ self.assertEqual(x > (1 << bits-1)-1, 1) ++ self.assertEqual(x < (1 << bits), 1) + + def test_isPrime(self): + """Util.number.isPrime""" +@@ -256,28 +256,28 @@ class MiscTests(unittest.TestCase): + self.assertEqual(number.isPrime(2), True) + self.assertEqual(number.isPrime(3), True) + self.assertEqual(number.isPrime(4), False) +- self.assertEqual(number.isPrime(2L**1279-1), True) +- self.assertEqual(number.isPrime(-(2L**1279-1)), False) # Regression test: negative numbers should not be prime ++ self.assertEqual(number.isPrime(2**1279-1), True) ++ self.assertEqual(number.isPrime(-(2**1279-1)), False) # Regression test: negative numbers should not be prime + # test some known gmp pseudo-primes taken from + # http://www.trnicely.net/misc/mpzspsp.html + for composite in (43 * 127 * 211, 61 * 151 * 211, 15259 * 30517, +- 346141L * 692281L, 1007119L * 2014237L, 3589477L * 7178953L, +- 4859419L * 9718837L, 2730439L * 5460877L, +- 245127919L * 490255837L, 963939391L * 1927878781L, +- 4186358431L * 8372716861L, 1576820467L * 3153640933L): +- self.assertEqual(number.isPrime(long(composite)), False) ++ 346141 * 692281, 1007119 * 2014237, 3589477 * 7178953, ++ 4859419 * 9718837, 2730439 * 5460877, ++ 245127919 * 490255837, 963939391 * 1927878781, ++ 4186358431 * 8372716861, 1576820467 * 3153640933): ++ self.assertEqual(number.isPrime(int(composite)), False) + + def test_size(self): + self.assertEqual(number.size(2),2) + self.assertEqual(number.size(3),2) + self.assertEqual(number.size(0xa2),8) + self.assertEqual(number.size(0xa2ba40),8*3) +- self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5L), 1024) ++ self.assertEqual(number.size(0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5), 1024) + + def test_negative_number_roundtrip_mpzToLongObj_longObjToMPZ(self): + """Test that mpzToLongObj and longObjToMPZ (internal functions) roundtrip negative numbers correctly.""" +- n = -100000000000000000000000000000000000L +- e = 2L ++ n = -100000000000000000000000000000000000 ++ e = 2 + k = number._fastmath.rsa_construct(n, e) + self.assertEqual(n, k.n) + self.assertEqual(e, k.e) +--- lib/Crypto/Signature/PKCS1_PSS.py ++++ lib/Crypto/Signature/PKCS1_PSS.py +@@ -61,7 +61,7 @@ the RSA key: + + # Allow nested scopes in Python 2.1 + # See http://oreilly.com/pub/a/python/2001/04/19/pythonnews.html +-from __future__ import nested_scopes ++ + + __revision__ = "$Id$" + __all__ = [ 'new', 'PSS_SigScheme' ] +@@ -199,7 +199,7 @@ class PSS_SigScheme: + def MGF1(mgfSeed, maskLen, hash): + """Mask Generation Function, described in B.2.1""" + T = b("") +- for counter in xrange(ceil_div(maskLen, hash.digest_size)): ++ for counter in range(ceil_div(maskLen, hash.digest_size)): + c = long_to_bytes(counter, 4) + T = T + hash.new(mgfSeed + c).digest() + assert(len(T)>=maskLen) +@@ -239,7 +239,7 @@ def EMSA_PSS_ENCODE(mhash, emBits, randF + + # Bitmask of digits that fill up + lmask = 0 +- for i in xrange(8*emLen-emBits): ++ for i in range(8*emLen-emBits): + lmask = lmask>>1 | 0x80 + + # Step 1 and 2 have been already done +@@ -297,7 +297,7 @@ def EMSA_PSS_VERIFY(mhash, em, emBits, m + + # Bitmask of digits that fill up + lmask = 0 +- for i in xrange(8*emLen-emBits): ++ for i in range(8*emLen-emBits): + lmask = lmask>>1 | 0x80 + + # Step 1 and 2 have been already done +--- lib/Crypto/Util/asn1.py ++++ lib/Crypto/Util/asn1.py +@@ -187,7 +187,7 @@ class DerSequence(DerObject): + + def hasInts(self): + """Return the number of items in this sequence that are numbers.""" +- return len(filter(isInt, self._seq)) ++ return len(list(filter(isInt, self._seq))) + + def hasOnlyInts(self): + """Return True if all items in this sequence are numbers.""" +--- lib/Crypto/Util/Counter.py ++++ lib/Crypto/Util/Counter.py +@@ -113,7 +113,7 @@ def new(nbits, prefix=b(""), suffix=b("" + + def _encode(n, nbytes, little_endian=False): + retval = [] +- n = long(n) ++ n = int(n) + for i in range(nbytes): + if little_endian: + retval.append(bchr(n & 0xff)) +--- lib/Crypto/Util/_number_new.py ++++ lib/Crypto/Util/_number_new.py +@@ -35,11 +35,11 @@ def ceil_shift(n, b): + This is done by right-shifting n by b bits and incrementing the result by 1 + if any '1' bits were shifted out. + """ +- if not isinstance(n, (int, long)) or not isinstance(b, (int, long)): ++ if not isinstance(n, int) or not isinstance(b, int): + raise TypeError("unsupported operand type(s): %r and %r" % (type(n).__name__, type(b).__name__)) + + assert n >= 0 and b >= 0 # I haven't tested or even thought about negative values +- mask = (1L << b) - 1 ++ mask = (1 << b) - 1 + if n & mask: + return (n >> b) + 1 + else: +@@ -48,7 +48,7 @@ def ceil_shift(n, b): + def ceil_div(a, b): + """Return ceil(a / b) without performing any floating-point operations.""" + +- if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): ++ if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__)) + + (q, r) = divmod(a, b) +@@ -58,7 +58,7 @@ def ceil_div(a, b): + return q + + def floor_div(a, b): +- if not isinstance(a, (int, long)) or not isinstance(b, (int, long)): ++ if not isinstance(a, int) or not isinstance(b, int): + raise TypeError("unsupported operand type(s): %r and %r" % (type(a).__name__, type(b).__name__)) + + (q, r) = divmod(a, b) +@@ -70,10 +70,10 @@ def exact_log2(num): + If no such integer exists, this function raises ValueError. + """ + +- if not isinstance(num, (int, long)): ++ if not isinstance(num, int): + raise TypeError("unsupported operand type: %r" % (type(num).__name__,)) + +- n = long(num) ++ n = int(num) + if n <= 0: + raise ValueError("cannot compute logarithm of non-positive number") + +@@ -85,7 +85,7 @@ def exact_log2(num): + n >>= 1 + i -= 1 + +- assert num == (1L << i) ++ assert num == (1 << i) + return i + + def exact_div(p, d, allow_divzero=False): +@@ -99,7 +99,7 @@ def exact_div(p, d, allow_divzero=False) + unless allow_divzero is true (default: False). + """ + +- if not isinstance(p, (int, long)) or not isinstance(d, (int, long)): ++ if not isinstance(p, int) or not isinstance(d, int): + raise TypeError("unsupported operand type(s): %r and %r" % (type(p).__name__, type(d).__name__)) + + if d == 0 and allow_divzero: +--- lib/Crypto/Util/number.py ++++ lib/Crypto/Util/number.py +@@ -32,7 +32,7 @@ import math + import sys + from Crypto.Util.py3compat import * + +-bignum = long ++bignum = int + try: + from Crypto.PublicKey import _fastmath + except ImportError: +@@ -57,7 +57,7 @@ if _fastmath is not None and not _fastma + _warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning) + + # New functions +-from _number_new import * ++from ._number_new import * + + # Commented out and replaced with faster versions below + ## def long2str(n): +@@ -136,7 +136,7 @@ def getRandomNBitInteger(N, randfunc=Non + the future. + """ + value = getRandomInteger (N-1, randfunc) +- value |= 2L ** (N-1) # Ensure high bit is set ++ value |= 2 ** (N-1) # Ensure high bit is set + assert size(value) >= N + return value + +@@ -153,8 +153,8 @@ def inverse(u, v): + """inverse(u:long, v:long):long + Return the inverse of u mod v. + """ +- u3, v3 = long(u), long(v) +- u1, v1 = 1L, 0L ++ u3, v3 = int(u), int(v) ++ u1, v1 = 1, 0 + while v3 > 0: + q=divmod(u3, v3)[0] + u1, v1 = v1, u1 - v1*q +@@ -208,7 +208,7 @@ def _rabinMillerTest(n, rounds, randfunc + + tested = [] + # we need to do at most n-2 rounds. +- for i in xrange (min (rounds, n-2)): ++ for i in range (min (rounds, n-2)): + # randomly choose a < n and make sure it hasn't been tested yet + a = getRandomRange (2, n, randfunc) + while a in tested: +@@ -219,7 +219,7 @@ def _rabinMillerTest(n, rounds, randfunc + if z == 1 or z == n_1: + continue + composite = 1 +- for r in xrange (b): ++ for r in range (b): + z = (z * z) % n + if z == 1: + return 0 +@@ -261,7 +261,7 @@ def getStrongPrime(N, e=0, false_positiv + + # Use the accelerator if available + if _fastmath is not None: +- return _fastmath.getStrongPrime(long(N), long(e), false_positive_prob, ++ return _fastmath.getStrongPrime(int(N), int(e), false_positive_prob, + randfunc) + + if (N < 512) or ((N % 128) != 0): +@@ -275,9 +275,9 @@ def getStrongPrime(N, e=0, false_positiv + x = (N - 512) >> 7; + # We need to approximate the sqrt(2) in the lower_bound by an integer + # expression because floating point math overflows with these numbers +- lower_bound = divmod(14142135623730950489L * (2L ** (511 + 128*x)), +- 10000000000000000000L)[0] +- upper_bound = (1L << (512 + 128*x)) - 1 ++ lower_bound = divmod(14142135623730950489 * (2 ** (511 + 128*x)), ++ 10000000000000000000)[0] ++ upper_bound = (1 << (512 + 128*x)) - 1 + # Randomly choose X in calculated range + X = getRandomRange (lower_bound, upper_bound, randfunc) + +@@ -291,7 +291,7 @@ def getStrongPrime(N, e=0, false_positiv + # sieve the field + for prime in sieve_base: + offset = y % prime +- for j in xrange ((prime - offset) % prime, len (field), prime): ++ for j in range ((prime - offset) % prime, len (field), prime): + field[j] = 1 + + # look for suitable p[i] starting at y +@@ -347,7 +347,7 @@ def getStrongPrime(N, e=0, false_positiv + X += increment + # abort when X has more bits than requested + # TODO: maybe we shouldn't abort but rather start over. +- if X >= 1L << N: ++ if X >= 1 << N: + raise RuntimeError ("Couln't find prime in field. " + "Developer: Increase field_size") + return X +@@ -365,7 +365,7 @@ def isPrime(N, false_positive_prob=1e-6, + If randfunc is omitted, then Random.new().read is used. + """ + if _fastmath is not None: +- return _fastmath.isPrime(long(N), false_positive_prob, randfunc) ++ return _fastmath.isPrime(int(N), false_positive_prob, randfunc) + + if N < 3 or N & 1 == 0: + return N == 2 +@@ -394,10 +394,10 @@ def long_to_bytes(n, blocksize=0): + """ + # after much testing, this algorithm was deemed to be the fastest + s = b('') +- n = long(n) ++ n = int(n) + pack = struct.pack + while n > 0: +- s = pack('>I', n & 0xffffffffL) + s ++ s = pack('>I', n & 0xffffffff) + s + n = n >> 32 + # strip off leading zeros + for i in range(len(s)): +@@ -420,7 +420,7 @@ def bytes_to_long(s): + + This is (essentially) the inverse of long_to_bytes(). + """ +- acc = 0L ++ acc = 0 + unpack = struct.unpack + length = len(s) + if length % 4: +--- lib/Crypto/Util/py3compat.py ++++ lib/Crypto/Util/py3compat.py +@@ -79,7 +79,7 @@ if sys.version_info[0] == 2: + return ''.join(s) + else: + def tobytes(s): +- if isinstance(s, unicode): ++ if isinstance(s, str): + return s.encode("latin-1") + else: + return ''.join(s) +--- lib/Crypto/Util/RFC1751.py ++++ lib/Crypto/Util/RFC1751.py +@@ -29,6 +29,7 @@ __revision__ = "$Id$" + + import binascii + from Crypto.Util.py3compat import * ++from functools import reduce + + binary={0:'0000', 1:'0001', 2:'0010', 3:'0011', 4:'0100', 5:'0101', + 6:'0110', 7:'0111', 8:'1000', 9:'1001', 10:'1010', 11:'1011', +@@ -36,8 +37,8 @@ binary={0:'0000', 1:'0001', 2:'0010', 3: + + def _key2bin(s): + "Convert a key into a string of binary digits" +- kl=map(lambda x: bord(x), s) +- kl=map(lambda x: binary[x>>4]+binary[x&15], kl) ++ kl=[bord(x) for x in s] ++ kl=[binary[x>>4]+binary[x&15] for x in kl] + return ''.join(kl) + + def _extract(key, start, length): +@@ -95,7 +96,7 @@ def english_to_key (s): + p=0 + for i in range(0, 64, 2): p=p+_extract(skbin, i, 2) + if (p&3) != _extract(skbin, 64, 2): +- raise ValueError, "Parity error in resulting key" ++ raise ValueError("Parity error in resulting key") + key=key+subkey[0:8] + return key + +@@ -352,13 +353,13 @@ if __name__=='__main__': + ] + + for key, words in data: +- print 'Trying key', key ++ print('Trying key', key) + key=binascii.a2b_hex(key) + w2=key_to_english(key) + if w2!=words: +- print 'key_to_english fails on key', repr(key), ', producing', str(w2) ++ print('key_to_english fails on key', repr(key), ', producing', str(w2)) + k2=english_to_key(words) + if k2!=key: +- print 'english_to_key fails on key', repr(key), ', producing', repr(k2) ++ print('english_to_key fails on key', repr(key), ', producing', repr(k2)) + + +--- pct-speedtest.py ++++ pct-speedtest.py +@@ -52,7 +52,7 @@ class Benchmark: + bytes = bytes_per_block * blocks + data = self.random_data(bytes) + retval = [] +- for i in xrange(blocks): ++ for i in range(blocks): + p = i * bytes_per_block + retval.append(data[p:p+bytes_per_block]) + return retval +--- setup.py ++++ setup.py +@@ -44,9 +44,9 @@ from distutils.command.build_ext import + import os, sys, re + import struct + +-if sys.version[0:1] == '1': ++if sys.version[0:1] != '3': + raise RuntimeError ("The Python Cryptography Toolkit requires " +- "Python 2.x or 3.x to build.") ++ "Python 3.x to build.") + + # 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 +@@ -54,12 +54,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 distutils.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 +@@ -390,21 +385,6 @@ 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'] = [ +- 'Development Status :: 5 - Production/Stable', +- 'License :: Public Domain', +- 'Intended Audience :: Developers', +- 'Operating System :: Unix', +- 'Operating System :: Microsoft :: Windows', +- 'Operating System :: MacOS :: MacOS X', +- 'Topic :: Security :: Cryptography', +- 'Programming Language :: Python :: 2', +- 'Programming Language :: Python :: 3', +- ] +- + core.setup(**kw) + + def touch(path): diff --git a/SPECS/python-crypto.spec b/SPECS/python-crypto.spec new file mode 100644 index 0000000..29b83be --- /dev/null +++ b/SPECS/python-crypto.spec @@ -0,0 +1,543 @@ +# Share docs between packages for multiple python versions +%global _docdir_fmt %{name} + +# Single python3 version in Fedora, python3_pkgversion macro not available +%{!?python3_pkgversion:%global python3_pkgversion 3} + +Summary: Cryptography library for Python +Name: python-crypto +Version: 2.6.1 +Release: 42%{?dist} +# Mostly Public Domain apart from parts of HMAC.py and setup.py, which are Python +License: Public Domain and Python +URL: http://www.pycrypto.org/ +Source0: http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-%{version}.tar.gz +Patch0: python-crypto-2.4-optflags.patch +Patch1: python-crypto-2.4-fix-pubkey-size-divisions.patch +Patch2: pycrypto-2.6.1-CVE-2013-7459.patch +Patch3: pycrypto-2.6.1-unbundle-libtomcrypt.patch +Patch4: python-crypto-2.6.1-link.patch +Patch5: pycrypto-2.6.1-CVE-2018-6594.patch +Patch6: pycrypto-2.6.1-use-os-random.patch +Patch7: pycrypto-2.6.1-drop-py2.1-support.patch +Patch8: python-crypto-2.6.1-python3.10.patch +Patch9: python-crypto-2.6.1-python3.11.patch +Patch10: python-crypto-2.6.1-python3only.patch +Patch11: python-crypto-2.6.1-no-distutils.patch +Patch12: python-crypto-2.6.1-SyntaxWarning.patch +BuildRequires: coreutils +BuildRequires: findutils +BuildRequires: gcc +BuildRequires: gmp-devel >= 4.1 +BuildRequires: libtomcrypt-devel >= 1.16 +BuildRequires: python%{python3_pkgversion}-devel +BuildRequires: python%{python3_pkgversion}-setuptools + +%description +PyCrypto is a collection of both secure hash functions (such as MD5 and +SHA), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.). + +This software is no longer maintained upstream. Please use the Cryptography +or PyCryptodome software instead. + +%package -n python%{python3_pkgversion}-crypto +Summary: Cryptography library for Python 3 +%{?python_provide:%python_provide python%{python3_pkgversion}-crypto} + +%description -n python%{python3_pkgversion}-crypto +PyCrypto is a collection of both secure hash functions (such as MD5 and +SHA), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.). + +This is the Python 3 build of the package. + +This software is no longer maintained upstream. Please use the Cryptography +or PyCryptodome software instead. + +%prep +%setup -n pycrypto-%{version} -q + +# Use distribution compiler flags rather than upstream's +%patch0 -p1 + +# Fix divisions within benchmarking suite: +%patch1 -p1 + +# AES.new with invalid parameter crashes python +# https://github.com/dlitz/pycrypto/issues/176 +# CVE-2013-7459 +%patch2 -p1 + +# Unbundle libtomcrypt (#1087557) +rm -rf src/libtom +%patch3 + +# log() not available in libgmp, need libm too +%patch4 + +# When creating ElGamal keys, the generator wasn't a square residue: ElGamal +# encryption done with those keys cannot be secure under the DDH assumption +# https://bugzilla.redhat.com/show_bug.cgi?id=1542313 (CVE-2018-6594) +# https://github.com/TElgamal/attack-on-pycrypto-elgamal +# https://github.com/Legrandin/pycryptodome/issues/90 +# https://github.com/dlitz/pycrypto/issues/253 +# Patch based on this commit from cryptodome: +# https://github.com/Legrandin/pycryptodome/commit/99c27a3b +# Converted to pull request for pycrypto: +# https://github.com/dlitz/pycrypto/pull/256 +%patch5 + +# Replace the user-space RNG with a thin wrapper to os.urandom +# Based on https://github.com/Legrandin/pycryptodome/commit/afd6328f +# Fixes compatibility with Python 3.8 (#1718332) +%patch6 + +# We already require Python 2.4 or later, so drop support for Python 2.1 +# in the code +%patch7 + +# Fix Python 3.10 compatibility +# https://bugzilla.redhat.com/show_bug.cgi?id=1897544 +%patch8 + +# Fix Python 3.11 compatibility +# https://bugzilla.redhat.com/show_bug.cgi?id=2021808 +%patch9 + +# Convert all code to Python 3 before the ability to use 2to3 goes away +%patch10 + +# Drop use of deprecated distutils, going away in Python 3.12 +%patch11 + +# Get rid of a SyntaxWarning in test_random.py +%patch12 + +%build +%global optflags %{optflags} -fno-strict-aliasing +%py3_build + +%install +%py3_install + +# Remove group write permissions on shared objects +find %{buildroot}%{python3_sitearch} -name '*.so' -exec chmod -c g-w {} \; + +%check +%{__python3} setup.py test + +# Benchmark +PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} pct-speedtest.py + +%files -n python%{python3_pkgversion}-crypto +%license COPYRIGHT LEGAL/ +%doc README TODO ACKS ChangeLog Doc/ +%{python3_sitearch}/Crypto/ +%{python3_sitearch}/pycrypto-%{version}-py3.*.egg-info + +%changelog +* Wed Oct 04 2023 Arkady L. Shane - 2.6.1-42 +- Rebuilt for MSVSphere 9.2 + +* Fri Jan 20 2023 Fedora Release Engineering - 2.6.1-42 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Jul 22 2022 Fedora Release Engineering - 2.6.1-41 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Mon Jun 13 2022 Python Maint - 2.6.1-40 +- Rebuilt for Python 3.11 + +* Fri Jan 21 2022 Fedora Release Engineering - 2.6.1-39 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Thu Nov 11 2021 Paul Howarth - 2.6.1-38 +- Convert all code to Python 3 before the ability to use 2to3 goes away +- Drop use of deprecated distutils, going away in Python 3.12 +- Get rid of a SyntaxWarning in test_random.py + +* Wed Nov 10 2021 Paul Howarth - 2.6.1-37 +- Fix Python 3.11 compatibility (#2021808) + +* Fri Jul 23 2021 Fedora Release Engineering - 2.6.1-36 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Jun 04 2021 Python Maint - 2.6.1-35 +- Rebuilt for Python 3.10 + +* Wed Jan 27 2021 Fedora Release Engineering - 2.6.1-34 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Nov 20 2020 Paul Howarth - 2.6.1-33 +- Fix Python 3.10 compatibility (#1897544) + +* Wed Jul 29 2020 Fedora Release Engineering - 2.6.1-32 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue May 26 2020 Miro Hrončok - 2.6.1-31 +- Rebuilt for Python 3.9 + +* Wed Jan 29 2020 Paul Howarth - 2.6.1-30 +- Drop Python 2 support + +* Thu Oct 03 2019 Miro Hrončok - 2.6.1-29 +- Rebuilt for Python 3.8.0rc1 (#1748018) + +* Mon Aug 19 2019 Miro Hrončok - 2.6.1-28 +- Rebuilt for Python 3.8 + +* Fri Jul 26 2019 Fedora Release Engineering - 2.6.1-27 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri Jun 7 2019 Paul Howarth - 2.6.1-26 +- Replace the user-space RNG with a thin wrapper to os.urandom + - Based on https://github.com/Legrandin/pycryptodome/commit/afd6328f + - Fixes compatibility with Python 3.8 (#1718332) +- Drop support for Python 2.1 + +* Sat Feb 02 2019 Fedora Release Engineering - 2.6.1-25 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Fri Jul 13 2018 Fedora Release Engineering - 2.6.1-24 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jun 19 2018 Miro Hrončok - 2.6.1-23 +- Rebuilt for Python 3.7 + +* Fri Feb 23 2018 Paul Howarth - 2.6.1-22 +- When creating ElGamal keys, the generator wasn't a square residue: ElGamal + encryption done with those keys cannot be secure under the DDH assumption + https://bugzilla.redhat.com/show_bug.cgi?id=1542313 (CVE-2018-6594) + https://github.com/TElgamal/attack-on-pycrypto-elgamal + https://github.com/Legrandin/pycryptodome/issues/90 + https://github.com/dlitz/pycrypto/issues/253 + https://github.com/dlitz/pycrypto/pull/256 + +* Fri Feb 09 2018 Fedora Release Engineering - 2.6.1-21 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Jan 25 2018 Paul Howarth - 2.6.1-20 +- log() not available in libgmp, need libm too + +* Mon Oct 23 2017 Simone Caronni - 2.6.1-19 +- Rebuild for libtomcrypt update + +* Tue Sep 05 2017 Igor Gnatenko - 2.6.1-18 +- Depend on %%{_bindir}/2to3 instead of python2-tools + +* Thu Aug 03 2017 Fedora Release Engineering - 2.6.1-17 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 2.6.1-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jun 29 2017 Paul Howarth - 2.6.1-15 +- BR: python2-tools (for 2to3) rather than plain python-tools + +* Sat Feb 11 2017 Fedora Release Engineering - 2.6.1-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Jan 18 2017 Paul Howarth - 2.6.1-13 +- AES.new with invalid parameter crashes python (CVE-2013-7459) + (https://github.com/dlitz/pycrypto/issues/176) + +* Fri Dec 09 2016 Charalampos Stratakis - 2.6.1-12 +- Rebuild for Python 3.6 + +* Tue Jul 19 2016 Fedora Release Engineering - 2.6.1-11 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Thu Feb 04 2016 Fedora Release Engineering - 2.6.1-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Dec 30 2015 Paul Howarth - 2.6.1-9 +- Enable python3 builds from EPEL-7 (#1110373) +- Modernize spec + +* Wed Nov 04 2015 Matej Stuchlik - 2.6.1-8 +- Rebuilt for Python 3.5 + +* Thu Jun 18 2015 Fedora Release Engineering - 2.6.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Sun Aug 17 2014 Fedora Release Engineering - 2.6.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 2.6.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 27 2014 Paul Howarth - 2.6.1-4 +- Rebuild for python3 3.4 in Rawhide again + +* Wed May 14 2014 Paul Howarth - 2.6.1-3 +- Unbundle libtomcrypt (#1087557) +- Drop %%defattr, redundant since rpm 4.4 + +* Wed May 14 2014 Bohuslav Kabrda - 2.6.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/Python_3.4 + +* Fri Oct 18 2013 Paul Howarth - 2.6.1-1 +- Update to 2.6.1 + - Fix PRNG not correctly reseeded in some situations (CVE-2013-1445) + +* Sun Aug 04 2013 Fedora Release Engineering - 2.6-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Thu Feb 14 2013 Fedora Release Engineering - 2.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Aug 03 2012 David Malcolm - 2.6-4 +- rebuild for https://fedoraproject.org/wiki/Features/Python_3.3 + +* Fri Aug 3 2012 David Malcolm - 2.6-3 +- remove rhel logic from with_python3 conditional + +* Sat Jul 21 2012 Fedora Release Engineering - 2.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu May 24 2012 Paul Howarth - 2.6-1 +- Update to 2.6 + - Fix insecure ElGamal key generation (launchpad bug #985164, CVE-2012-2417) + - Huge documentation cleanup + - Added more tests, including test vectors from NIST 800-38A + - Remove broken MODE_PGP, which never actually worked properly + - A new mode, MODE_OPENPGP, has been added for people wishing to write + OpenPGP implementations (see also launchpad bug #996814) + - Fix: getPrime with invalid input causes Python to abort with fatal error + (launchpad bug #988431) + - Fix: Segfaults within error-handling paths (launchpad bug #934294) + - Fix: Block ciphers allow empty string as IV (launchpad bug #997464) + - Fix DevURandomRNG to work with Python3's new I/O stack + - Remove automagic dependencies on libgmp and libmpir; let the caller + disable them using args + - Many other minor bug fixes and improvements +- Drop upstream patches + +* Sat Feb 18 2012 Paul Howarth - 2.5-2 +- Add upstream fixes for issues found by Dave Malcolm's experimental static + analysis tool (#790584) + +* Mon Jan 16 2012 Paul Howarth - 2.5-1 +- Update to 2.5 + - Added PKCS#1 encryption schemes (v1.5 and OAEP); we now have a decent, + easy-to-use non-textbook RSA implementation + - Added PKCS#1 signature schemes (v1.5 and PSS); v1.5 required some + extensive changes to Hash modules to contain the algorithm-specific ASN.1 + OID, and to that end we now always have a (thin) Python module to hide the + one in pure C + - Added 2 standard Key Derivation Functions (PBKDF1 and PBKDF2) + - Added export/import of RSA keys in OpenSSH and PKCS#8 formats + - Added password-protected export/import of RSA keys (one old method for + PKCS#8 PEM only) + - Added ability to generate RSA key pairs with configurable public + exponent e + - Added ability to construct an RSA key pair even if only the private + exponent d is known, and not p and q + - Added SHA-2 C source code (fully from Lorenz Quack) + - Unit tests for all the above + - Updates to documentation (both inline and in Doc/pycrypt.rst) + - Minor bug fixes (setup.py and tests) +- Upstream no longer ships python-3-changes.txt + +* Sat Jan 7 2012 Paul Howarth - 2.4.1-2 +- Rebuild with gcc 4.7 + +* Mon Nov 7 2011 Paul Howarth - 2.4.1-1 +- Update to 2.4.1 + - Fix "error: Setup script exited with error: src/config.h: No such file or + directory" when installing via easy_install + +* Wed Oct 26 2011 Marcela Mašláňová - 2.4-2.1 +- Rebuild with new gmp without compat lib + +* Tue Oct 25 2011 Paul Howarth - 2.4-2 +- Add python3-crypto subpackage (based on patch from Dave Malcolm - #748529) + +* Mon Oct 24 2011 Paul Howarth - 2.4-1 +- Update to 2.4 + - Python 3 support! PyCrypto now supports every version of Python from 2.1 + through to 3.2 + - Timing-attack countermeasures in _fastmath: when built against libgmp + version 5 or later, we use mpz_powm_sec instead of mpz_powm, which should + prevent the timing attack described by Geremy Condra at PyCon 2011 + - New hash modules (for Python ≥ 2.5 only): SHA224, SHA384 and SHA512 + - Configuration using GNU autoconf, which should help fix a bunch of build + issues + - Support using MPIR as an alternative to GMP + - Improve the test command in setup.py, by allowing tests to be performed on + a single sub-package or module only + - Fix double-decref of "counter" when Cipher object initialization fails + - Apply patches from Debian's python-crypto 2.3-3 package: + - fix-RSA-generate-exception.patch + - epydoc-exclude-introspect.patch + - no-usr-local.patch + - Fix launchpad bug #702835: "Import key code is not compatible with GMP + library" + - More tests, better documentation, various bugfixes +- Update patch for imposing our own compiler optimization flags +- Drop lib64 patch, no longer needed +- No longer need to fix up permissions and remove shellbangs + +* Wed Oct 12 2011 Peter Schiffer - 2.3-5.1 +- Rebuild with new gmp + +* Wed May 11 2011 Paul Howarth - 2.3-5 +- Upstream rolled new tarball with top-level directory restored +- Nobody else likes macros for commands + +* Tue Feb 08 2011 Fedora Release Engineering - 2.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Sep 29 2010 jkeating - 2.3-3 +- Rebuilt for gcc bug 634757 + +* Fri Sep 24 2010 David Malcolm - 2.3-2 +- Add "-fno-strict-aliasing" to compilation flags + +* Fri Aug 27 2010 Paul Howarth - 2.3-1 +- Update to 2.3 + - Fix NameError when attempting to use deprecated getRandomNumber() function + - _slowmath: Compute RSA u parameter when it's not given to RSA.construct; + this makes _slowmath behave the same as _fastmath in this regard + - Make RSA.generate raise a more user-friendly exception message when the + user tries to generate a bogus-length key +- Add -c option to %%setup because upstream tarball has dropped the top-level + directory +- Run benchmark as part of %%check if we have python 2.4 or later +- BR: python2-devel rather than just python-devel +- Add patch to make sure we can find libgmp in 64-bit multilib environments + +* Tue Aug 3 2010 Paul Howarth - 2.2-1 +- Update to 2.2 + - Deprecated Crypto.Util.number.getRandomNumber() + - It's been replaced by getRandomNBitInteger and getRandomInteger + - Better isPrime() and getPrime() implementations + - getStrongPrime() implementation for generating RSA primes + - Support for importing and exporting RSA keys in DER and PEM format + - Fix PyCrypto when floor division (python -Qnew) is enabled + - When building using gcc, use -std=c99 for compilation +- Update optflags patch + +* Thu Jul 22 2010 David Malcolm - 2.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild + +* Tue Feb 16 2010 Paul Howarth - 2.1.0-1 +- Update to 2.1.0 (see ChangeLog for details) +- Remove patches (no longer needed) +- Use new upstream URLs +- Upstream has replaced LICENSE with LEGAL/ and COPYRIGHT +- Clarify that license is mostly Public Domain, partly Python +- Add %%check section and run the test suite in it +- Remove upstream's fiddling with compiler optimization flags so we get + usable debuginfo +- Filter out unwanted provides for python shared objects +- Tidy up egg-info handling +- Simplify %%files list +- Pacify rpmlint as much as is reasonable +- Add dist tag + +* Sun Jul 26 2009 Fedora Release Engineering - 2.0.1-19 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Thu Feb 26 2009 Fedora Release Engineering - 2.0.1-18 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Feb 13 2009 Stewart Adam - 2.0.1-17 +- Use patches in upstream git to fix #484473 + +* Fri Feb 13 2009 Thorsten Leemhuis - 2.0.1-16.1 +- add patch to fix #485298 / CVE-2009-0544 + +* Sat Feb 7 2009 Stewart Adam - 2.0.1-15.1 +- Oops, actually apply the patch +- Modify patch so modules remain compatible with PEP 247 + +* Sat Feb 7 2009 Stewart Adam - 2.0.1-15 +- Add patch to hashlib instead of deprecated md5 and sha modules (#484473) + +* Sat Nov 29 2008 Ignacio Vazquez-Abrams - 2.0.1-14.1 +- Rebuild for Python 2.6 + +* Sun May 04 2008 Thorsten Leemhuis - 2.0.1-13 +- provide pycrypto + +* Sat Feb 09 2008 Thorsten Leemhuis - 2.0.1-12 +- rebuilt + +* Fri Jan 04 2008 Thorsten Leemhuis - 2.0.1-11 +- egg-info file in python_sitearch and not in python_sitelib + +* Fri Jan 04 2008 Thorsten Leemhuis - 2.0.1-10 +- ship egg-file + +* Tue Aug 21 2007 Thorsten Leemhuis - 2.0.1-9 +- Remove the old and outdated python-abi hack + +* Fri Aug 03 2007 Thorsten Leemhuis +- Update License field due to the "Licensing guidelines changes" + +* Mon Jun 04 2007 David Woodhouse - 2.0.1-8 +- Fix libdir handling so it works on more arches than x86_64 + +* Wed Apr 18 2007 Thorsten Leemhuis - 2.0.1-7 +- Fix typo + +* Wed Apr 18 2007 Thorsten Leemhuis - 2.0.1-6 +- Remove dist +- rebuild, because the older version was much bigger, as it was build when + distutils was doing static links of libpython + +* Sat Dec 09 2006 Thorsten Leemhuis - 2.0.1-5 +- Rebuild for python 2.5 + +* Thu Sep 07 2006 Thorsten Leemhuis - 2.0.1-4 +- Don't ghost pyo files (#205408) + +* Tue Aug 29 2006 Thorsten Leemhuis - 2.0.1-3 +- Rebuild for Fedora Extras 6 + +* Mon Feb 13 2006 Thorsten Leemhuis - 2.0.1-2 +- Rebuild for Fedora Extras 5 + +* Wed Aug 17 2005 Thorsten Leemhuis - 0:2.0.1-1 +- Update to 2.0.1 +- Use Dist +- Drop python-crypto-64bit-unclean.patch, similar patch was applied + upstream + +* Thu May 05 2005 Thorsten Leemhuis - 0:2.0-4 +- add python-crypto-64bit-unclean.patch (#156173) + +* Mon Mar 21 2005 Seth Vidal - 0:2.0-3 +- iterate release for build on python 2.4 based systems + +* Sat Dec 18 2004 Thorsten Leemhuis - 0:2.0-2 +- Fix build on x86_64: use python_sitearch for files and patch source + to find gmp + +* Thu Aug 26 2004 Thorsten Leemhuis - 0:2.0-0.fdr.1 +- Update to 2.00 + +* Fri Aug 13 2004 Ville Skytta - 0:1.9-0.fdr.6.a6 +- Don't use get_python_version(), it's available in Python >= 2.3 only. + +* Thu Aug 12 2004 Thorsten Leemhuis 0:1.9-0.fdr.5.a6 +- Own dir python_sitearch/Crypto/ + +* Wed Aug 11 2004 Thorsten Leemhuis 0:1.9-0.fdr.4.a6 +- Match python spec template more + +* Sat Jul 17 2004 Thorsten Leemhuis 0:1.9-0.fdr.3.a6 +- Own _libdir/python/site-packages/Crypto/ + +* Wed Mar 24 2004 Panu Matilainen 0.3.2-0.fdr.2.a6 +- generate .pyo files during install +- require exact version of python used to build the package +- include more docs + demos +- fix dependency on /usr/local/bin/python +- use fedora.us style buildroot +- buildrequires gmp-devel +- use description from README + +* Sun Jan 11 2004 Ryan Boder 0.3.2-0.fdr.1.a6 +- Initial build. +