summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwayne Litzenberger <dlitz@dlitz.net>2013-04-21 20:39:56 -0700
committerDwayne Litzenberger <dlitz@dlitz.net>2013-04-21 20:39:56 -0700
commit6dbfccadecc55c203dd76f9e504c94ba042ec12f (patch)
tree6ddab8a0dddcab7d92783428068c373679146d6c
parentce92486a1d8a4abbff2d40b2be737ca09dd98c6a (diff)
parentfd398a28e3a227a539b264a9f1e11287b904c7da (diff)
downloadpycrypto-6dbfccadecc55c203dd76f9e504c94ba042ec12f.tar.gz
Merge branch 'hash-speedup-wip'
-rw-r--r--lib/Crypto/Hash/MD2.py91
-rw-r--r--lib/Crypto/Hash/MD4.py91
-rw-r--r--lib/Crypto/Hash/MD5.py99
-rw-r--r--lib/Crypto/Hash/RIPEMD160.py94
-rw-r--r--lib/Crypto/Hash/SHA1.py100
-rw-r--r--lib/Crypto/Hash/SHA224.py95
-rw-r--r--lib/Crypto/Hash/SHA256.py95
-rw-r--r--lib/Crypto/Hash/SHA384.py96
-rw-r--r--lib/Crypto/Hash/SHA512.py95
-rw-r--r--lib/Crypto/Hash/__init__.py119
-rw-r--r--lib/Crypto/Hash/hashalgo.py116
-rw-r--r--lib/Crypto/Random/Fortuna/FortunaGenerator.py2
-rw-r--r--lib/Crypto/SelfTest/Hash/common.py77
-rw-r--r--lib/Crypto/Signature/PKCS1_PSS.py19
-rw-r--r--lib/Crypto/Signature/PKCS1_v1_5.py72
-rw-r--r--pct-speedtest.py80
-rw-r--r--setup.py14
-rw-r--r--src/AES.c2
-rw-r--r--src/ARC2.c2
-rw-r--r--src/Blowfish.c2
-rw-r--r--src/DES.c3
-rw-r--r--src/MD2.c30
-rw-r--r--src/MD4.c21
-rw-r--r--src/RIPEMD160.c25
-rw-r--r--src/SHA224.c18
-rw-r--r--src/SHA256.c20
-rw-r--r--src/SHA384.c18
-rw-r--r--src/SHA512.c18
-rw-r--r--src/_counter.c3
-rw-r--r--src/_counter.h2
-rw-r--r--src/_fastmath.c2
-rw-r--r--src/block_template.c2
-rw-r--r--src/hash_SHA2.h2
-rw-r--r--src/hash_template.c24
-rw-r--r--src/stream_template.c2
35 files changed, 602 insertions, 949 deletions
diff --git a/lib/Crypto/Hash/MD2.py b/lib/Crypto/Hash/MD2.py
deleted file mode 100644
index dac959e..0000000
--- a/lib/Crypto/Hash/MD2.py
+++ /dev/null
@@ -1,91 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-md2 OBJECT IDENTIFIER ::= {
- #: iso(1) member-body(2) us(840) rsadsi(113549)
- #: digestAlgorithm(2) 2
- #: }
- #:
- #: This value uniquely identifies the MD2 algorithm.
- oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02')
-
- 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 e28a201..0000000
--- a/lib/Crypto/Hash/MD4.py
+++ /dev/null
@@ -1,91 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-md2 OBJECT IDENTIFIER ::= {
- #: iso(1) member-body(2) us(840) rsadsi(113549)
- #: digestAlgorithm(2) 4
- #: }
- #:
- #: This value uniquely identifies the MD4 algorithm.
- oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04')
-
- 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 18e9e7b..c5df793 100644
--- a/lib/Crypto/Hash/MD5.py
+++ b/lib/Crypto/Hash/MD5.py
@@ -35,63 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-md5 OBJECT IDENTIFIER ::= {
- #: iso(1) member-body(2) us(840) rsadsi(113549)
- #: digestAlgorithm(2) 5
- #: }
- #:
- #: This value uniquely identifies the MD5 algorithm.
- oid = b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05')
-
- digest_size = 16
- block_size = 64
-
- def __init__(self, data=None):
- 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 3abed5d..0000000
--- a/lib/Crypto/Hash/RIPEMD160.py
+++ /dev/null
@@ -1,94 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-ripemd160 OBJECT IDENTIFIER ::= {
- #: iso(1) identified-organization(3) teletrust(36)
- #: algorithm(3) hashAlgorithm(2) ripemd160(1)
- #: }
- #:
- #: This value uniquely identifies the RIPMD-160 algorithm.
- oid = b("\x06\x05\x2b\x24\x03\x02\x01")
-
- 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 334ae18..9ad9f1e 100644
--- a/lib/Crypto/Hash/SHA1.py
+++ b/lib/Crypto/Hash/SHA1.py
@@ -35,64 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-sha1 OBJECT IDENTIFIER ::= {
- #: iso(1) identified-organization(3) oiw(14) secsig(3)
- #: algorithms(2) 26
- #: }
- #:
- #: This value uniquely identifies the SHA-1 algorithm.
- oid = b('\x06\x05\x2b\x0e\x03\x02\x1a')
-
- digest_size = 20
- block_size = 64
-
- def __init__(self, data=None):
- 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 959b56d..0000000
--- a/lib/Crypto/Hash/SHA224.py
+++ /dev/null
@@ -1,95 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-sha224 OBJECT IDENTIFIER ::= {
- #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
- #: nistalgorithm(4) hashalgs(2) 4
- #: }
- #:
- #: This value uniquely identifies the SHA-224 algorithm.
- oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04')
-
- 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 b0a99b3..0000000
--- a/lib/Crypto/Hash/SHA256.py
+++ /dev/null
@@ -1,95 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-sha256 OBJECT IDENTIFIER ::= {
- #: joint-iso-itu-t(2) country(16) us(840) organization(1)
- #: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
- #: }
- #:
- #: This value uniquely identifies the SHA-256 algorithm.
- oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01')
-
- 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 3490b02..0000000
--- a/lib/Crypto/Hash/SHA384.py
+++ /dev/null
@@ -1,96 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-sha384 OBJECT IDENTIFIER ::= {
- #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
- #: nistalgorithm(4) hashalgs(2) 2
- #: }
- #:
- #: This value uniquely identifies the SHA-384 algorithm.
- oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02')
-
- 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 d57548d..0000000
--- a/lib/Crypto/Hash/SHA512.py
+++ /dev/null
@@ -1,95 +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
- """
-
- #: ASN.1 Object identifier (OID)::
- #:
- #: id-sha512 OBJECT IDENTIFIER ::= {
- #: joint-iso-itu-t(2)
- #: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
- #: }
- #:
- #: This value uniquely identifies the SHA-512 algorithm.
- oid = b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03')
-
- 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/__init__.py b/lib/Crypto/Hash/__init__.py
index b9f9525..1050c78 100644
--- a/lib/Crypto/Hash/__init__.py
+++ b/lib/Crypto/Hash/__init__.py
@@ -53,4 +53,123 @@ __all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
'SHA224', 'SHA256', 'SHA384', 'SHA512']
__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 *
+def new(algo, *args):
+ """Initialize a new hash object.
+
+ The first argument to this function may be an algorithm name or another
+ hash object.
+
+ This function has significant overhead. It's recommended that you instead
+ import and use the individual hash modules directly.
+ """
+
+ # Try just invoking algo.new()
+ # We do this first so that this is the fastest.
+ try:
+ new_func = algo.new
+ except AttributeError:
+ pass
+ else:
+ return new_func(*args)
+
+ # Try getting the algorithm name.
+ if isinstance(algo, str):
+ name = algo
+ else:
+ try:
+ name = algo.name
+ except AttributeError:
+ raise ValueError("unsupported hash type %r" % (algo,))
+
+ # Got the name. Let's see if we have a PyCrypto implementation.
+ try:
+ new_func = _new_funcs[name]
+ except KeyError:
+ # No PyCrypto implementation. Try hashlib.
+ try:
+ import hashlib
+ except ImportError:
+ # There is no hashlib.
+ raise ValueError("unsupported hash type %s" % (name,))
+ return hashlib.new(name, *args)
+ else:
+ # We have a PyCrypto implementation. Instantiate it.
+ return new_func(*args)
+
+# This dict originally gets the following _*_new methods, but its members get
+# replaced with the real new() methods of the various hash modules as they are
+# used. We do it without locks to improve performance, which is safe in
+# CPython because dict access is atomic in CPython. This might break PyPI.
+_new_funcs = {}
+
+def _md2_new(*args):
+ from Crypto.Hash import MD2
+ _new_funcs['MD2'] = _new_funcs['md2'] = MD2.new
+ return MD2.new(*args)
+_new_funcs['MD2'] = _new_funcs['md2'] = _md2_new
+del _md2_new
+
+def _md4_new(*args):
+ from Crypto.Hash import MD4
+ _new_funcs['MD4'] = _new_funcs['md4'] = MD4.new
+ return MD4.new(*args)
+_new_funcs['MD4'] = _new_funcs['md4'] = _md4_new
+del _md4_new
+
+def _md5_new(*args):
+ from Crypto.Hash import MD5
+ _new_funcs['MD5'] = _new_funcs['md5'] = MD5.new
+ return MD5.new(*args)
+_new_funcs['MD5'] = _new_funcs['md5'] = _md5_new
+del _md5_new
+
+def _ripemd160_new(*args):
+ from Crypto.Hash import RIPEMD160
+ _new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
+ _new_funcs['RIPEMD'] = _new_funcs['ripemd'] = RIPEMD160.new
+ return RIPEMD160.new(*args)
+_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
+ _new_funcs['RIPEMD'] = _new_funcs['ripemd'] = _ripemd160_new
+del _ripemd160_new
+
+def _sha1_new(*args):
+ from Crypto.Hash import SHA1
+ _new_funcs['SHA1'] = _new_funcs['sha1'] = \
+ _new_funcs['SHA'] = _new_funcs['sha'] = SHA1.new
+ return SHA1.new(*args)
+_new_funcs['SHA1'] = _new_funcs['sha1'] = \
+ _new_funcs['SHA'] = _new_funcs['sha'] = _sha1_new
+del _sha1_new
+
+def _sha224_new(*args):
+ from Crypto.Hash import SHA224
+ _new_funcs['SHA224'] = _new_funcs['sha224'] = SHA224.new
+ return SHA224.new(*args)
+_new_funcs['SHA224'] = _new_funcs['sha224'] = _sha224_new
+del _sha224_new
+
+def _sha256_new(*args):
+ from Crypto.Hash import SHA256
+ _new_funcs['SHA256'] = _new_funcs['sha256'] = SHA256.new
+ return SHA256.new(*args)
+_new_funcs['SHA256'] = _new_funcs['sha256'] = _sha256_new
+del _sha256_new
+
+def _sha384_new(*args):
+ from Crypto.Hash import SHA384
+ _new_funcs['SHA384'] = _new_funcs['sha384'] = SHA384.new
+ return SHA384.new(*args)
+_new_funcs['SHA384'] = _new_funcs['sha384'] = _sha384_new
+del _sha384_new
+
+def _sha512_new(*args):
+ from Crypto.Hash import SHA512
+ _new_funcs['SHA512'] = _new_funcs['sha512'] = SHA512.new
+ return SHA512.new(*args)
+_new_funcs['SHA512'] = _new_funcs['sha512'] = _sha512_new
+del _sha512_new
diff --git a/lib/Crypto/Hash/hashalgo.py b/lib/Crypto/Hash/hashalgo.py
deleted file mode 100644
index b38b3a6..0000000
--- a/lib/Crypto/Hash/hashalgo.py
+++ /dev/null
@@ -1,116 +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()
- 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/Random/Fortuna/FortunaGenerator.py b/lib/Crypto/Random/Fortuna/FortunaGenerator.py
index 723fa63..09351fc 100644
--- a/lib/Crypto/Random/Fortuna/FortunaGenerator.py
+++ b/lib/Crypto/Random/Fortuna/FortunaGenerator.py
@@ -25,7 +25,7 @@
__revision__ = "$Id$"
import sys
-if sys.version_info[0] is 2 and sys.version_info[1] is 1:
+if sys.version_info[0] == 2 and sys.version_info[1] == 1:
from Crypto.Util.py21compat import *
from Crypto.Util.py3compat import *
diff --git a/lib/Crypto/SelfTest/Hash/common.py b/lib/Crypto/SelfTest/Hash/common.py
index f77fb0f..e722800 100644
--- a/lib/Crypto/SelfTest/Hash/common.py
+++ b/lib/Crypto/SelfTest/Hash/common.py
@@ -29,7 +29,10 @@ __revision__ = "$Id$"
import sys
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:
@@ -94,11 +97,27 @@ 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)
+ h3.update(self.input)
+ out6 = binascii.b2a_hex(h3.digest())
+ self.assertEqual(self.expected, out6)
+
+ if hasattr(h, 'name'):
+ # Verify that Crypto.Hash.new(h.name) produces a fresh hash object
+ h4 = Crypto.Hash.new(h.name)
+ h4.update(self.input)
+ out7 = binascii.b2a_hex(h4.digest())
+ self.assertEqual(self.expected, out7)
class HashTestOID(unittest.TestCase):
def __init__(self, hashmod, oid):
@@ -107,16 +126,38 @@ class HashTestOID(unittest.TestCase):
self.oid = oid
def runTest(self):
+ from Crypto.Signature import PKCS1_v1_5
h = self.hashmod.new()
- if self.oid==None:
- try:
- raised = 0
- a = h.oid
- except AttributeError:
- raised = 1
- self.assertEqual(raised,1)
- else:
- self.assertEqual(h.oid, self.oid)
+ 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)
+ self.hashmod = hashmod
+
+ def runTest(self):
+ obj1 = self.hashmod.new("foo")
+ obj2 = self.hashmod.new()
+ obj3 = Crypto.Hash.new(obj1.name, "foo")
+ obj4 = Crypto.Hash.new(obj1.name)
+ obj5 = Crypto.Hash.new(obj1, "foo")
+ obj6 = Crypto.Hash.new(obj1)
+ self.assert_(isinstance(self.hashmod, obj1))
+ self.assert_(isinstance(self.hashmod, obj2))
+ self.assert_(isinstance(self.hashmod, obj3))
+ self.assert_(isinstance(self.hashmod, obj4))
+ self.assert_(isinstance(self.hashmod, obj5))
+ self.assert_(isinstance(self.hashmod, obj6))
class MACSelfTest(unittest.TestCase):
@@ -178,11 +219,13 @@ def make_hash_tests(module, module_name, test_data, digest_size, oid=None):
description = row[2].encode('latin-1')
name = "%s #%d: %s" % (module_name, i+1, description)
tests.append(HashSelfTest(module, name, expected, input))
- if oid is not None:
- oid = b(oid)
name = "%s #%d: digest_size" % (module_name, i+1)
tests.append(HashDigestSizeSelfTest(module, name, digest_size))
- tests.append(HashTestOID(module, oid))
+ 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
def make_mac_tests(module, module_name, test_data, hashmods):
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
diff --git a/lib/Crypto/Signature/PKCS1_v1_5.py b/lib/Crypto/Signature/PKCS1_v1_5.py
index 73ac251..22bb340 100644
--- a/lib/Crypto/Signature/PKCS1_v1_5.py
+++ b/lib/Crypto/Signature/PKCS1_v1_5.py
@@ -208,7 +208,7 @@ def EMSA_PKCS1_V1_5_ENCODE(hash, emLen):
# { OID id-sha512 PARAMETERS NULL }
# }
#
- digestAlgo = DerSequence([hash.oid, DerNull().encode()])
+ digestAlgo = DerSequence([_HASH_OIDS[hash.name], DerNull().encode()])
digest = DerOctetString(hash.digest())
digestInfo = DerSequence([
digestAlgo.encode(),
@@ -234,3 +234,73 @@ def new(key):
"""
return PKCS115_SigScheme(key)
+# AlgorithmIdentifier OIDs for use with PKCS#1 v1.5.
+#
+# These map names to the associated OIDs. We should try to be compatible
+# with the standard library's hashlib modules, where possible.
+#
+# XXX - These will probably be moved somewhere else soon.
+_HASH_OIDS = {
+ #: id-md2 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 2
+ #: }
+ "MD2": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02'),
+ "md2": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02'),
+
+ #: id-md4 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 4
+ #: }
+ "MD4": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04'),
+ "md4": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x04'),
+
+ #: id-md5 OBJECT IDENTIFIER ::= {
+ #: iso(1) member-body(2) us(840) rsadsi(113549)
+ #: digestAlgorithm(2) 5
+ #: }
+ "MD5": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05'),
+ "md5": b('\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05'),
+
+ #: id-ripemd160 OBJECT IDENTIFIER ::= {
+ #: iso(1) identified-organization(3) teletrust(36)
+ #: algorithm(3) hashAlgorithm(2) ripemd160(1)
+ #: }
+ "RIPEMD160": b("\x06\x05\x2b\x24\x03\x02\x01"),
+ "ripemd160": b("\x06\x05\x2b\x24\x03\x02\x01"),
+
+ #: id-sha1 OBJECT IDENTIFIER ::= {
+ #: iso(1) identified-organization(3) oiw(14) secsig(3)
+ #: algorithms(2) 26
+ #: }
+ "SHA1": b('\x06\x05\x2b\x0e\x03\x02\x1a'),
+ "sha1": b('\x06\x05\x2b\x0e\x03\x02\x1a'),
+
+ #: id-sha224 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
+ #: nistalgorithm(4) hashalgs(2) 4
+ #: }
+ "SHA224": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04'),
+ "sha224": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04'),
+
+ #: id-sha256 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1)
+ #: gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
+ #: }
+ "SHA256": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01'),
+ "sha256": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01'),
+
+ #: id-sha384 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3)
+ #: nistalgorithm(4) hashalgs(2) 2
+ #: }
+ "SHA384": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02'),
+ "sha384": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02'),
+
+ #: id-sha512 OBJECT IDENTIFIER ::= {
+ #: joint-iso-itu-t(2)
+ #: country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
+ #: }
+ "SHA512": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03'),
+ "sha512": b('\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03'),
+}
diff --git a/pct-speedtest.py b/pct-speedtest.py
index eb2778f..bd099ce 100644
--- a/pct-speedtest.py
+++ b/pct-speedtest.py
@@ -28,10 +28,17 @@ import os
import sys
from Crypto.PublicKey import RSA
+from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5 as RSAES_PKCS1_v1_5
+from Crypto.Signature import PKCS1_PSS, PKCS1_v1_5 as RSASSA_PKCS1_v1_5
from Crypto.Cipher import AES, ARC2, ARC4, Blowfish, CAST, DES3, DES, XOR
-from Crypto.Hash import HMAC, MD2, MD4, MD5, SHA, SHA224, SHA256, SHA384, SHA512
+from Crypto.Hash import HMAC, MD2, MD4, MD5, SHA224, SHA256, SHA384, SHA512
from Crypto.Random import get_random_bytes
try:
+ from Crypto.Hash import SHA1
+except ImportError:
+ # Maybe it's called SHA
+ from Crypto.Hash import SHA as SHA1
+try:
from Crypto.Hash import RIPEMD160
except ImportError:
# Maybe it's called RIPEMD
@@ -194,6 +201,59 @@ class Benchmark:
mac_constructor = lambda data=None: hmac_constructor(key, data, digestmod)
self.test_hash_large(mac_name, mac_constructor, digest_size)
+ def test_pkcs1_sign(self, scheme_name, scheme_constructor, hash_name, hash_constructor, digest_size):
+ self.announce_start("%s signing %s (%d-byte inputs)" % (scheme_name, hash_name, digest_size))
+
+ # Make a key
+ k = RSA.generate(2048)
+ sigscheme = scheme_constructor(k)
+
+ # Make some hashes
+ blocks = self.random_blocks(digest_size, 50)
+ hashes = []
+ for b in blocks:
+ hashes.append(hash_constructor(b))
+
+ # Perform signing
+ t0 = time.time()
+ for h in hashes:
+ sigscheme.sign(h)
+ t = time.time()
+
+ speed = len(hashes) / (t - t0)
+ self.announce_result(speed, "sigs/sec")
+
+ def test_pkcs1_verify(self, scheme_name, scheme_constructor, hash_name, hash_constructor, digest_size):
+ self.announce_start("%s verification %s (%d-byte inputs)" % (scheme_name, hash_name, digest_size))
+
+ # Make a key
+ k = RSA.generate(2048)
+ sigscheme = scheme_constructor(k)
+
+ # Make some hashes
+ blocks = self.random_blocks(digest_size, 50)
+ hashes = []
+ for b in blocks:
+ hashes.append(hash_constructor(b))
+
+ # Make some signatures
+ signatures = []
+ for h in hashes:
+ signatures.append(sigscheme.sign(h))
+
+ # Double the list, to make timing better
+ hashes = hashes + hashes
+ signatures = signatures + signatures
+
+ # Perform verification
+ t0 = time.time()
+ for h, s in zip(hashes, signatures):
+ sigscheme.verify(h, s)
+ t = time.time()
+
+ speed = len(hashes) / (t - t0)
+ self.announce_result(speed, "sigs/sec")
+
def run(self):
pubkey_specs = [
("RSA(1024)", RSA, int(1024/8)),
@@ -221,7 +281,7 @@ class Benchmark:
("MD2", MD2),
("MD4", MD4),
("MD5", MD5),
- ("SHA", SHA),
+ ("SHA1", SHA1),
("SHA224", SHA224),
("SHA256", SHA256),
("SHA384", SHA384),
@@ -277,6 +337,22 @@ class Benchmark:
self.test_hmac_small("hmac+"+hash_name, hmac.HMAC, func, func().digest_size)
self.test_hmac_large("hmac+"+hash_name, hmac.HMAC, func, func().digest_size)
+ # PKCS1_v1_5 (sign) + Crypto.Hash
+ for hash_name, module in hash_specs:
+ self.test_pkcs1_sign("PKCS#1-v1.5", RSASSA_PKCS1_v1_5.new, hash_name, module.new, module.digest_size)
+
+ # PKCS1_PSS (sign) + Crypto.Hash
+ for hash_name, module in hash_specs:
+ self.test_pkcs1_sign("PKCS#1-PSS", PKCS1_PSS.new, hash_name, module.new, module.digest_size)
+
+ # PKCS1_v1_5 (verify) + Crypto.Hash
+ for hash_name, module in hash_specs:
+ self.test_pkcs1_verify("PKCS#1-v1.5", RSASSA_PKCS1_v1_5.new, hash_name, module.new, module.digest_size)
+
+ # PKCS1_PSS (verify) + Crypto.Hash
+ for hash_name, module in hash_specs:
+ self.test_pkcs1_verify("PKCS#1-PSS", PKCS1_PSS.new, hash_name, module.new, module.digest_size)
+
if __name__ == '__main__':
Benchmark().run()
diff --git a/setup.py b/setup.py
index 13ff5e2..85bd65a 100644
--- a/setup.py
+++ b/setup.py
@@ -399,25 +399,25 @@ kw = {'name':"pycrypto",
sources=["src/_fastmath.c"]),
# Hash functions
- Extension("Crypto.Hash._MD2",
+ Extension("Crypto.Hash.MD2",
include_dirs=['src/'],
sources=["src/MD2.c"]),
- Extension("Crypto.Hash._MD4",
+ Extension("Crypto.Hash.MD4",
include_dirs=['src/'],
sources=["src/MD4.c"]),
- Extension("Crypto.Hash._SHA256",
+ Extension("Crypto.Hash.SHA256",
include_dirs=['src/'],
sources=["src/SHA256.c"]),
- Extension("Crypto.Hash._SHA224",
+ Extension("Crypto.Hash.SHA224",
include_dirs=['src/'],
sources=["src/SHA224.c"]),
- Extension("Crypto.Hash._SHA384",
+ Extension("Crypto.Hash.SHA384",
include_dirs=['src/'],
sources=["src/SHA384.c"]),
- Extension("Crypto.Hash._SHA512",
+ Extension("Crypto.Hash.SHA512",
include_dirs=['src/'],
sources=["src/SHA512.c"]),
- Extension("Crypto.Hash._RIPEMD160",
+ Extension("Crypto.Hash.RIPEMD160",
include_dirs=['src/'],
sources=["src/RIPEMD160.c"],
define_macros=[endianness_macro()]),
diff --git a/src/AES.c b/src/AES.c
index 0aeaeda..9b125e2 100644
--- a/src/AES.c
+++ b/src/AES.c
@@ -24,9 +24,9 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "Python.h"
#include <assert.h>
#include <stdlib.h>
-#include "Python.h"
#define MODULE_NAME _AES
#define BLOCK_SIZE 16
diff --git a/src/ARC2.c b/src/ARC2.c
index 49b5daf..a872823 100644
--- a/src/ARC2.c
+++ b/src/ARC2.c
@@ -41,8 +41,8 @@
*
*/
-#include <string.h>
#include "Python.h"
+#include <string.h>
#define MODULE_NAME _ARC2
#define BLOCK_SIZE 8
diff --git a/src/Blowfish.c b/src/Blowfish.c
index 94562bb..fd90fd7 100644
--- a/src/Blowfish.c
+++ b/src/Blowfish.c
@@ -26,6 +26,7 @@
* http://www.schneier.com/paper-blowfish-fse.html
*/
+#include "Python.h"
#include "config.h"
#if HAVE_STDINT_H
# include <stdint.h>
@@ -36,7 +37,6 @@
#endif
#include <assert.h>
#include <string.h>
-#include "Python.h"
#include "Blowfish-tables.h"
diff --git a/src/DES.c b/src/DES.c
index 96a9335..096e309 100644
--- a/src/DES.c
+++ b/src/DES.c
@@ -24,6 +24,8 @@
* Country of origin: Canada
*/
+#include "Python.h"
+
/* Setting this will cause LibTomCrypt to return CRYPT_INVALID_ARG when its
* assert-like LTC_ARGCHK macro fails. */
#define ARGTYPE 4
@@ -34,7 +36,6 @@
#undef DES /* this is needed because tomcrypt_custom.h defines DES to an empty string */
#include <assert.h>
-#include "Python.h"
typedef struct {
symmetric_key sk;
diff --git a/src/MD2.c b/src/MD2.c
index f670ec4..043bcc8 100644
--- a/src/MD2.c
+++ b/src/MD2.c
@@ -27,24 +27,30 @@
*/
-#include <string.h>
#include "Python.h"
+#include <string.h>
#include "pycrypto_compat.h"
-#define MODULE_NAME _MD2
+#define MODULE_NAME MD2
#define DIGEST_SIZE 16
#define BLOCK_SIZE 64
-/**
- * id-md2 OBJECT IDENTIFIER ::= {
- * iso(1) member-body(2) us(840) rsadsi(113549)
- * digestAlgorithm(2) 2
- * }
- */
-static const char md2_oid[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02 };
-
-#define DER_OID ((void*)&md2_oid)
-#define DER_OID_SIZE (sizeof md2_oid)
+static char MODULE__doc__[] =
+ "MD2 cryptographic hash algorithm.\n"
+ "\n"
+ "MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import MD2\n"
+ " >>>\n"
+ " >>> h = MD2.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.\n"
+ "\n"
+ "This algorithm is both slow and insecure. Do not use it for new designs.\n"
+ "\n"
+ ".. _RFC1319: http://tools.ietf.org/html/rfc1319\n";
typedef unsigned char U8;
typedef unsigned int U32;
diff --git a/src/MD4.c b/src/MD4.c
index 2c0a984..7e453a8 100644
--- a/src/MD4.c
+++ b/src/MD4.c
@@ -27,14 +27,31 @@
*/
-#include <string.h>
#include "Python.h"
+#include <string.h>
#include "pycrypto_compat.h"
-#define MODULE_NAME _MD4
+#define MODULE_NAME MD4
#define DIGEST_SIZE 16
#define BLOCK_SIZE 64
+static char MODULE__doc__[] =
+ "MD4 cryptographic hash algorithm.\n"
+ "\n"
+ "MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import MD4\n"
+ " >>>\n"
+ " >>> h = MD4.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.\n"
+ "\n"
+ "This algorithm is insecure. Do not use it for new designs.\n"
+ "\n"
+ ".. _RFC1320: http://tools.ietf.org/html/rfc1320\n";
+
typedef unsigned int U32;
typedef unsigned char U8;
#define U32_MAX (U32)4294967295
diff --git a/src/RIPEMD160.c b/src/RIPEMD160.c
index 9786af8..9593fc8 100644
--- a/src/RIPEMD160.c
+++ b/src/RIPEMD160.c
@@ -43,6 +43,8 @@
* "RIPEMD-160 is big-bit-endian, little-byte-endian, and left-justified."
*/
+#include "Python.h"
+
#include "config.h"
#if HAVE_STDINT_H
# include <stdint.h>
@@ -54,12 +56,31 @@
#include <assert.h>
#include <string.h>
-#include "Python.h"
#include "pycrypto_compat.h"
#define RIPEMD160_DIGEST_SIZE 20
#define BLOCK_SIZE 64
+static char MODULE__doc__[] =
+ "RIPEMD-160 cryptographic hash algorithm.\n"
+ "\n"
+ "RIPEMD-160_ produces the 160 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import RIPEMD160\n"
+ " >>>\n"
+ " >>> h = RIPEMD160.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest\n"
+ "with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.\n"
+ "\n"
+ "This algorithm is considered secure, although it has not been scrutinized as\n"
+ "extensively as SHA-1. Moreover, it provides an informal security level of just\n"
+ "80bits.\n"
+ "\n"
+ ".. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html\n";
+
#define RIPEMD160_MAGIC 0x9f19dd68u
typedef struct {
uint32_t magic;
@@ -400,7 +421,7 @@ static int ripemd160_digest(const ripemd160_state *self, unsigned char *out)
}
/* Template definitions */
-#define MODULE_NAME _RIPEMD160
+#define MODULE_NAME RIPEMD160
#define DIGEST_SIZE RIPEMD160_DIGEST_SIZE
#define hash_state ripemd160_state
#define hash_init ripemd160_init
diff --git a/src/SHA224.c b/src/SHA224.c
index ca70fbd..86591cf 100644
--- a/src/SHA224.c
+++ b/src/SHA224.c
@@ -27,12 +27,28 @@
*
*/
-#define MODULE_NAME _SHA224
+#define MODULE_NAME SHA224
#define DIGEST_SIZE (224/8)
#define BLOCK_SIZE (512/8)
#define WORD_SIZE 4
#define SCHEDULE_SIZE 64
+static char MODULE__doc__[] =
+ "SHA-224 cryptographic hash algorithm.\n"
+ "\n"
+ "SHA-224 belongs to the SHA-2_ family of cryptographic hashes.\n"
+ "It produces the 224 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import SHA224\n"
+ " >>>\n"
+ " >>> h = SHA224.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "*SHA* stands for Secure Hash Algorithm.\n"
+ "\n"
+ ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n";
+
#include "hash_SHA2.h"
/* Initial Values H */
diff --git a/src/SHA256.c b/src/SHA256.c
index 61a2d74..9473abc 100644
--- a/src/SHA256.c
+++ b/src/SHA256.c
@@ -26,12 +26,28 @@
* ===================================================================
*
*/
-#define MODULE_NAME _SHA256
+#define MODULE_NAME SHA256
#define DIGEST_SIZE (256/8)
#define BLOCK_SIZE (512/8)
#define WORD_SIZE 4
#define SCHEDULE_SIZE 64
-
+
+static char MODULE__doc__[] =
+ "SHA-256 cryptographic hash algorithm.\n"
+ "\n"
+ "SHA-256 belongs to the SHA-2_ family of cryptographic hashes.\n"
+ "It produces the 256 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import SHA256\n"
+ " >>>\n"
+ " >>> h = SHA256.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "*SHA* stands for Secure Hash Algorithm.\n"
+ "\n"
+ ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n";
+
#include "hash_SHA2.h"
/* Initial Values H */
diff --git a/src/SHA384.c b/src/SHA384.c
index 05dfe25..eb7051e 100644
--- a/src/SHA384.c
+++ b/src/SHA384.c
@@ -27,12 +27,28 @@
*
*/
-#define MODULE_NAME _SHA384
+#define MODULE_NAME SHA384
#define DIGEST_SIZE (384/8)
#define BLOCK_SIZE (1024/8)
#define WORD_SIZE 8
#define SCHEDULE_SIZE 80
+static char MODULE__doc__[] =
+ "SHA-384 cryptographic hash algorithm.\n"
+ "\n"
+ "SHA-384 belongs to the SHA-2_ family of cryptographic hashes.\n"
+ "It produces the 384 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import SHA384\n"
+ " >>>\n"
+ " >>> h = SHA384.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "*SHA* stands for Secure Hash Algorithm.\n"
+ "\n"
+ ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n";
+
#include "hash_SHA2.h"
/* Initial Values H */
diff --git a/src/SHA512.c b/src/SHA512.c
index 3370e8e..f12755c 100644
--- a/src/SHA512.c
+++ b/src/SHA512.c
@@ -27,12 +27,28 @@
*
*/
-#define MODULE_NAME _SHA512
+#define MODULE_NAME SHA512
#define DIGEST_SIZE (512/8)
#define BLOCK_SIZE (1024/8)
#define WORD_SIZE 8
#define SCHEDULE_SIZE 80
+static char MODULE__doc__[] =
+ "SHA-512 cryptographic hash algorithm.\n"
+ "\n"
+ "SHA-512 belongs to the SHA-2_ family of cryptographic hashes.\n"
+ "It produces the 512 bit digest of a message.\n"
+ "\n"
+ " >>> from Crypto.Hash import SHA512\n"
+ " >>>\n"
+ " >>> h = SHA512.new()\n"
+ " >>> h.update(b'Hello')\n"
+ " >>> print h.hexdigest()\n"
+ "\n"
+ "*SHA* stands for Secure Hash Algorithm.\n"
+ "\n"
+ ".. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf\n";
+
#include "hash_SHA2.h"
/* Initial Values H */
diff --git a/src/_counter.c b/src/_counter.c
index 9b396e4..6579a5f 100644
--- a/src/_counter.c
+++ b/src/_counter.c
@@ -22,10 +22,10 @@
* ===================================================================
*/
+#include "Python.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
-#include "Python.h"
#include "pycrypto_compat.h"
#include "_counter.h"
@@ -106,6 +106,7 @@ CounterObject_init(PCT_CounterObject *self, PyObject *args, PyObject *kwargs)
/* Sanity-check pointers */
assert(self->val <= self->p);
+ assert(self->buf_size >= 0);
assert(self->p + self->nbytes <= self->val + self->buf_size);
assert(self->val + PyBytes_GET_SIZE(self->prefix) == self->p);
assert(PyBytes_GET_SIZE(self->prefix) + self->nbytes + PyBytes_GET_SIZE(self->suffix) == self->buf_size);
diff --git a/src/_counter.h b/src/_counter.h
index fc3e24e..f671094 100644
--- a/src/_counter.h
+++ b/src/_counter.h
@@ -38,7 +38,7 @@ typedef struct {
PyBytesObject *prefix; /* Prefix (useful for a nonce) */
PyBytesObject *suffix; /* Suffix (useful for a nonce) */
uint8_t *val; /* Buffer for our output string */
- uint32_t buf_size; /* Size of the buffer */
+ Py_ssize_t buf_size;/* Size of the buffer */
uint8_t *p; /* Pointer to the part of the buffer that we're allowed to update */
uint16_t nbytes; /* The number of bytes that from .p that are part of the counter */
void (*inc_func)(void *); /* Pointer to the counter increment function */
diff --git a/src/_fastmath.c b/src/_fastmath.c
index 99b1c43..bd2651d 100644
--- a/src/_fastmath.c
+++ b/src/_fastmath.c
@@ -26,9 +26,9 @@
* $Id$
*/
+#include "Python.h"
#include <stdio.h>
#include <string.h>
-#include "Python.h"
#include "pycrypto_compat.h"
#include <longintrepr.h> /* for conversions */
#include "config.h"
diff --git a/src/block_template.c b/src/block_template.c
index c36b316..2cfee1b 100644
--- a/src/block_template.c
+++ b/src/block_template.c
@@ -24,6 +24,7 @@
* ===================================================================
*/
+#include "Python.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -33,7 +34,6 @@
#include <string.h>
#endif
-#include "Python.h"
#include "pycrypto_compat.h"
#include "modsupport.h"
diff --git a/src/hash_SHA2.h b/src/hash_SHA2.h
index 5867191..02991bd 100644
--- a/src/hash_SHA2.h
+++ b/src/hash_SHA2.h
@@ -26,6 +26,8 @@
#ifndef __HASH_SHA2_H
#define __HASH_SHA2_H
+#include "Python.h"
+
/* check if implementation set the correct macros */
#ifndef MODULE_NAME
#error SHA2 Implementation must define MODULE_NAME before including this header
diff --git a/src/hash_template.c b/src/hash_template.c
index eb27e9f..d085bb8 100644
--- a/src/hash_template.c
+++ b/src/hash_template.c
@@ -24,13 +24,13 @@
/* Basic object type */
+#include "Python.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _HAVE_STDC_HEADERS
#include <string.h>
#endif
-#include "Python.h"
#include "pycrypto_compat.h"
#define _STR(x) #x
@@ -209,9 +209,13 @@ ALG_getattr(PyObject *self, char *name)
if (PyUnicode_CompareWithASCIIString(attr, "digest_size")==0)
return PyLong_FromLong(DIGEST_SIZE);
+ if (PyUnicode_CompareWithASCIIString(attr, "name")==0)
+ return PyUnicode_FromString(_MODULE_STRING); /* we should try to be compatible with hashlib here */
#else
if (strcmp(name, "digest_size")==0)
return PyInt_FromLong(DIGEST_SIZE);
+ if (strcmp(name, "name")==0)
+ return PyString_FromString(_MODULE_STRING); /* we should try to be compatible with hashlib here */
#endif
#ifdef IS_PY3K
@@ -309,14 +313,14 @@ static struct PyMethodDef ALG_functions[] = {
#ifdef IS_PY3K
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
- "Crypto.Hash." _MODULE_STRING,
- NULL,
- -1,
- ALG_functions,
- NULL,
- NULL,
- NULL,
- NULL
+ "Crypto.Hash." _MODULE_STRING, /* m_name */
+ MODULE__doc__, /* m_doc */
+ -1, /* m_size */
+ ALG_functions, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
};
#endif
@@ -349,7 +353,7 @@ _MODULE_NAME (void)
return NULL;
#else
ALGtype.ob_type = &PyType_Type;
- m = Py_InitModule("Crypto.Hash." _MODULE_STRING, ALG_functions);
+ m = Py_InitModule3("Crypto.Hash." _MODULE_STRING, ALG_functions, MODULE__doc__);
#endif
/* Add some symbolic constants to the module */
diff --git a/src/stream_template.c b/src/stream_template.c
index c3effa4..a74d18d 100644
--- a/src/stream_template.c
+++ b/src/stream_template.c
@@ -24,6 +24,7 @@
* ===================================================================
*/
+#include "Python.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -33,7 +34,6 @@
#include <string.h>
#endif
-#include "Python.h"
#include "pycrypto_compat.h"
#include "modsupport.h"