summaryrefslogtreecommitdiff
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
parent0d8ea5ff1607a3d7ae544667bff99229954484ff (diff)
downloadpycrypto-hash-speedup-wip.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.
-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
-rw-r--r--setup.py14
-rw-r--r--src/MD2.c29
-rw-r--r--src/MD4.c20
-rw-r--r--src/RIPEMD160.c23
-rw-r--r--src/SHA224.c19
-rw-r--r--src/SHA256.c21
-rw-r--r--src/SHA384.c19
-rw-r--r--src/SHA512.c19
-rw-r--r--src/hash_template.c22
21 files changed, 274 insertions, 845 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
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/MD2.c b/src/MD2.c
index dadb999..043bcc8 100644
--- a/src/MD2.c
+++ b/src/MD2.c
@@ -31,21 +31,26 @@
#include <string.h>
#include "pycrypto_compat.h"
-#define MODULE_NAME _MD2
-#define ALGORITHM_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 d5c20f4..7e453a8 100644
--- a/src/MD4.c
+++ b/src/MD4.c
@@ -31,11 +31,27 @@
#include <string.h>
#include "pycrypto_compat.h"
-#define MODULE_NAME _MD4
-#define ALGORITHM_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 37d4c73..9593fc8 100644
--- a/src/RIPEMD160.c
+++ b/src/RIPEMD160.c
@@ -61,6 +61,26 @@
#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;
@@ -401,8 +421,7 @@ static int ripemd160_digest(const ripemd160_state *self, unsigned char *out)
}
/* Template definitions */
-#define MODULE_NAME _RIPEMD160
-#define ALGORITHM_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 99e2f7c..86591cf 100644
--- a/src/SHA224.c
+++ b/src/SHA224.c
@@ -27,13 +27,28 @@
*
*/
-#define MODULE_NAME _SHA224
-#define ALGORITHM_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 8cc3265..9473abc 100644
--- a/src/SHA256.c
+++ b/src/SHA256.c
@@ -26,13 +26,28 @@
* ===================================================================
*
*/
-#define MODULE_NAME _SHA256
-#define ALGORITHM_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 24b200c..eb7051e 100644
--- a/src/SHA384.c
+++ b/src/SHA384.c
@@ -27,13 +27,28 @@
*
*/
-#define MODULE_NAME _SHA384
-#define ALGORITHM_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 3b227ab..f12755c 100644
--- a/src/SHA512.c
+++ b/src/SHA512.c
@@ -27,13 +27,28 @@
*
*/
-#define MODULE_NAME _SHA512
-#define ALGORITHM_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/hash_template.c b/src/hash_template.c
index afffbfb..d085bb8 100644
--- a/src/hash_template.c
+++ b/src/hash_template.c
@@ -210,12 +210,12 @@ 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(ALGORITHM_NAME);
+ 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(ALGORITHM_NAME);
+ return PyString_FromString(_MODULE_STRING); /* we should try to be compatible with hashlib here */
#endif
#ifdef IS_PY3K
@@ -313,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
@@ -353,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 */