summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDwayne Litzenberger <dlitz@dlitz.net>2013-02-17 11:21:38 -0800
committerDwayne Litzenberger <dlitz@dlitz.net>2013-02-17 20:07:02 -0800
commitfd398a28e3a227a539b264a9f1e11287b904c7da (patch)
tree9f1628ef88c17604f55ec0ad652b0e1fb3959f38 /lib
parent0d8ea5ff1607a3d7ae544667bff99229954484ff (diff)
downloadpycrypto-fd398a28e3a227a539b264a9f1e11287b904c7da.tar.gz
Hash: Speed up initialization by removing pure-Python wrappershash-speedup-wip
The pure Python wrappers around Crypto.Hash.* were convenient, but they slowed down hash initialization by 4-7x. There is a speed trade-off here: The MD5 and SHA1 objects are just wrapped hashlib objects (or old-style md5/sha objects). To maintain API compatibility with the rest of PyCrypto, we still have to wrap them, so they're slower to initialize than the rest of the hash functions. If hashlib ever adds a .new() method, we will automatically use hashlib directly and gain the initialization speed-up.
Diffstat (limited to 'lib')
-rw-r--r--lib/Crypto/Hash/MD2.py81
-rw-r--r--lib/Crypto/Hash/MD4.py81
-rw-r--r--lib/Crypto/Hash/MD5.py90
-rw-r--r--lib/Crypto/Hash/RIPEMD160.py84
-rw-r--r--lib/Crypto/Hash/SHA1.py91
-rw-r--r--lib/Crypto/Hash/SHA224.py85
-rw-r--r--lib/Crypto/Hash/SHA256.py85
-rw-r--r--lib/Crypto/Hash/SHA384.py86
-rw-r--r--lib/Crypto/Hash/SHA512.py85
-rw-r--r--lib/Crypto/Hash/hashalgo.py120
-rw-r--r--lib/Crypto/SelfTest/Hash/common.py26
-rw-r--r--lib/Crypto/Signature/PKCS1_PSS.py19
12 files changed, 131 insertions, 802 deletions
diff --git a/lib/Crypto/Hash/MD2.py b/lib/Crypto/Hash/MD2.py
deleted file mode 100644
index a2e8b31..0000000
--- a/lib/Crypto/Hash/MD2.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""MD2 cryptographic hash algorithm.
-
-MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.
-
- >>> from Crypto.Hash import MD2
- >>>
- >>> h = MD2.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.
-
-This algorithm is both slow and insecure. Do not use it for new designs.
-
-.. _RFC1319: http://tools.ietf.org/html/rfc1319
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'MD2Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-import Crypto.Hash._MD2 as _MD2
-hashFactory = _MD2
-
-class MD2Hash(HashAlgo):
- """Class that implements an MD2 hash
-
- :undocumented: block_size
- """
-
- digest_size = 16
- block_size = 16
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return MD2Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `MD2Hash.update()`.
- Optional.
-
- :Return: An `MD2Hash` object
- """
- return MD2Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = MD2Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = MD2Hash.block_size
-
diff --git a/lib/Crypto/Hash/MD4.py b/lib/Crypto/Hash/MD4.py
deleted file mode 100644
index 4f0b6bb..0000000
--- a/lib/Crypto/Hash/MD4.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""MD4 cryptographic hash algorithm.
-
-MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
-
- >>> from Crypto.Hash import MD4
- >>>
- >>> h = MD4.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
-
-This algorithm is insecure. Do not use it for new designs.
-
-.. _RFC1320: http://tools.ietf.org/html/rfc1320
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'MD4Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-import Crypto.Hash._MD4 as _MD4
-hashFactory = _MD4
-
-class MD4Hash(HashAlgo):
- """Class that implements an MD4 hash
-
- :undocumented: block_size
- """
-
- digest_size = 16
- block_size = 64
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return MD4Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `MD4Hash.update()`.
- Optional.
-
- :Return: A `MD4Hash` object
- """
- return MD4Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = MD4Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = MD4Hash.block_size
-
diff --git a/lib/Crypto/Hash/MD5.py b/lib/Crypto/Hash/MD5.py
index 2e6a01b..c5df793 100644
--- a/lib/Crypto/Hash/MD5.py
+++ b/lib/Crypto/Hash/MD5.py
@@ -35,54 +35,58 @@ This algorithm is insecure. Do not use it for new designs.
.. _RFC1321: http://tools.ietf.org/html/rfc1321
"""
+from __future__ import nested_scopes
+
_revision__ = "$Id$"
-__all__ = ['new', 'digest_size', 'MD5Hash' ]
+__all__ = ['new', 'block_size', 'digest_size']
from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- # The md5 module is deprecated in Python 2.6, so use hashlib when possible.
- import hashlib
- hashFactory = hashlib.md5
-
-except ImportError:
- import md5
- hashFactory = md5
-
-class MD5Hash(HashAlgo):
- """Class that implements an MD5 hash
-
- :undocumented: block_size
- """
-
- digest_size = 16
- block_size = 64
-
- def __init__(self, data=None):
- self.name = "MD5"
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return MD5Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `MD5Hash.update()`.
- Optional.
-
- :Return: A `MD5Hash` object
- """
- return MD5Hash().new(data)
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+def __make_constructor():
+ try:
+ # The md5 module is deprecated in Python 2.6, so use hashlib when possible.
+ from hashlib import md5 as _hash_new
+ except ImportError:
+ from md5 import new as _hash_new
+
+ h = _hash_new()
+ if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
+ # The module from stdlib has the API that we need. Just use it.
+ return _hash_new
+ else:
+ # Wrap the hash object in something that gives us the expected API.
+ _copy_sentinel = object()
+ class _MD5(object):
+ digest_size = 16
+ block_size = 64
+ name = "md5"
+ def __init__(self, *args):
+ if args and args[0] is _copy_sentinel:
+ self._h = args[1]
+ else:
+ self._h = _hash_new(*args)
+ def copy(self):
+ return _MD5(_copy_sentinel, self._h.copy())
+ def update(self, *args):
+ f = self.update = self._h.update
+ f(*args)
+ def digest(self):
+ f = self.digest = self._h.digest
+ return f()
+ def hexdigest(self):
+ f = self.hexdigest = self._h.hexdigest
+ return f()
+ _MD5.new = _MD5
+ return _MD5
+
+new = __make_constructor()
+del __make_constructor
#: The size of the resulting hash in bytes.
-digest_size = MD5Hash.digest_size
+digest_size = new().digest_size
#: The internal block size of the hash algorithm in bytes.
-block_size = MD5Hash.block_size
-
+block_size = new().block_size
diff --git a/lib/Crypto/Hash/RIPEMD160.py b/lib/Crypto/Hash/RIPEMD160.py
deleted file mode 100644
index 2bfb26d..0000000
--- a/lib/Crypto/Hash/RIPEMD160.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""RIPEMD-160 cryptographic hash algorithm.
-
-RIPEMD-160_ produces the 160 bit digest of a message.
-
- >>> from Crypto.Hash import RIPEMD160
- >>>
- >>> h = RIPEMD160.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest
-with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.
-
-This algorithm is considered secure, although it has not been scrutinized as
-extensively as SHA-1. Moreover, it provides an informal security level of just
-80bits.
-
-.. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'RIPEMD160Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-import Crypto.Hash._RIPEMD160 as _RIPEMD160
-hashFactory = _RIPEMD160
-
-class RIPEMD160Hash(HashAlgo):
- """Class that implements a RIPMD-160 hash
-
- :undocumented: block_size
- """
-
- digest_size = 20
- block_size = 64
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return RIPEMD160Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `RIPEMD160Hash.update()`.
- Optional.
-
- :Return: A `RIPEMD160Hash` object
- """
- return RIPEMD160Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = RIPEMD160Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = RIPEMD160Hash.block_size
-
diff --git a/lib/Crypto/Hash/SHA1.py b/lib/Crypto/Hash/SHA1.py
index afddf1a..9ad9f1e 100644
--- a/lib/Crypto/Hash/SHA1.py
+++ b/lib/Crypto/Hash/SHA1.py
@@ -35,55 +35,58 @@ This algorithm is not considered secure. Do not use it for new designs.
.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
"""
+from __future__ import nested_scopes
+
_revision__ = "$Id$"
-__all__ = ['new', 'digest_size', 'SHA1Hash' ]
+__all__ = ['new', 'block_size', 'digest_size']
from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- # The sha module is deprecated in Python 2.6, so use hashlib when possible.
- import hashlib
- hashFactory = hashlib.sha1
-
-except ImportError:
- import sha
- hashFactory = sha
-
-class SHA1Hash(HashAlgo):
- """Class that implements a SHA-1 hash
-
- :undocumented: block_size
- """
-
- digest_size = 20
- block_size = 64
-
- def __init__(self, data=None):
- self.name = "SHA1"
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return SHA1Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `SHA1Hash.update()`.
- Optional.
-
- :Return: A `SHA1Hash` object
- """
- return SHA1Hash().new(data)
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
+
+def __make_constructor():
+ try:
+ # The sha module is deprecated in Python 2.6, so use hashlib when possible.
+ from hashlib import sha1 as _hash_new
+ except ImportError:
+ from sha import new as _hash_new
+
+ h = _hash_new()
+ if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
+ # The module from stdlib has the API that we need. Just use it.
+ return _hash_new
+ else:
+ # Wrap the hash object in something that gives us the expected API.
+ _copy_sentinel = object()
+ class _SHA1(object):
+ digest_size = 20
+ block_size = 64
+ name = "sha1"
+ def __init__(self, *args):
+ if args and args[0] is _copy_sentinel:
+ self._h = args[1]
+ else:
+ self._h = _hash_new(*args)
+ def copy(self):
+ return _SHA1(_copy_sentinel, self._h.copy())
+ def update(self, *args):
+ f = self.update = self._h.update
+ f(*args)
+ def digest(self):
+ f = self.digest = self._h.digest
+ return f()
+ def hexdigest(self):
+ f = self.hexdigest = self._h.hexdigest
+ return f()
+ _SHA1.new = _SHA1
+ return _SHA1
+
+new = __make_constructor()
+del __make_constructor
#: The size of the resulting hash in bytes.
-digest_size = SHA1Hash.digest_size
+digest_size = new().digest_size
#: The internal block size of the hash algorithm in bytes.
-block_size = SHA1Hash.block_size
-
-
+block_size = new().block_size
diff --git a/lib/Crypto/Hash/SHA224.py b/lib/Crypto/Hash/SHA224.py
deleted file mode 100644
index 379bbb2..0000000
--- a/lib/Crypto/Hash/SHA224.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""SHA-224 cryptographic hash algorithm.
-
-SHA-224 belongs to the SHA-2_ family of cryptographic hashes.
-It produces the 224 bit digest of a message.
-
- >>> from Crypto.Hash import SHA224
- >>>
- >>> h = SHA224.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-*SHA* stands for Secure Hash Algorithm.
-
-.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'SHA224Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- import hashlib
- hashFactory = hashlib.sha224
-
-except ImportError:
- from Crypto.Hash import _SHA224
- hashFactory = _SHA224
-
-class SHA224Hash(HashAlgo):
- """Class that implements a SHA-224 hash
-
- :undocumented: block_size
- """
-
- digest_size = 28
- block_size = 64
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return SHA224Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `SHA224Hash.update()`.
- Optional.
-
- :Return: A `SHA224Hash` object
- """
- return SHA224Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = SHA224Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = SHA224Hash.block_size
-
diff --git a/lib/Crypto/Hash/SHA256.py b/lib/Crypto/Hash/SHA256.py
deleted file mode 100644
index 46b7861..0000000
--- a/lib/Crypto/Hash/SHA256.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""SHA-256 cryptographic hash algorithm.
-
-SHA-256 belongs to the SHA-2_ family of cryptographic hashes.
-It produces the 256 bit digest of a message.
-
- >>> from Crypto.Hash import SHA256
- >>>
- >>> h = SHA256.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-*SHA* stands for Secure Hash Algorithm.
-
-.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'SHA256Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- import hashlib
- hashFactory = hashlib.sha256
-
-except ImportError:
- from Crypto.Hash import _SHA256
- hashFactory = _SHA256
-
-class SHA256Hash(HashAlgo):
- """Class that implements a SHA-256 hash
-
- :undocumented: block_size
- """
-
- digest_size = 32
- block_size = 64
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return SHA256Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `SHA256Hash.update()`.
- Optional.
-
- :Return: A `SHA256Hash` object
- """
- return SHA256Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = SHA256Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = SHA256Hash.block_size
-
diff --git a/lib/Crypto/Hash/SHA384.py b/lib/Crypto/Hash/SHA384.py
deleted file mode 100644
index da6aca1..0000000
--- a/lib/Crypto/Hash/SHA384.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""SHA-384 cryptographic hash algorithm.
-
-SHA-384 belongs to the SHA-2_ family of cryptographic hashes.
-It produces the 384 bit digest of a message.
-
- >>> from Crypto.Hash import SHA384
- >>>
- >>> h = SHA384.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-*SHA* stands for Secure Hash Algorithm.
-
-.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'SHA384Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- import hashlib
- hashFactory = hashlib.sha384
-
-except ImportError:
- from Crypto.Hash import _SHA384
- hashFactory = _SHA384
-
-class SHA384Hash(HashAlgo):
- """Class that implements a SHA-384 hash
-
- :undocumented: block_size
- """
-
- digest_size = 48
- block_size = 128
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return SHA384Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `SHA384Hash.update()`.
- Optional.
-
- :Return: A `SHA384Hash` object
- """
- return SHA384Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = SHA384Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = SHA384Hash.block_size
-
-
diff --git a/lib/Crypto/Hash/SHA512.py b/lib/Crypto/Hash/SHA512.py
deleted file mode 100644
index d8a4c3a..0000000
--- a/lib/Crypto/Hash/SHA512.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-"""SHA-512 cryptographic hash algorithm.
-
-SHA-512 belongs to the SHA-2_ family of cryptographic hashes.
-It produces the 512 bit digest of a message.
-
- >>> from Crypto.Hash import SHA512
- >>>
- >>> h = SHA512.new()
- >>> h.update(b'Hello')
- >>> print h.hexdigest()
-
-*SHA* stands for Secure Hash Algorithm.
-
-.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
-"""
-
-_revision__ = "$Id$"
-
-__all__ = ['new', 'digest_size', 'SHA512Hash' ]
-
-from Crypto.Util.py3compat import *
-from Crypto.Hash.hashalgo import HashAlgo
-
-try:
- import hashlib
- hashFactory = hashlib.sha512
-
-except ImportError:
- from Crypto.Hash import _SHA512
- hashFactory = _SHA512
-
-class SHA512Hash(HashAlgo):
- """Class that implements a SHA-512 hash
-
- :undocumented: block_size
- """
-
- digest_size = 64
- block_size = 128
-
- def __init__(self, data=None):
- HashAlgo.__init__(self, hashFactory, data)
-
- def new(self, data=None):
- return SHA512Hash(data)
-
-def new(data=None):
- """Return a fresh instance of the hash object.
-
- :Parameters:
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `SHA512Hash.update()`.
- Optional.
-
- :Return: A `SHA512Hash` object
- """
- return SHA512Hash().new(data)
-
-#: The size of the resulting hash in bytes.
-digest_size = SHA512Hash.digest_size
-
-#: The internal block size of the hash algorithm in bytes.
-block_size = SHA512Hash.block_size
-
diff --git a/lib/Crypto/Hash/hashalgo.py b/lib/Crypto/Hash/hashalgo.py
deleted file mode 100644
index a778bf4..0000000
--- a/lib/Crypto/Hash/hashalgo.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# ===================================================================
-# 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.
-# ===================================================================
-
-from binascii import hexlify
-
-class HashAlgo:
- """A generic class for an abstract cryptographic hash algorithm.
-
- :undocumented: block_size
- """
-
- #: The size of the resulting hash in bytes.
- digest_size = None
- #: The internal block size of the hash algorithm in bytes.
- block_size = None
-
- def __init__(self, hashFactory, data=None):
- """Initialize the hash object.
-
- :Parameters:
- hashFactory : callable
- An object that will generate the actual hash implementation.
- *hashFactory* must have a *new()* method, or must be directly
- callable.
- data : byte string
- The very first chunk of the message to hash.
- It is equivalent to an early call to `update()`.
- """
- if hasattr(hashFactory, 'new'):
- self._hash = hashFactory.new()
- else:
- self._hash = hashFactory()
- try:
- self.name = self._hash.name
- except AttributeError:
- pass
- if data:
- self.update(data)
-
- def update(self, data):
- """Continue hashing of a message by consuming the next chunk of data.
-
- Repeated calls are equivalent to a single call with the concatenation
- of all the arguments. In other words:
-
- >>> m.update(a); m.update(b)
-
- is equivalent to:
-
- >>> m.update(a+b)
-
- :Parameters:
- data : byte string
- The next chunk of the message being hashed.
- """
- return self._hash.update(data)
-
- def digest(self):
- """Return the **binary** (non-printable) digest of the message that has been hashed so far.
-
- This method does not change the state of the hash object.
- You can continue updating the object after calling this function.
-
- :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
- characters, including null bytes.
- """
- return self._hash.digest()
-
- def hexdigest(self):
- """Return the **printable** digest of the message that has been hashed so far.
-
- This method does not change the state of the hash object.
-
- :Return: A string of 2* `digest_size` characters. It contains only
- hexadecimal ASCII digits.
- """
- return self._hash.hexdigest()
-
- def copy(self):
- """Return a copy ("clone") of the hash object.
-
- The copy will have the same internal state as the original hash
- object.
- This can be used to efficiently compute the digests of strings that
- share a common initial substring.
-
- :Return: A hash object of the same type
- """
- return self._hash.copy()
-
- def new(self, data=None):
- """Return a fresh instance of the hash object.
-
- Unlike the `copy` method, the internal state of the object is empty.
-
- :Parameters:
- data : byte string
- The next chunk of the message being hashed.
-
- :Return: A hash object of the same type
- """
- pass
-
diff --git a/lib/Crypto/SelfTest/Hash/common.py b/lib/Crypto/SelfTest/Hash/common.py
index 487e2cb..e722800 100644
--- a/lib/Crypto/SelfTest/Hash/common.py
+++ b/lib/Crypto/SelfTest/Hash/common.py
@@ -31,6 +31,8 @@ import unittest
import binascii
import Crypto.Hash
from Crypto.Util.py3compat import *
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
+ from Crypto.Util.py21compat import *
# For compatibility with Python 2.1 and Python 2.2
if sys.hexversion < 0x02030000:
@@ -95,11 +97,14 @@ class HashSelfTest(unittest.TestCase):
self.assertEqual(self.expected.decode(), out3) # h = .new(data); h.hexdigest()
self.assertEqual(self.expected, out4) # h = .new(data); h.digest()
- # Verify that new() object method produces a fresh hash object
- h2 = h.new()
- h2.update(self.input)
- out5 = binascii.b2a_hex(h2.digest())
- self.assertEqual(self.expected, out5)
+ # Verify that the .new() method produces a fresh hash object, except
+ # for MD5 and SHA1, which are hashlib objects. (But test any .new()
+ # method that does exist.)
+ if self.hashmod.__name__ not in ('Crypto.Hash.MD5', 'Crypto.Hash.SHA1') or hasattr(h, 'new'):
+ h2 = h.new()
+ h2.update(self.input)
+ out5 = binascii.b2a_hex(h2.digest())
+ self.assertEqual(self.expected, out5)
# Verify that Crypto.Hash.new(h) produces a fresh hash object
h3 = Crypto.Hash.new(h)
@@ -125,6 +130,16 @@ class HashTestOID(unittest.TestCase):
h = self.hashmod.new()
self.assertEqual(PKCS1_v1_5._HASH_OIDS[h.name], self.oid)
+class HashDocStringTest(unittest.TestCase):
+ def __init__(self, hashmod):
+ unittest.TestCase.__init__(self)
+ self.hashmod = hashmod
+
+ def runTest(self):
+ docstring = self.hashmod.__doc__
+ self.assert_(hasattr(self.hashmod, '__doc__'))
+ self.assert_(isinstance(self.hashmod.__doc__, str))
+
class GenericHashConstructorTest(unittest.TestCase):
def __init__(self, hashmod):
unittest.TestCase.__init__(self)
@@ -208,6 +223,7 @@ def make_hash_tests(module, module_name, test_data, digest_size, oid=None):
tests.append(HashDigestSizeSelfTest(module, name, digest_size))
if oid is not None:
tests.append(HashTestOID(module, b(oid)))
+ tests.append(HashDocStringTest(module))
if getattr(module, 'name', None) is not None:
tests.append(GenericHashConstructorTest(module))
return tests
diff --git a/lib/Crypto/Signature/PKCS1_PSS.py b/lib/Crypto/Signature/PKCS1_PSS.py
index cd9eaf3..3840959 100644
--- a/lib/Crypto/Signature/PKCS1_PSS.py
+++ b/lib/Crypto/Signature/PKCS1_PSS.py
@@ -72,6 +72,7 @@ if sys.version_info[0] == 2 and sys.version_info[1] == 1:
import Crypto.Util.number
from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes
from Crypto.Util.strxor import strxor
+from Crypto.Hash import new as Hash_new
class PSS_SigScheme:
"""This signature scheme can perform PKCS#1 PSS RSA signature or verification."""
@@ -203,7 +204,11 @@ def MGF1(mgfSeed, maskLen, hash):
T = b("")
for counter in xrange(ceil_div(maskLen, hash.digest_size)):
c = long_to_bytes(counter, 4)
- T = T + hash.new(mgfSeed + c).digest()
+ try:
+ T = T + hash.new(mgfSeed + c).digest()
+ except AttributeError:
+ # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
+ T = T + Hash_new(hash, mgfSeed + c).digest()
assert(len(T)>=maskLen)
return T[:maskLen]
@@ -253,7 +258,11 @@ def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen):
if randFunc and sLen>0:
salt = randFunc(sLen)
# Step 5 and 6
- h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
+ try:
+ h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt)
+ except AttributeError:
+ # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
+ h = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt)
# Step 7 and 8
db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt
# Step 9
@@ -328,7 +337,11 @@ def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen):
salt = b("")
if sLen: salt = db[-sLen:]
# Step 12 and 13
- hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
+ try:
+ hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest()
+ except AttributeError:
+ # hash object doesn't have a "new" method. Use Crypto.Hash.new() to instantiate it
+ hp = Hash_new(mhash, bchr(0x00)*8 + mhash.digest() + salt).digest()
# Step 14
if h!=hp:
return False