[ sf.net patch # 1121611 ]
A new hashlib module to replace the md5 and sha modules. It adds
support for additional secure hashes such as SHA-256 and SHA-512. The
hashlib module uses OpenSSL for fast platform optimized
implementations of algorithms when available. The old md5 and sha
modules still exist as wrappers around hashlib to preserve backwards
compatibility.
diff --git a/Doc/ACKS b/Doc/ACKS
index 3f07066..2c89e2a 100644
--- a/Doc/ACKS
+++ b/Doc/ACKS
@@ -164,6 +164,7 @@
Justin Sheehy
Michael Simcich
Ionel Simionescu
+Gregory P. Smith
Roy Smith
Clay Spence
Nicholas Spies
diff --git a/Doc/Makefile.deps b/Doc/Makefile.deps
index b3c4dbb..aa843a4 100644
--- a/Doc/Makefile.deps
+++ b/Doc/Makefile.deps
@@ -202,6 +202,7 @@
lib/librgbimg.tex \
lib/libossaudiodev.tex \
lib/libcrypto.tex \
+ lib/libhashlib.tex \
lib/libmd5.tex \
lib/libsha.tex \
lib/libhmac.tex \
diff --git a/Doc/lib/lib.tex b/Doc/lib/lib.tex
index 43fafb1..bb995d8 100644
--- a/Doc/lib/lib.tex
+++ b/Doc/lib/lib.tex
@@ -303,6 +303,7 @@
\input{libcrypto} % Cryptographic Services
\input{libhmac}
+\input{libhashlib}
\input{libmd5}
\input{libsha}
diff --git a/Doc/lib/libhmac.tex b/Doc/lib/libhmac.tex
index 1d49417..5ca24d1 100644
--- a/Doc/lib/libhmac.tex
+++ b/Doc/lib/libhmac.tex
@@ -14,8 +14,10 @@
\begin{funcdesc}{new}{key\optional{, msg\optional{, digestmod}}}
Return a new hmac object. If \var{msg} is present, the method call
\code{update(\var{msg})} is made. \var{digestmod} is the digest
- module for the HMAC object to use. It defaults to the
- \refmodule{md5} module.
+ constructor or module for the HMAC object to use. It defaults to
+ the \code{\refmodule{hashlib}.md5} constructor. \note{The md5 hash
+ has known weaknesses but remains the default for backwards compatibility.
+ Choose a better one for your application.}
\end{funcdesc}
An HMAC object has the following methods:
@@ -29,14 +31,14 @@
\begin{methoddesc}[hmac]{digest}{}
Return the digest of the strings passed to the \method{update()}
- method so far. This is a 16-byte string (for \refmodule{md5}) or a
- 20-byte string (for \refmodule{sha}) which may contain non-\ASCII{}
- characters, including NUL bytes.
+ method so far. This string will be the same length as the
+ \var{digest_size} of the digest given to the constructor. It
+ may contain non-\ASCII{} characters, including NUL bytes.
\end{methoddesc}
\begin{methoddesc}[hmac]{hexdigest}{}
- Like \method{digest()} except the digest is returned as a string of
- length 32 for \refmodule{md5} (40 for \refmodule{sha}), containing
+ Like \method{digest()} except the digest is returned as a string
+ twice the length containing
only hexadecimal digits. This may be used to exchange the value
safely in email or other non-binary environments.
\end{methoddesc}
@@ -46,3 +48,7 @@
efficiently compute the digests of strings that share a common
initial substring.
\end{methoddesc}
+
+\begin{seealso}
+ \seemodule{hashlib}{The python module providing secure hash functions.}
+\end{seealso}
diff --git a/Doc/lib/libmd5.tex b/Doc/lib/libmd5.tex
index 6f837b4..f6b35c7 100644
--- a/Doc/lib/libmd5.tex
+++ b/Doc/lib/libmd5.tex
@@ -4,6 +4,7 @@
\declaremodule{builtin}{md5}
\modulesynopsis{RSA's MD5 message digest algorithm.}
+\deprecated{2.5}{Use the \refmodule{hashlib} module instead.}
This module implements the interface to RSA's MD5 message digest
\index{message digest, MD5}
diff --git a/Doc/lib/libsha.tex b/Doc/lib/libsha.tex
index 4800b17..6d1da68 100644
--- a/Doc/lib/libsha.tex
+++ b/Doc/lib/libsha.tex
@@ -5,6 +5,8 @@
\modulesynopsis{NIST's secure hash algorithm, SHA.}
\sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org}
+\deprecated{2.5}{Use the \refmodule{hashlib} module instead.}
+
This module implements the interface to NIST's\index{NIST} secure hash
algorithm,\index{Secure Hash Algorithm} known as SHA-1. SHA-1 is an
diff --git a/Doc/whatsnew/whatsnew25.tex b/Doc/whatsnew/whatsnew25.tex
index 4bd380a..118b4c7 100644
--- a/Doc/whatsnew/whatsnew25.tex
+++ b/Doc/whatsnew/whatsnew25.tex
@@ -247,6 +247,15 @@
a different directory as the extraction target, and to unpack only a
subset of the archive's members. (Contributed by Lars Gust\"abel.)
+\item A new \module{hashlib} module has been added to replace the
+\module{md5} and \module{sha} modules and adds support for additional
+secure hashes such as SHA-256 and SHA-512. The \module{hashlib} module
+uses OpenSSL for fast platform optimized implementations of algorithms
+when available. The old \module{md5} and \module{sha} modules still
+exist as wrappers around hashlib to preserve backwards compatibility.
+
+(Contributed by Gregory P. Smith.)
+
\end{itemize}
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
new file mode 100644
index 0000000..3528699
--- /dev/null
+++ b/Lib/hashlib.py
@@ -0,0 +1,110 @@
+# $Id$
+#
+# Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+# Licensed to PSF under a Contributor Agreement.
+#
+
+__doc__ = """hashlib module - A common interface to many hash functions.
+
+new(name, string='') - returns a new hash object implementing the
+ given hash function; initializing the hash
+ using the given string data.
+
+Named constructor functions are also available, these are much faster
+than using new():
+
+md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
+
+More algorithms may be available on your platform but the above are
+guaranteed to exist.
+
+Choose your hash function wisely. Some have known weaknesses.
+sha384 and sha512 will be slow on 32 bit platforms.
+"""
+
+
+def __get_builtin_constructor(name):
+ if name in ('SHA1', 'sha1'):
+ import _sha
+ return _sha.new
+ elif name in ('MD5', 'md5'):
+ import _md5
+ return _md5.new
+ elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
+ import _sha256
+ bs = name[3:]
+ if bs == '256':
+ return _sha256.sha256
+ elif bs == '224':
+ return _sha256.sha224
+ elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
+ import _sha512
+ bs = name[3:]
+ if bs == '512':
+ return _sha512.sha512
+ elif bs == '384':
+ return _sha512.sha384
+
+ raise ValueError, "unsupported hash type"
+
+
+def __py_new(name, string=''):
+ """new(name, string='') - Return a new hashing object using the named algorithm;
+ optionally initialized with a string.
+ """
+ return __get_builtin_constructor(name)(string)
+
+
+def __hash_new(name, string=''):
+ """new(name, string='') - Return a new hashing object using the named algorithm;
+ optionally initialized with a string.
+ """
+ try:
+ return _hashlib.new(name, string)
+ except ValueError:
+ # If the _hashlib module (OpenSSL) doesn't support the named
+ # hash, try using our builtin implementations.
+ # This allows for SHA224/256 and SHA384/512 support even though
+ # the OpenSSL library prior to 0.9.8 doesn't provide them.
+ return __get_builtin_constructor(name)(string)
+
+
+try:
+ import _hashlib
+ # use the wrapper of the C implementation
+ new = __hash_new
+
+ for opensslFuncName in filter(lambda n: n.startswith('openssl_'), dir(_hashlib)):
+ funcName = opensslFuncName[len('openssl_'):]
+ try:
+ # try them all, some may not work due to the OpenSSL
+ # version not supporting that algorithm.
+ f = getattr(_hashlib, opensslFuncName)
+ f()
+ # Use the C function directly (very fast)
+ exec funcName + ' = f'
+ except ValueError:
+ try:
+ # Use the builtin implementation directly (fast)
+ exec funcName + ' = __get_builtin_constructor(funcName)'
+ except ValueError:
+ # this one has no builtin implementation, don't define it
+ pass
+ # clean up our locals
+ del f
+ del opensslFuncName
+ del funcName
+
+except ImportError:
+ # We don't have the _hashlib OpenSSL module?
+ # use the built in legacy interfaces via a wrapper function
+ new = __py_new
+
+ # lookup the C function to use directly for the named constructors
+ md5 = __get_builtin_constructor('md5')
+ sha1 = __get_builtin_constructor('sha1')
+ sha224 = __get_builtin_constructor('sha224')
+ sha256 = __get_builtin_constructor('sha256')
+ sha384 = __get_builtin_constructor('sha384')
+ sha512 = __get_builtin_constructor('sha512')
+
diff --git a/Lib/hmac.py b/Lib/hmac.py
index 11b0fb3..41d6c6c 100644
--- a/Lib/hmac.py
+++ b/Lib/hmac.py
@@ -28,27 +28,33 @@
key: key for the keyed hash object.
msg: Initial input for the hash, if provided.
- digestmod: A module supporting PEP 247. Defaults to the md5 module.
+ digestmod: A module supporting PEP 247. *OR*
+ A hashlib constructor returning a new hash object.
+ Defaults to hashlib.md5.
"""
if key is _secret_backdoor_key: # cheap
return
if digestmod is None:
- import md5
- digestmod = md5
+ import hashlib
+ digestmod = hashlib.md5
- self.digestmod = digestmod
- self.outer = digestmod.new()
- self.inner = digestmod.new()
- self.digest_size = digestmod.digest_size
+ if callable(digestmod):
+ self.digest_cons = digestmod
+ else:
+ self.digest_cons = lambda d='': digestmod.new(d)
+
+ self.outer = self.digest_cons()
+ self.inner = self.digest_cons()
+ self.digest_size = self.inner.digest_size
blocksize = 64
ipad = "\x36" * blocksize
opad = "\x5C" * blocksize
if len(key) > blocksize:
- key = digestmod.new(key).digest()
+ key = self.digest_cons(key).digest()
key = key + chr(0) * (blocksize - len(key))
self.outer.update(_strxor(key, opad))
@@ -70,7 +76,7 @@
An update to this copy won't affect the original object.
"""
other = HMAC(_secret_backdoor_key)
- other.digestmod = self.digestmod
+ other.digest_cons = self.digest_cons
other.digest_size = self.digest_size
other.inner = self.inner.copy()
other.outer = self.outer.copy()
diff --git a/Lib/md5.py b/Lib/md5.py
new file mode 100644
index 0000000..bbe1984
--- /dev/null
+++ b/Lib/md5.py
@@ -0,0 +1,10 @@
+# $Id$
+#
+# Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+# Licensed to PSF under a Contributor Agreement.
+
+from hashlib import md5
+new = md5
+
+blocksize = 1 # legacy value (wrong in any useful sense)
+digest_size = 16
diff --git a/Lib/sha.py b/Lib/sha.py
new file mode 100644
index 0000000..9d914a9
--- /dev/null
+++ b/Lib/sha.py
@@ -0,0 +1,11 @@
+# $Id$
+#
+# Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+# Licensed to PSF under a Contributor Agreement.
+
+from hashlib import sha1 as sha
+new = sha
+
+blocksize = 1 # legacy value (wrong in any useful sense)
+digest_size = 20
+digestsize = 20
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 2f620a2..e1c878c 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -1090,6 +1090,9 @@
s = _expectations[sys.platform]
self.expected = set(s.split())
+ # this isn't a regularly run unit test, it is always skipped
+ self.expected.add('test_hashlib_speed')
+
if not os.path.supports_unicode_filenames:
self.expected.add('test_pep277')
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
new file mode 100644
index 0000000..1dcadcd
--- /dev/null
+++ b/Lib/test/test_hashlib.py
@@ -0,0 +1,191 @@
+# Test hashlib module
+#
+# $Id$
+#
+# Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+# Licensed to PSF under a Contributor Agreement.
+#
+
+import hashlib
+import unittest
+from test import test_support
+
+
+def hexstr(s):
+ import string
+ h = string.hexdigits
+ r = ''
+ for c in s:
+ i = ord(c)
+ r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
+ return r
+
+
+class HashLibTestCase(unittest.TestCase):
+ supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
+ 'sha224', 'SHA224', 'sha256', 'SHA256',
+ 'sha384', 'SHA384', 'sha512', 'SHA512' )
+
+ def test_unknown_hash(self):
+ try:
+ hashlib.new('spam spam spam spam spam')
+ except ValueError:
+ pass
+ else:
+ self.assert_(0 == "hashlib didn't reject bogus hash name")
+
+ def test_hexdigest(self):
+ for name in self.supported_hash_names:
+ h = hashlib.new(name)
+ self.assert_(hexstr(h.digest()) == h.hexdigest())
+
+
+ def test_large_update(self):
+ aas = 'a' * 128
+ bees = 'b' * 127
+ cees = 'c' * 126
+
+ for name in self.supported_hash_names:
+ m1 = hashlib.new(name)
+ m1.update(aas)
+ m1.update(bees)
+ m1.update(cees)
+
+ m2 = hashlib.new(name)
+ m2.update(aas + bees + cees)
+ self.assertEqual(m1.digest(), m2.digest())
+
+
+ def check(self, name, data, digest):
+ # test the direct constructors
+ computed = getattr(hashlib, name)(data).hexdigest()
+ self.assert_(computed == digest)
+ # test the general new() interface
+ computed = hashlib.new(name, data).hexdigest()
+ self.assert_(computed == digest)
+
+
+ def test_case_md5_0(self):
+ self.check('md5', '', 'd41d8cd98f00b204e9800998ecf8427e')
+
+ def test_case_md5_1(self):
+ self.check('md5', 'abc', '900150983cd24fb0d6963f7d28e17f72')
+
+ def test_case_md5_2(self):
+ self.check('md5', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
+ 'd174ab98d277d9f5a5611c2c9f419d9f')
+
+
+ # use the three examples from Federal Information Processing Standards
+ # Publication 180-1, Secure Hash Standard, 1995 April 17
+ # http://www.itl.nist.gov/div897/pubs/fip180-1.htm
+
+ def test_case_sha1_0(self):
+ self.check('sha1', "",
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709")
+
+ def test_case_sha1_1(self):
+ self.check('sha1', "abc",
+ "a9993e364706816aba3e25717850c26c9cd0d89d")
+
+ def test_case_sha1_2(self):
+ self.check('sha1', "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
+
+ def test_case_sha1_3(self):
+ self.check('sha1', "a" * 1000000,
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f")
+
+
+ # use the examples from Federal Information Processing Standards
+ # Publication 180-2, Secure Hash Standard, 2002 August 1
+ # http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+
+ def test_case_sha224_0(self):
+ self.check('sha224', "",
+ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")
+
+ def test_case_sha224_1(self):
+ self.check('sha224', "abc",
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7")
+
+ def test_case_sha224_2(self):
+ self.check('sha224',
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525")
+
+ def test_case_sha224_3(self):
+ self.check('sha224', "a" * 1000000,
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67")
+
+
+ def test_case_sha256_0(self):
+ self.check('sha256', "",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
+
+ def test_case_sha256_1(self):
+ self.check('sha256', "abc",
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+
+ def test_case_sha256_2(self):
+ self.check('sha256',
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1")
+
+ def test_case_sha256_3(self):
+ self.check('sha256', "a" * 1000000,
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0")
+
+
+ def test_case_sha384_0(self):
+ self.check('sha384', "",
+ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da"+
+ "274edebfe76f65fbd51ad2f14898b95b")
+
+ def test_case_sha384_1(self):
+ self.check('sha384', "abc",
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"+
+ "8086072ba1e7cc2358baeca134c825a7")
+
+ def test_case_sha384_2(self):
+ self.check('sha384',
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"+
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"+
+ "fcc7c71a557e2db966c3e9fa91746039")
+
+ def test_case_sha384_3(self):
+ self.check('sha384', "a" * 1000000,
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"+
+ "07b8b3dc38ecc4ebae97ddd87f3d8985")
+
+
+ def test_case_sha512_0(self):
+ self.check('sha512', "",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"+
+ "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
+
+ def test_case_sha512_1(self):
+ self.check('sha512', "abc",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"+
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
+
+ def test_case_sha512_2(self):
+ self.check('sha512',
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"+
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"+
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909")
+
+ def test_case_sha512_3(self):
+ self.check('sha512', "a" * 1000000,
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"+
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b")
+
+
+def test_main():
+ test_support.run_unittest(HashLibTestCase)
+
+
+if __name__ == "__main__":
+ test_main()
diff --git a/Lib/test/test_hashlib_speed.py b/Lib/test/test_hashlib_speed.py
new file mode 100644
index 0000000..a62d923
--- /dev/null
+++ b/Lib/test/test_hashlib_speed.py
@@ -0,0 +1,93 @@
+
+import sys, time
+import hashlib
+from test import test_support
+
+
+def creatorFunc():
+ raise RuntimeError, "eek, creatorFunc not overridden"
+
+
+def test_scaled_msg(scale, name):
+
+ iterations = 106201/scale * 20
+ longStr = 'Z'*scale
+
+ localCF = creatorFunc
+ start = time.time()
+ for f in xrange(iterations):
+ x = localCF(longStr).digest()
+ end = time.time()
+
+ print ('%2.2f' % (end-start)), "seconds", iterations, "x", len(longStr), "bytes", name
+
+def test_create():
+ start = time.time()
+ for f in xrange(20000):
+ d = creatorFunc()
+ end = time.time()
+
+ print ('%2.2f' % (end-start)), "seconds", '[20000 creations]'
+
+def test_zero():
+ start = time.time()
+ for f in xrange(20000):
+ x = creatorFunc().digest()
+ end = time.time()
+
+ print ('%2.2f' % (end-start)), "seconds", '[20000 "" digests]'
+
+
+
+### this 'test' is not normally run. skip it if the test runner finds it
+if __name__ != '__main__':
+ raise test_support.TestSkipped, "not a unit test (stand alone benchmark)"
+
+hName = sys.argv[1]
+
+#
+# setup our creatorFunc to test the requested hash
+#
+if hName in ('_md5', '_sha'):
+ exec 'import '+hName
+ exec 'creatorFunc = '+hName+'.new'
+ print "testing speed of old", hName, "legacy interface"
+elif hName == '_hashlib' and len(sys.argv) > 3:
+ import _hashlib
+ exec 'creatorFunc = _hashlib.%s' % sys.argv[2]
+ print "testing speed of _hashlib.%s" % sys.argv[2], getattr(_hashlib, sys.argv[2])
+elif hName == '_hashlib' and len(sys.argv) == 3:
+ import _hashlib
+ exec 'creatorFunc = lambda x=_hashlib.new : x(%r)' % sys.argv[2]
+ print "testing speed of _hashlib.new(%r)" % sys.argv[2]
+elif hasattr(hashlib, hName) and callable(getattr(hashlib, hName)):
+ creatorFunc = getattr(hashlib, hName)
+ print "testing speed of hashlib."+hName, getattr(hashlib, hName)
+else:
+ exec "creatorFunc = lambda x=hashlib.new : x(%r)" % hName
+ print "testing speed of hashlib.new(%r)" % hName
+
+try:
+ test_create()
+except ValueError:
+ print
+ print "pass argument(s) naming the hash to run a speed test on:"
+ print " '_md5' and '_sha' test the legacy builtin md5 and sha"
+ print " '_hashlib' 'openssl_hName' 'fast' tests the builtin _hashlib"
+ print " '_hashlib' 'hName' tests builtin _hashlib.new(shaFOO)"
+ print " 'hName' tests the hashlib.hName() implementation if it exists"
+ print " otherwise it uses hashlib.new(hName)."
+ print
+ raise
+
+test_zero()
+test_scaled_msg(scale=106201, name='[huge data]')
+test_scaled_msg(scale=10620, name='[large data]')
+test_scaled_msg(scale=1062, name='[medium data]')
+test_scaled_msg(scale=424, name='[4*small data]')
+test_scaled_msg(scale=336, name='[3*small data]')
+test_scaled_msg(scale=212, name='[2*small data]')
+test_scaled_msg(scale=106, name='[small data]')
+test_scaled_msg(scale=creatorFunc().digest_size, name='[digest_size data]')
+test_scaled_msg(scale=10, name='[tiny data]')
+
diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py
index b365794..9d094d2 100644
--- a/Lib/test/test_hmac.py
+++ b/Lib/test/test_hmac.py
@@ -105,9 +105,10 @@
def test_default_is_md5(self):
# Testing if HMAC defaults to MD5 algorithm.
- import md5
+ # NOTE: this whitebox test depends on the hmac class internals
+ import hashlib
h = hmac.HMAC("key")
- self.failUnless(h.digestmod == md5)
+ self.failUnless(h.digest_cons == hashlib.md5)
def test_exercise_all_methods(self):
# Exercising all methods once.
@@ -127,8 +128,8 @@
# Testing if attributes are of same type.
h1 = hmac.HMAC("key")
h2 = h1.copy()
- self.failUnless(h1.digestmod == h2.digestmod,
- "Modules don't match.")
+ self.failUnless(h1.digest_cons == h2.digest_cons,
+ "digest constructors don't match.")
self.failUnless(type(h1.inner) == type(h2.inner),
"Types of inner don't match.")
self.failUnless(type(h1.outer) == type(h2.outer),
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
new file mode 100644
index 0000000..bfa180c
--- /dev/null
+++ b/Modules/_hashopenssl.c
@@ -0,0 +1,487 @@
+/* Module that wraps all OpenSSL hash algorithms */
+
+/*
+ * Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+ * Licensed to PSF under a Contributor Agreement.
+ *
+ * Derived from a skeleton of shamodule.c containing work performed by:
+ *
+ * Andrew Kuchling (amk@amk.ca)
+ * Greg Stein (gstein@lyra.org)
+ *
+ */
+
+#include "Python.h"
+#include "structmember.h"
+
+/* EVP is the preferred interface to hashing in OpenSSL */
+#include <openssl/evp.h>
+
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *name; /* name of this hash algorithm */
+ EVP_MD_CTX ctx; /* OpenSSL message digest context */
+} EVPobject;
+
+
+static PyTypeObject EVPtype;
+
+
+#define DEFINE_CONSTS_FOR_NEW(Name) \
+ static PyObject *CONST_ ## Name ## _name_obj; \
+ static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
+ static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
+
+DEFINE_CONSTS_FOR_NEW(md5);
+DEFINE_CONSTS_FOR_NEW(sha1);
+DEFINE_CONSTS_FOR_NEW(sha224);
+DEFINE_CONSTS_FOR_NEW(sha256);
+DEFINE_CONSTS_FOR_NEW(sha384);
+DEFINE_CONSTS_FOR_NEW(sha512);
+
+
+static EVPobject *
+newEVPobject(PyObject *name)
+{
+ EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
+
+ /* save the name for .name to return */
+ if (retval != NULL) {
+ Py_INCREF(name);
+ retval->name = name;
+ }
+
+ return retval;
+}
+
+/* Internal methods for a hash object */
+
+static void
+EVP_dealloc(PyObject *ptr)
+{
+ EVP_MD_CTX_cleanup(&((EVPobject *)ptr)->ctx);
+ Py_XDECREF(((EVPobject *)ptr)->name);
+ PyObject_Del(ptr);
+}
+
+
+/* External methods for a hash object */
+
+PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object.");
+
+static PyObject *
+EVP_copy(EVPobject *self, PyObject *args)
+{
+ EVPobject *newobj;
+
+ if (!PyArg_ParseTuple(args, ":copy"))
+ return NULL;
+
+ if ( (newobj = newEVPobject(self->name))==NULL)
+ return NULL;
+
+ EVP_MD_CTX_copy(&newobj->ctx, &self->ctx);
+ return (PyObject *)newobj;
+}
+
+PyDoc_STRVAR(EVP_digest__doc__,
+"Return the digest value as a string of binary data.");
+
+static PyObject *
+EVP_digest(EVPobject *self, PyObject *args)
+{
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX temp_ctx;
+ PyObject *retval;
+ unsigned int digest_size;
+
+ if (!PyArg_ParseTuple(args, ":digest"))
+ return NULL;
+
+ EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
+ digest_size = EVP_MD_CTX_size(&temp_ctx);
+ EVP_DigestFinal(&temp_ctx, (char *)digest, NULL);
+
+ retval = PyString_FromStringAndSize((const char *)digest, digest_size);
+ EVP_MD_CTX_cleanup(&temp_ctx);
+ return retval;
+}
+
+PyDoc_STRVAR(EVP_hexdigest__doc__,
+"Return the digest value as a string of hexadecimal digits.");
+
+static PyObject *
+EVP_hexdigest(EVPobject *self, PyObject *args)
+{
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ EVP_MD_CTX temp_ctx;
+ PyObject *retval;
+ char *hex_digest;
+ unsigned int i, j, digest_size;
+
+ if (!PyArg_ParseTuple(args, ":hexdigest"))
+ return NULL;
+
+ /* Get the raw (binary) digest value */
+ EVP_MD_CTX_copy(&temp_ctx, &self->ctx);
+ digest_size = EVP_MD_CTX_size(&temp_ctx);
+ EVP_DigestFinal(&temp_ctx, digest, NULL);
+
+ EVP_MD_CTX_cleanup(&temp_ctx);
+
+ /* Create a new string */
+ /* NOTE: not thread safe! modifying an already created string object */
+ /* (not a problem because we hold the GIL by default) */
+ retval = PyString_FromStringAndSize(NULL, digest_size * 2);
+ if (!retval)
+ return NULL;
+ hex_digest = PyString_AsString(retval);
+ if (!hex_digest) {
+ Py_DECREF(retval);
+ return NULL;
+ }
+
+ /* Make hex version of the digest */
+ for(i=j=0; i<digest_size; i++) {
+ char c;
+ c = (digest[i] >> 4) & 0xf;
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ c = (digest[i] & 0xf);
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ }
+ return retval;
+}
+
+PyDoc_STRVAR(EVP_update__doc__,
+"Update this hash object's state with the provided string.");
+
+static PyObject *
+EVP_update(EVPobject *self, PyObject *args)
+{
+ unsigned char *cp;
+ int len;
+
+ if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ return NULL;
+
+ EVP_DigestUpdate(&self->ctx, cp, len);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef EVP_methods[] = {
+ {"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__},
+ {"digest", (PyCFunction)EVP_digest, METH_VARARGS, EVP_digest__doc__},
+ {"hexdigest", (PyCFunction)EVP_hexdigest, METH_VARARGS, EVP_hexdigest__doc__},
+ {"copy", (PyCFunction)EVP_copy, METH_VARARGS, EVP_copy__doc__},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject *
+EVP_get_block_size(EVPobject *self, void *closure)
+{
+ return PyInt_FromLong(EVP_MD_CTX_block_size(&((EVPobject *)self)->ctx));
+}
+
+static PyObject *
+EVP_get_digest_size(EVPobject *self, void *closure)
+{
+ return PyInt_FromLong(EVP_MD_CTX_size(&((EVPobject *)self)->ctx));
+}
+
+static PyMemberDef EVP_members[] = {
+ {"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
+ {NULL} /* Sentinel */
+};
+
+static PyGetSetDef EVP_getseters[] = {
+ {"digest_size",
+ (getter)EVP_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {"block_size",
+ (getter)EVP_get_block_size, NULL,
+ NULL,
+ NULL},
+ /* the old md5 and sha modules support 'digest_size' as in PEP 247.
+ * the old sha module also supported 'digestsize'. ugh. */
+ {"digestsize",
+ (getter)EVP_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {NULL} /* Sentinel */
+};
+
+
+static PyObject *
+EVP_repr(PyObject *self)
+{
+ char buf[100];
+ PyOS_snprintf(buf, sizeof(buf), "<%s HASH object @ %p>",
+ PyString_AsString(((EVPobject *)self)->name), self);
+ return PyString_FromString(buf);
+}
+
+#if HASH_OBJ_CONSTRUCTOR
+static int
+EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"name", "string", NULL};
+ PyObject *name_obj = NULL;
+ char *nameStr;
+ unsigned char *cp = NULL;
+ unsigned int len;
+ const EVP_MD *digest;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s#:HASH", kwlist,
+ &name_obj, &cp, &len)) {
+ return -1;
+ }
+
+ if (!PyArg_Parse(name_obj, "s", &nameStr)) {
+ PyErr_SetString(PyExc_TypeError, "name must be a string");
+ return -1;
+ }
+
+ digest = EVP_get_digestbyname(nameStr);
+ if (!digest) {
+ PyErr_SetString(PyExc_ValueError, "unknown hash function");
+ return -1;
+ }
+ EVP_DigestInit(&self->ctx, digest);
+
+ self->name = name_obj;
+ Py_INCREF(self->name);
+
+ if (cp && len)
+ EVP_DigestUpdate(&self->ctx, cp, len);
+
+ return 0;
+}
+#endif
+
+
+PyDoc_STRVAR(hashtype_doc,
+"A hash represents the object used to calculate a checksum of a\n\
+string of information.\n\
+\n\
+Methods:\n\
+\n\
+update() -- updates the current digest with an additional string\n\
+digest() -- return the current digest value\n\
+hexdigest() -- return the current digest as a string of hexadecimal digits\n\
+copy() -- return a copy of the current hash object\n\
+\n\
+Attributes:\n\
+\n\
+name -- the hash algorithm being used by this object\n\
+digest_size -- number of bytes in this hashes output\n");
+
+static PyTypeObject EVPtype = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_hashlib.HASH", /*tp_name*/
+ sizeof(EVPobject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ EVP_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ EVP_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ hashtype_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ EVP_methods, /* tp_methods */
+ EVP_members, /* tp_members */
+ EVP_getseters, /* tp_getset */
+#if 1
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+#endif
+#if HASH_OBJ_CONSTRUCTOR
+ (initproc)EVP_tp_init, /* tp_init */
+#endif
+};
+
+static PyObject *
+EVPnew(PyObject *name_obj,
+ const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
+ const char *cp, unsigned int len)
+{
+ EVPobject *self;
+
+ if (!digest && !initial_ctx) {
+ PyErr_SetString(PyExc_ValueError, "unsupported hash type");
+ return NULL;
+ }
+
+ if ((self = newEVPobject(name_obj)) == NULL)
+ return NULL;
+
+ if (initial_ctx) {
+ EVP_MD_CTX_copy(&self->ctx, initial_ctx);
+ } else {
+ EVP_DigestInit(&self->ctx, digest);
+ }
+
+ if (cp && len)
+ EVP_DigestUpdate(&self->ctx, cp, len);
+
+ return (PyObject *)self;
+}
+
+
+/* The module-level function: new() */
+
+PyDoc_STRVAR(EVP_new__doc__,
+"Return a new hash object using the named algorithm.\n\
+An optional string argument may be provided and will be\n\
+automatically hashed.\n\
+\n\
+The MD5 and SHA1 algorithms are always supported.\n");
+
+static PyObject *
+EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = {"name", "string", NULL};
+ PyObject *name_obj = NULL;
+ char *name;
+ const EVP_MD *digest;
+ unsigned char *cp = NULL;
+ unsigned int len;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s#:new", kwlist,
+ &name_obj, &cp, &len)) {
+ return NULL;
+ }
+
+ if (!PyArg_Parse(name_obj, "s", &name)) {
+ PyErr_SetString(PyExc_TypeError, "name must be a string");
+ return NULL;
+ }
+
+ digest = EVP_get_digestbyname(name);
+
+ return EVPnew(name_obj, digest, NULL, cp, len);
+}
+
+/*
+ * This macro generates constructor function definitions for specific
+ * hash algorithms. These constructors are much faster than calling
+ * the generic one passing it a python string and are noticably
+ * faster than calling a python new() wrapper. Thats important for
+ * code that wants to make hashes of a bunch of small strings.
+ */
+#define GEN_CONSTRUCTOR(NAME) \
+ static PyObject * \
+ EVP_new_ ## NAME (PyObject *self, PyObject *args) \
+ { \
+ unsigned char *cp = NULL; \
+ unsigned int len; \
+ \
+ if (!PyArg_ParseTuple(args, "|s#:" #NAME , &cp, &len)) { \
+ return NULL; \
+ } \
+ \
+ return EVPnew( \
+ CONST_ ## NAME ## _name_obj, \
+ NULL, \
+ CONST_new_ ## NAME ## _ctx_p, \
+ cp, len); \
+ }
+
+/* a PyMethodDef structure for the constructor */
+#define CONSTRUCTOR_METH_DEF(NAME) \
+ {"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
+ PyDoc_STR("Returns a " #NAME \
+ " hash object; optionally initialized with a string") \
+ }
+
+/* used in the init function to setup a constructor */
+#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
+ CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
+ if (EVP_get_digestbyname(#NAME)) { \
+ CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
+ EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
+ } \
+} while (0);
+
+GEN_CONSTRUCTOR(md5)
+GEN_CONSTRUCTOR(sha1)
+GEN_CONSTRUCTOR(sha224)
+GEN_CONSTRUCTOR(sha256)
+GEN_CONSTRUCTOR(sha384)
+GEN_CONSTRUCTOR(sha512)
+
+/* List of functions exported by this module */
+
+static struct PyMethodDef EVP_functions[] = {
+ {"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__},
+ CONSTRUCTOR_METH_DEF(md5),
+ CONSTRUCTOR_METH_DEF(sha1),
+ CONSTRUCTOR_METH_DEF(sha224),
+ CONSTRUCTOR_METH_DEF(sha256),
+ CONSTRUCTOR_METH_DEF(sha384),
+ CONSTRUCTOR_METH_DEF(sha512),
+ {NULL, NULL} /* Sentinel */
+};
+
+
+/* Initialize this module. */
+
+PyMODINIT_FUNC
+init_hashlib(void)
+{
+ PyObject *m;
+
+ OpenSSL_add_all_digests();
+
+ /* TODO build EVP_functions openssl_* entries dynamically based
+ * on what hashes are supported rather than listing many
+ * but having some be unsupported. Only init appropriate
+ * constants. */
+
+ EVPtype.ob_type = &PyType_Type;
+ if (PyType_Ready(&EVPtype) < 0)
+ return;
+
+ m = Py_InitModule("_hashlib", EVP_functions);
+ if (m == NULL)
+ return;
+
+#if HASH_OBJ_CONSTRUCTOR
+ Py_INCREF(&EVPtype);
+ PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
+#endif
+
+ /* these constants are used by the convenience constructors */
+ INIT_CONSTRUCTOR_CONSTANTS(md5);
+ INIT_CONSTRUCTOR_CONSTANTS(sha1);
+ INIT_CONSTRUCTOR_CONSTANTS(sha224);
+ INIT_CONSTRUCTOR_CONSTANTS(sha256);
+ INIT_CONSTRUCTOR_CONSTANTS(sha384);
+ INIT_CONSTRUCTOR_CONSTANTS(sha512);
+}
diff --git a/Modules/md5module.c b/Modules/md5module.c
index 65b83a7..9c647c5 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -10,6 +10,7 @@
/* MD5 objects */
#include "Python.h"
+#include "structmember.h"
#include "md5.h"
typedef struct {
@@ -150,15 +151,46 @@
};
static PyObject *
-md5_getattr(md5object *self, char *name)
+md5_get_block_size(PyObject *self, void *closure)
{
- if (strcmp(name, "digest_size") == 0) {
- return PyInt_FromLong(16);
- }
-
- return Py_FindMethod(md5_methods, (PyObject *)self, name);
+ return PyInt_FromLong(64);
}
+static PyObject *
+md5_get_digest_size(PyObject *self, void *closure)
+{
+ return PyInt_FromLong(16);
+}
+
+static PyObject *
+md5_get_name(PyObject *self, void *closure)
+{
+ return PyString_FromStringAndSize("MD5", 3);
+}
+
+static PyGetSetDef md5_getseters[] = {
+ {"digest_size",
+ (getter)md5_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {"block_size",
+ (getter)md5_get_block_size, NULL,
+ NULL,
+ NULL},
+ {"name",
+ (getter)md5_get_name, NULL,
+ NULL,
+ NULL},
+ /* the old md5 and sha modules support 'digest_size' as in PEP 247.
+ * the old sha module also supported 'digestsize'. ugh. */
+ {"digestsize",
+ (getter)md5_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {NULL} /* Sentinel */
+};
+
+
PyDoc_STRVAR(module_doc,
"This module implements the interface to RSA's MD5 message digest\n\
algorithm (see also Internet RFC 1321). Its use is quite\n\
@@ -191,13 +223,13 @@
static PyTypeObject MD5type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
- "md5.md5", /*tp_name*/
+ "_md5.md5", /*tp_name*/
sizeof(md5object), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)md5_dealloc, /*tp_dealloc*/
0, /*tp_print*/
- (getattrfunc)md5_getattr, /*tp_getattr*/
+ 0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
@@ -210,8 +242,17 @@
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
- 0, /*tp_xxx4*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
md5type_doc, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ md5_methods, /*tp_methods*/
+ 0, /*tp_members*/
+ md5_getseters, /*tp_getset*/
};
@@ -247,7 +288,6 @@
static PyMethodDef md5_functions[] = {
{"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
- {"md5", (PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
{NULL, NULL} /* Sentinel */
};
@@ -255,12 +295,14 @@
/* Initialize this module. */
PyMODINIT_FUNC
-initmd5(void)
+init_md5(void)
{
PyObject *m, *d;
MD5type.ob_type = &PyType_Type;
- m = Py_InitModule3("md5", md5_functions, module_doc);
+ if (PyType_Ready(&MD5type) < 0)
+ return;
+ m = Py_InitModule3("_md5", md5_functions, module_doc);
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
PyModule_AddIntConstant(m, "digest_size", 16);
diff --git a/Modules/sha256module.c b/Modules/sha256module.c
new file mode 100644
index 0000000..8da36b7
--- /dev/null
+++ b/Modules/sha256module.c
@@ -0,0 +1,709 @@
+/* SHA256 module */
+
+/* This module provides an interface to NIST's SHA-256 and SHA-224 Algorithms */
+
+/* See below for information about the original code this module was
+ based upon. Additional work performed by:
+
+ Andrew Kuchling (amk@amk.ca)
+ Greg Stein (gstein@lyra.org)
+ Trevor Perrin (trevp@trevp.net)
+
+ Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+ Licensed to PSF under a Contributor Agreement.
+
+*/
+
+/* SHA objects */
+
+#include "Python.h"
+#include "structmember.h"
+
+
+/* Endianness testing and definitions */
+#define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
+ if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
+
+#define PCT_LITTLE_ENDIAN 1
+#define PCT_BIG_ENDIAN 0
+
+/* Some useful types */
+
+typedef unsigned char SHA_BYTE;
+
+#if SIZEOF_INT == 4
+typedef unsigned int SHA_INT32; /* 32-bit integer */
+#else
+/* not defined. compilation will die. */
+#endif
+
+/* The SHA block size and message digest sizes, in bytes */
+
+#define SHA_BLOCKSIZE 64
+#define SHA_DIGESTSIZE 32
+
+/* The structure for storing SHA info */
+
+typedef struct {
+ PyObject_HEAD
+ SHA_INT32 digest[8]; /* Message digest */
+ SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
+ SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
+ int Endianness;
+ int local; /* unprocessed amount in data */
+ int digestsize;
+} SHAobject;
+
+/* When run on a little-endian CPU we need to perform byte reversal on an
+ array of longwords. */
+
+static void longReverse(SHA_INT32 *buffer, int byteCount, int Endianness)
+{
+ SHA_INT32 value;
+
+ if ( Endianness == PCT_BIG_ENDIAN )
+ return;
+
+ byteCount /= sizeof(*buffer);
+ while (byteCount--) {
+ value = *buffer;
+ value = ( ( value & 0xFF00FF00L ) >> 8 ) | \
+ ( ( value & 0x00FF00FFL ) << 8 );
+ *buffer++ = ( value << 16 ) | ( value >> 16 );
+ }
+}
+
+static void SHAcopy(SHAobject *src, SHAobject *dest)
+{
+ dest->Endianness = src->Endianness;
+ dest->local = src->local;
+ dest->digestsize = src->digestsize;
+ dest->count_lo = src->count_lo;
+ dest->count_hi = src->count_hi;
+ memcpy(dest->digest, src->digest, sizeof(src->digest));
+ memcpy(dest->data, src->data, sizeof(src->data));
+}
+
+
+/* ------------------------------------------------------------------------
+ *
+ * This code for the SHA-256 algorithm was noted as public domain. The
+ * original headers are pasted below.
+ *
+ * Several changes have been made to make it more compatible with the
+ * Python environment and desired interface.
+ *
+ */
+
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * gurantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+
+/* SHA256 by Tom St Denis */
+
+/* Various logical functions */
+#define ROR(x, y)\
+( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
+((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) ROR((x),(n))
+#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+
+static void
+sha_transform(SHAobject *sha_info)
+{
+ int i;
+ SHA_INT32 S[8], W[64], t0, t1;
+
+ memcpy(W, sha_info->data, sizeof(sha_info->data));
+ longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
+
+ for (i = 16; i < 64; ++i) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+ }
+ for (i = 0; i < 8; ++i) {
+ S[i] = sha_info->digest[i];
+ }
+
+ /* Compress */
+#define RND(a,b,c,d,e,f,g,h,i,ki) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
+
+#undef RND
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ sha_info->digest[i] = sha_info->digest[i] + S[i];
+ }
+
+}
+
+
+
+/* initialize the SHA digest */
+
+static void
+sha_init(SHAobject *sha_info)
+{
+ TestEndianness(sha_info->Endianness)
+ sha_info->digest[0] = 0x6A09E667L;
+ sha_info->digest[1] = 0xBB67AE85L;
+ sha_info->digest[2] = 0x3C6EF372L;
+ sha_info->digest[3] = 0xA54FF53AL;
+ sha_info->digest[4] = 0x510E527FL;
+ sha_info->digest[5] = 0x9B05688CL;
+ sha_info->digest[6] = 0x1F83D9ABL;
+ sha_info->digest[7] = 0x5BE0CD19L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+ sha_info->digestsize = 32;
+}
+
+static void
+sha224_init(SHAobject *sha_info)
+{
+ TestEndianness(sha_info->Endianness)
+ sha_info->digest[0] = 0xc1059ed8L;
+ sha_info->digest[1] = 0x367cd507L;
+ sha_info->digest[2] = 0x3070dd17L;
+ sha_info->digest[3] = 0xf70e5939L;
+ sha_info->digest[4] = 0xffc00b31L;
+ sha_info->digest[5] = 0x68581511L;
+ sha_info->digest[6] = 0x64f98fa7L;
+ sha_info->digest[7] = 0xbefa4fa4L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+ sha_info->digestsize = 28;
+}
+
+
+/* update the SHA digest */
+
+static void
+sha_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
+{
+ int i;
+ SHA_INT32 clo;
+
+ clo = sha_info->count_lo + ((SHA_INT32) count << 3);
+ if (clo < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo = clo;
+ sha_info->count_hi += (SHA_INT32) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+/* finish computing the SHA digest */
+
+static void
+sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
+{
+ int count;
+ SHA_INT32 lo_bit_count, hi_bit_count;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((SHA_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - count);
+ sha_transform(sha_info);
+ memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ }
+ else {
+ memset(((SHA_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+
+ /* GJS: note that we add the hi/lo in big-endian. sha_transform will
+ swap these values into host-order. */
+ sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
+ sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
+ sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
+ sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
+ sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
+ sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
+ sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
+ sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
+ sha_transform(sha_info);
+ digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
+ digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
+ digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
+ digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
+ digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
+ digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
+ digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
+ digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
+ digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
+ digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
+ digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
+ digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
+ digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
+ digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
+ digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
+ digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
+ digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
+ digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
+ digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
+ digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
+ digest[20] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
+ digest[21] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
+ digest[22] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
+ digest[23] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
+ digest[24] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
+ digest[25] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
+ digest[26] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
+ digest[27] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
+ digest[28] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
+ digest[29] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
+ digest[30] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
+ digest[31] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
+}
+
+/*
+ * End of copied SHA code.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static PyTypeObject SHA224type;
+static PyTypeObject SHA256type;
+
+
+static SHAobject *
+newSHA224object(void)
+{
+ return (SHAobject *)PyObject_New(SHAobject, &SHA224type);
+}
+
+static SHAobject *
+newSHA256object(void)
+{
+ return (SHAobject *)PyObject_New(SHAobject, &SHA256type);
+}
+
+/* Internal methods for a hash object */
+
+static void
+SHA_dealloc(PyObject *ptr)
+{
+ PyObject_Del(ptr);
+}
+
+
+/* External methods for a hash object */
+
+PyDoc_STRVAR(SHA256_copy__doc__, "Return a copy of the hash object.");
+
+static PyObject *
+SHA256_copy(SHAobject *self, PyObject *args)
+{
+ SHAobject *newobj;
+
+ if (!PyArg_ParseTuple(args, ":copy")) {
+ return NULL;
+ }
+
+ if (((PyObject*)self)->ob_type == &SHA256type) {
+ if ( (newobj = newSHA256object())==NULL)
+ return NULL;
+ } else {
+ if ( (newobj = newSHA224object())==NULL)
+ return NULL;
+ }
+
+ SHAcopy(self, newobj);
+ return (PyObject *)newobj;
+}
+
+PyDoc_STRVAR(SHA256_digest__doc__,
+"Return the digest value as a string of binary data.");
+
+static PyObject *
+SHA256_digest(SHAobject *self, PyObject *args)
+{
+ unsigned char digest[SHA_DIGESTSIZE];
+ SHAobject temp;
+
+ if (!PyArg_ParseTuple(args, ":digest"))
+ return NULL;
+
+ SHAcopy(self, &temp);
+ sha_final(digest, &temp);
+ return PyString_FromStringAndSize((const char *)digest, self->digestsize);
+}
+
+PyDoc_STRVAR(SHA256_hexdigest__doc__,
+"Return the digest value as a string of hexadecimal digits.");
+
+static PyObject *
+SHA256_hexdigest(SHAobject *self, PyObject *args)
+{
+ unsigned char digest[SHA_DIGESTSIZE];
+ SHAobject temp;
+ PyObject *retval;
+ char *hex_digest;
+ int i, j;
+
+ if (!PyArg_ParseTuple(args, ":hexdigest"))
+ return NULL;
+
+ /* Get the raw (binary) digest value */
+ SHAcopy(self, &temp);
+ sha_final(digest, &temp);
+
+ /* Create a new string */
+ retval = PyString_FromStringAndSize(NULL, self->digestsize * 2);
+ if (!retval)
+ return NULL;
+ hex_digest = PyString_AsString(retval);
+ if (!hex_digest) {
+ Py_DECREF(retval);
+ return NULL;
+ }
+
+ /* Make hex version of the digest */
+ for(i=j=0; i<self->digestsize; i++) {
+ char c;
+ c = (digest[i] >> 4) & 0xf;
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ c = (digest[i] & 0xf);
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ }
+ return retval;
+}
+
+PyDoc_STRVAR(SHA256_update__doc__,
+"Update this hash object's state with the provided string.");
+
+static PyObject *
+SHA256_update(SHAobject *self, PyObject *args)
+{
+ unsigned char *cp;
+ int len;
+
+ if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ return NULL;
+
+ sha_update(self, cp, len);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef SHA_methods[] = {
+ {"copy", (PyCFunction)SHA256_copy, METH_VARARGS, SHA256_copy__doc__},
+ {"digest", (PyCFunction)SHA256_digest, METH_VARARGS, SHA256_digest__doc__},
+ {"hexdigest", (PyCFunction)SHA256_hexdigest, METH_VARARGS, SHA256_hexdigest__doc__},
+ {"update", (PyCFunction)SHA256_update, METH_VARARGS, SHA256_update__doc__},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject *
+SHA256_get_block_size(PyObject *self, void *closure)
+{
+ return PyInt_FromLong(SHA_BLOCKSIZE);
+}
+
+static PyObject *
+SHA256_get_name(PyObject *self, void *closure)
+{
+ if (((SHAobject *)self)->digestsize == 32)
+ return PyString_FromStringAndSize("SHA256", 6);
+ else
+ return PyString_FromStringAndSize("SHA224", 6);
+}
+
+static PyGetSetDef SHA_getseters[] = {
+ {"block_size",
+ (getter)SHA256_get_block_size, NULL,
+ NULL,
+ NULL},
+ {"name",
+ (getter)SHA256_get_name, NULL,
+ NULL,
+ NULL},
+ {NULL} /* Sentinel */
+};
+
+static PyMemberDef SHA_members[] = {
+ {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
+ /* the old md5 and sha modules support 'digest_size' as in PEP 247.
+ * the old sha module also supported 'digestsize'. ugh. */
+ {"digestsize", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject SHA224type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_sha256.sha224", /*tp_name*/
+ sizeof(SHAobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ SHA_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ SHA_methods, /* tp_methods */
+ SHA_members, /* tp_members */
+ SHA_getseters, /* tp_getset */
+};
+
+static PyTypeObject SHA256type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_sha256.sha256", /*tp_name*/
+ sizeof(SHAobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ SHA_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ SHA_methods, /* tp_methods */
+ SHA_members, /* tp_members */
+ SHA_getseters, /* tp_getset */
+};
+
+
+/* The single module-level function: new() */
+
+PyDoc_STRVAR(SHA256_new__doc__,
+"Return a new SHA-256 hash object; optionally initialized with a string.");
+
+static PyObject *
+SHA256_new(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = {"string", NULL};
+ SHAobject *new;
+ unsigned char *cp = NULL;
+ int len;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
+ &cp, &len)) {
+ return NULL;
+ }
+
+ if ((new = newSHA256object()) == NULL)
+ return NULL;
+
+ sha_init(new);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(new);
+ return NULL;
+ }
+ if (cp)
+ sha_update(new, cp, len);
+
+ return (PyObject *)new;
+}
+
+PyDoc_STRVAR(SHA224_new__doc__,
+"Return a new SHA-224 hash object; optionally initialized with a string.");
+
+static PyObject *
+SHA224_new(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = {"string", NULL};
+ SHAobject *new;
+ unsigned char *cp = NULL;
+ int len;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
+ &cp, &len)) {
+ return NULL;
+ }
+
+ if ((new = newSHA224object()) == NULL)
+ return NULL;
+
+ sha224_init(new);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(new);
+ return NULL;
+ }
+ if (cp)
+ sha_update(new, cp, len);
+
+ return (PyObject *)new;
+}
+
+
+/* List of functions exported by this module */
+
+static struct PyMethodDef SHA_functions[] = {
+ {"sha256", (PyCFunction)SHA256_new, METH_VARARGS|METH_KEYWORDS, SHA256_new__doc__},
+ {"sha224", (PyCFunction)SHA224_new, METH_VARARGS|METH_KEYWORDS, SHA224_new__doc__},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+/* Initialize this module. */
+
+#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
+
+PyMODINIT_FUNC
+init_sha256(void)
+{
+ PyObject *m;
+
+ SHA224type.ob_type = &PyType_Type;
+ if (PyType_Ready(&SHA224type) < 0)
+ return;
+ SHA256type.ob_type = &PyType_Type;
+ if (PyType_Ready(&SHA256type) < 0)
+ return;
+ m = Py_InitModule("_sha256", SHA_functions);
+}
diff --git a/Modules/sha512module.c b/Modules/sha512module.c
new file mode 100644
index 0000000..0d97fb6
--- /dev/null
+++ b/Modules/sha512module.c
@@ -0,0 +1,777 @@
+/* SHA512 module */
+
+/* This module provides an interface to NIST's SHA-512 and SHA-384 Algorithms */
+
+/* See below for information about the original code this module was
+ based upon. Additional work performed by:
+
+ Andrew Kuchling (amk@amk.ca)
+ Greg Stein (gstein@lyra.org)
+ Trevor Perrin (trevp@trevp.net)
+
+ Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+ Licensed to PSF under a Contributor Agreement.
+
+*/
+
+/* SHA objects */
+
+#include "Python.h"
+#include "structmember.h"
+
+#ifdef PY_LONG_LONG /* If no PY_LONG_LONG, don't compile anything! */
+
+/* Endianness testing and definitions */
+#define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
+ if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
+
+#define PCT_LITTLE_ENDIAN 1
+#define PCT_BIG_ENDIAN 0
+
+/* Some useful types */
+
+typedef unsigned char SHA_BYTE;
+
+#if SIZEOF_INT == 4
+typedef unsigned int SHA_INT32; /* 32-bit integer */
+typedef unsigned PY_LONG_LONG SHA_INT64; /* 64-bit integer */
+#else
+/* not defined. compilation will die. */
+#endif
+
+/* The SHA block size and message digest sizes, in bytes */
+
+#define SHA_BLOCKSIZE 128
+#define SHA_DIGESTSIZE 64
+
+/* The structure for storing SHA info */
+
+typedef struct {
+ PyObject_HEAD
+ SHA_INT64 digest[8]; /* Message digest */
+ SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
+ SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
+ int Endianness;
+ int local; /* unprocessed amount in data */
+ int digestsize;
+} SHAobject;
+
+/* When run on a little-endian CPU we need to perform byte reversal on an
+ array of longwords. */
+
+static void longReverse(SHA_INT64 *buffer, int byteCount, int Endianness)
+{
+ SHA_INT64 value;
+
+ if ( Endianness == PCT_BIG_ENDIAN )
+ return;
+
+ byteCount /= sizeof(*buffer);
+ while (byteCount--) {
+ value = *buffer;
+
+ ((unsigned char*)buffer)[0] = (unsigned char)(value >> 56) & 0xff;
+ ((unsigned char*)buffer)[1] = (unsigned char)(value >> 48) & 0xff;
+ ((unsigned char*)buffer)[2] = (unsigned char)(value >> 40) & 0xff;
+ ((unsigned char*)buffer)[3] = (unsigned char)(value >> 32) & 0xff;
+ ((unsigned char*)buffer)[4] = (unsigned char)(value >> 24) & 0xff;
+ ((unsigned char*)buffer)[5] = (unsigned char)(value >> 16) & 0xff;
+ ((unsigned char*)buffer)[6] = (unsigned char)(value >> 8) & 0xff;
+ ((unsigned char*)buffer)[7] = (unsigned char)(value ) & 0xff;
+
+ buffer++;
+ }
+}
+
+static void SHAcopy(SHAobject *src, SHAobject *dest)
+{
+ dest->Endianness = src->Endianness;
+ dest->local = src->local;
+ dest->digestsize = src->digestsize;
+ dest->count_lo = src->count_lo;
+ dest->count_hi = src->count_hi;
+ memcpy(dest->digest, src->digest, sizeof(src->digest));
+ memcpy(dest->data, src->data, sizeof(src->data));
+}
+
+
+/* ------------------------------------------------------------------------
+ *
+ * This code for the SHA-512 algorithm was noted as public domain. The
+ * original headers are pasted below.
+ *
+ * Several changes have been made to make it more compatible with the
+ * Python environment and desired interface.
+ *
+ */
+
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * gurantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
+ */
+
+
+/* SHA512 by Tom St Denis */
+
+/* Various logical functions */
+#define ROR64(x, y) \
+ ( ((((x) & 0xFFFFFFFFFFFFFFFFULL)>>((unsigned PY_LONG_LONG)(y) & 63)) | \
+ ((x)<<((unsigned PY_LONG_LONG)(64-((y) & 63))))) & 0xFFFFFFFFFFFFFFFFULL)
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) ROR64((x),(n))
+#define R(x, n) (((x) & 0xFFFFFFFFFFFFFFFFULL) >> ((unsigned PY_LONG_LONG)n))
+#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+
+
+static void
+sha512_transform(SHAobject *sha_info)
+{
+ int i;
+ SHA_INT64 S[8], W[80], t0, t1;
+
+ memcpy(W, sha_info->data, sizeof(sha_info->data));
+ longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
+
+ for (i = 16; i < 80; ++i) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+ }
+ for (i = 0; i < 8; ++i) {
+ S[i] = sha_info->digest[i];
+ }
+
+ /* Compress */
+#define RND(a,b,c,d,e,f,g,h,i,ki) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98d728ae22ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x7137449123ef65cdULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcfec4d3b2fULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba58189dbbcULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25bf348b538ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1b605d019ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4af194f9bULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5da6d8118ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98a3030242ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b0145706fbeULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be4ee4b28cULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3d5ffb4e2ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74f27b896fULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe3b1696b1ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a725c71235ULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174cf692694ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c19ef14ad2ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786384f25e3ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc68b8cd5b5ULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc77ac9c65ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f592b0275ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa6ea6e483ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dcbd41fbd4ULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da831153b5ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152ee66dfabULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d2db43210ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c898fb213fULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7beef0ee4ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf33da88fc2ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147930aa725ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351e003826fULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x142929670a0e6e70ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a8546d22ffcULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b21385c26c926ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc5ac42aedULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d139d95b3dfULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a73548baf63deULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb3c77b2a8ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e47edaee6ULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c851482353bULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a14cf10364ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664bbc423001ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70d0f89791ULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a30654be30ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819d6ef5218ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd69906245565a910ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e35855771202aULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa07032bbd1b8ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116b8d2d0c8ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c085141ab53ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774cdf8eeb99ULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5e19b48a8ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3c5c95a63ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4ae3418acbULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f7763e373ULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3d6b2b8a3ULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee5defb2fcULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f43172f60ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814a1f0ab72ULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc702081a6439ecULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa23631e28ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506cebde82bde9ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7b2c67915ULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2e372532bULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,0xca273eceea26619cULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,0xd186b8c721c0c207ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,0xeada7dd6cde0eb1eULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,0xf57d4f7fee6ed178ULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,0x06f067aa72176fbaULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,0x0a637dc5a2c898a6ULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,0x113f9804bef90daeULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,0x1b710b35131c471bULL);
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,0x28db77f523047d84ULL);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,0x32caab7b40c72493ULL);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,0x3c9ebe0a15c9bebcULL);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,0x431d67c49c100d4cULL);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,0x4cc5d4becb3e42b6ULL);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,0x597f299cfc657e2aULL);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,0x5fcb6fab3ad6faecULL);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,0x6c44198c4a475817ULL);
+
+#undef RND
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ sha_info->digest[i] = sha_info->digest[i] + S[i];
+ }
+
+}
+
+
+
+/* initialize the SHA digest */
+
+static void
+sha512_init(SHAobject *sha_info)
+{
+ TestEndianness(sha_info->Endianness)
+ sha_info->digest[0] = 0x6a09e667f3bcc908ULL;
+ sha_info->digest[1] = 0xbb67ae8584caa73bULL;
+ sha_info->digest[2] = 0x3c6ef372fe94f82bULL;
+ sha_info->digest[3] = 0xa54ff53a5f1d36f1ULL;
+ sha_info->digest[4] = 0x510e527fade682d1ULL;
+ sha_info->digest[5] = 0x9b05688c2b3e6c1fULL;
+ sha_info->digest[6] = 0x1f83d9abfb41bd6bULL;
+ sha_info->digest[7] = 0x5be0cd19137e2179ULL;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+ sha_info->digestsize = 64;
+}
+
+static void
+sha384_init(SHAobject *sha_info)
+{
+ TestEndianness(sha_info->Endianness)
+ sha_info->digest[0] = 0xcbbb9d5dc1059ed8ULL;
+ sha_info->digest[1] = 0x629a292a367cd507ULL;
+ sha_info->digest[2] = 0x9159015a3070dd17ULL;
+ sha_info->digest[3] = 0x152fecd8f70e5939ULL;
+ sha_info->digest[4] = 0x67332667ffc00b31ULL;
+ sha_info->digest[5] = 0x8eb44a8768581511ULL;
+ sha_info->digest[6] = 0xdb0c2e0d64f98fa7ULL;
+ sha_info->digest[7] = 0x47b5481dbefa4fa4ULL;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+ sha_info->digestsize = 48;
+}
+
+
+/* update the SHA digest */
+
+static void
+sha512_update(SHAobject *sha_info, SHA_BYTE *buffer, int count)
+{
+ int i;
+ SHA_INT32 clo;
+
+ clo = sha_info->count_lo + ((SHA_INT32) count << 3);
+ if (clo < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo = clo;
+ sha_info->count_hi += (SHA_INT32) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ sha512_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ sha512_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+/* finish computing the SHA digest */
+
+static void
+sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
+{
+ int count;
+ SHA_INT32 lo_bit_count, hi_bit_count;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x7f);
+ ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 16) {
+ memset(((SHA_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - count);
+ sha512_transform(sha_info);
+ memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 16);
+ }
+ else {
+ memset(((SHA_BYTE *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 16 - count);
+ }
+
+ /* GJS: note that we add the hi/lo in big-endian. sha512_transform will
+ swap these values into host-order. */
+ sha_info->data[112] = 0;
+ sha_info->data[113] = 0;
+ sha_info->data[114] = 0;
+ sha_info->data[115] = 0;
+ sha_info->data[116] = 0;
+ sha_info->data[117] = 0;
+ sha_info->data[118] = 0;
+ sha_info->data[119] = 0;
+ sha_info->data[120] = (hi_bit_count >> 24) & 0xff;
+ sha_info->data[121] = (hi_bit_count >> 16) & 0xff;
+ sha_info->data[122] = (hi_bit_count >> 8) & 0xff;
+ sha_info->data[123] = (hi_bit_count >> 0) & 0xff;
+ sha_info->data[124] = (lo_bit_count >> 24) & 0xff;
+ sha_info->data[125] = (lo_bit_count >> 16) & 0xff;
+ sha_info->data[126] = (lo_bit_count >> 8) & 0xff;
+ sha_info->data[127] = (lo_bit_count >> 0) & 0xff;
+ sha512_transform(sha_info);
+ digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 56) & 0xff);
+ digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 48) & 0xff);
+ digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 40) & 0xff);
+ digest[ 3] = (unsigned char) ((sha_info->digest[0] >> 32) & 0xff);
+ digest[ 4] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
+ digest[ 5] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
+ digest[ 6] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
+ digest[ 7] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
+ digest[ 8] = (unsigned char) ((sha_info->digest[1] >> 56) & 0xff);
+ digest[ 9] = (unsigned char) ((sha_info->digest[1] >> 48) & 0xff);
+ digest[10] = (unsigned char) ((sha_info->digest[1] >> 40) & 0xff);
+ digest[11] = (unsigned char) ((sha_info->digest[1] >> 32) & 0xff);
+ digest[12] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
+ digest[13] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
+ digest[14] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
+ digest[15] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
+ digest[16] = (unsigned char) ((sha_info->digest[2] >> 56) & 0xff);
+ digest[17] = (unsigned char) ((sha_info->digest[2] >> 48) & 0xff);
+ digest[18] = (unsigned char) ((sha_info->digest[2] >> 40) & 0xff);
+ digest[19] = (unsigned char) ((sha_info->digest[2] >> 32) & 0xff);
+ digest[20] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
+ digest[21] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
+ digest[22] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
+ digest[23] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
+ digest[24] = (unsigned char) ((sha_info->digest[3] >> 56) & 0xff);
+ digest[25] = (unsigned char) ((sha_info->digest[3] >> 48) & 0xff);
+ digest[26] = (unsigned char) ((sha_info->digest[3] >> 40) & 0xff);
+ digest[27] = (unsigned char) ((sha_info->digest[3] >> 32) & 0xff);
+ digest[28] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
+ digest[29] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
+ digest[30] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
+ digest[31] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
+ digest[32] = (unsigned char) ((sha_info->digest[4] >> 56) & 0xff);
+ digest[33] = (unsigned char) ((sha_info->digest[4] >> 48) & 0xff);
+ digest[34] = (unsigned char) ((sha_info->digest[4] >> 40) & 0xff);
+ digest[35] = (unsigned char) ((sha_info->digest[4] >> 32) & 0xff);
+ digest[36] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
+ digest[37] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
+ digest[38] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
+ digest[39] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
+ digest[40] = (unsigned char) ((sha_info->digest[5] >> 56) & 0xff);
+ digest[41] = (unsigned char) ((sha_info->digest[5] >> 48) & 0xff);
+ digest[42] = (unsigned char) ((sha_info->digest[5] >> 40) & 0xff);
+ digest[43] = (unsigned char) ((sha_info->digest[5] >> 32) & 0xff);
+ digest[44] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
+ digest[45] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
+ digest[46] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
+ digest[47] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
+ digest[48] = (unsigned char) ((sha_info->digest[6] >> 56) & 0xff);
+ digest[49] = (unsigned char) ((sha_info->digest[6] >> 48) & 0xff);
+ digest[50] = (unsigned char) ((sha_info->digest[6] >> 40) & 0xff);
+ digest[51] = (unsigned char) ((sha_info->digest[6] >> 32) & 0xff);
+ digest[52] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
+ digest[53] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
+ digest[54] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
+ digest[55] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
+ digest[56] = (unsigned char) ((sha_info->digest[7] >> 56) & 0xff);
+ digest[57] = (unsigned char) ((sha_info->digest[7] >> 48) & 0xff);
+ digest[58] = (unsigned char) ((sha_info->digest[7] >> 40) & 0xff);
+ digest[59] = (unsigned char) ((sha_info->digest[7] >> 32) & 0xff);
+ digest[60] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
+ digest[61] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
+ digest[62] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
+ digest[63] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
+}
+
+/*
+ * End of copied SHA code.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static PyTypeObject SHA384type;
+static PyTypeObject SHA512type;
+
+
+static SHAobject *
+newSHA384object(void)
+{
+ return (SHAobject *)PyObject_New(SHAobject, &SHA384type);
+}
+
+static SHAobject *
+newSHA512object(void)
+{
+ return (SHAobject *)PyObject_New(SHAobject, &SHA512type);
+}
+
+/* Internal methods for a hash object */
+
+static void
+SHA512_dealloc(PyObject *ptr)
+{
+ PyObject_Del(ptr);
+}
+
+
+/* External methods for a hash object */
+
+PyDoc_STRVAR(SHA512_copy__doc__, "Return a copy of the hash object.");
+
+static PyObject *
+SHA512_copy(SHAobject *self, PyObject *args)
+{
+ SHAobject *newobj;
+
+ if (!PyArg_ParseTuple(args, ":copy")) {
+ return NULL;
+ }
+
+ if (((PyObject*)self)->ob_type == &SHA512type) {
+ if ( (newobj = newSHA512object())==NULL)
+ return NULL;
+ } else {
+ if ( (newobj = newSHA384object())==NULL)
+ return NULL;
+ }
+
+ SHAcopy(self, newobj);
+ return (PyObject *)newobj;
+}
+
+PyDoc_STRVAR(SHA512_digest__doc__,
+"Return the digest value as a string of binary data.");
+
+static PyObject *
+SHA512_digest(SHAobject *self, PyObject *args)
+{
+ unsigned char digest[SHA_DIGESTSIZE];
+ SHAobject temp;
+
+ if (!PyArg_ParseTuple(args, ":digest"))
+ return NULL;
+
+ SHAcopy(self, &temp);
+ sha512_final(digest, &temp);
+ return PyString_FromStringAndSize((const char *)digest, self->digestsize);
+}
+
+PyDoc_STRVAR(SHA512_hexdigest__doc__,
+"Return the digest value as a string of hexadecimal digits.");
+
+static PyObject *
+SHA512_hexdigest(SHAobject *self, PyObject *args)
+{
+ unsigned char digest[SHA_DIGESTSIZE];
+ SHAobject temp;
+ PyObject *retval;
+ char *hex_digest;
+ int i, j;
+
+ if (!PyArg_ParseTuple(args, ":hexdigest"))
+ return NULL;
+
+ /* Get the raw (binary) digest value */
+ SHAcopy(self, &temp);
+ sha512_final(digest, &temp);
+
+ /* Create a new string */
+ retval = PyString_FromStringAndSize(NULL, self->digestsize * 2);
+ if (!retval)
+ return NULL;
+ hex_digest = PyString_AsString(retval);
+ if (!hex_digest) {
+ Py_DECREF(retval);
+ return NULL;
+ }
+
+ /* Make hex version of the digest */
+ for(i=j=0; i<self->digestsize; i++) {
+ char c;
+ c = (digest[i] >> 4) & 0xf;
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ c = (digest[i] & 0xf);
+ c = (c>9) ? c+'a'-10 : c + '0';
+ hex_digest[j++] = c;
+ }
+ return retval;
+}
+
+PyDoc_STRVAR(SHA512_update__doc__,
+"Update this hash object's state with the provided string.");
+
+static PyObject *
+SHA512_update(SHAobject *self, PyObject *args)
+{
+ unsigned char *cp;
+ int len;
+
+ if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
+ return NULL;
+
+ sha512_update(self, cp, len);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyMethodDef SHA_methods[] = {
+ {"copy", (PyCFunction)SHA512_copy, METH_VARARGS, SHA512_copy__doc__},
+ {"digest", (PyCFunction)SHA512_digest, METH_VARARGS, SHA512_digest__doc__},
+ {"hexdigest", (PyCFunction)SHA512_hexdigest, METH_VARARGS, SHA512_hexdigest__doc__},
+ {"update", (PyCFunction)SHA512_update, METH_VARARGS, SHA512_update__doc__},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject *
+SHA512_get_block_size(PyObject *self, void *closure)
+{
+ return PyInt_FromLong(SHA_BLOCKSIZE);
+}
+
+static PyObject *
+SHA512_get_name(PyObject *self, void *closure)
+{
+ if (((SHAobject *)self)->digestsize == 64)
+ return PyString_FromStringAndSize("SHA512", 6);
+ else
+ return PyString_FromStringAndSize("SHA384", 6);
+}
+
+static PyGetSetDef SHA_getseters[] = {
+ {"block_size",
+ (getter)SHA512_get_block_size, NULL,
+ NULL,
+ NULL},
+ {"name",
+ (getter)SHA512_get_name, NULL,
+ NULL,
+ NULL},
+ {NULL} /* Sentinel */
+};
+
+static PyMemberDef SHA_members[] = {
+ {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
+ /* the old md5 and sha modules support 'digest_size' as in PEP 247.
+ * the old sha module also supported 'digestsize'. ugh. */
+ {"digestsize", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
+ {NULL} /* Sentinel */
+};
+
+static PyTypeObject SHA384type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_sha512.sha384", /*tp_name*/
+ sizeof(SHAobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ SHA512_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ SHA_methods, /* tp_methods */
+ SHA_members, /* tp_members */
+ SHA_getseters, /* tp_getset */
+};
+
+static PyTypeObject SHA512type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_sha512.sha512", /*tp_name*/
+ sizeof(SHAobject), /*tp_size*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ SHA512_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ SHA_methods, /* tp_methods */
+ SHA_members, /* tp_members */
+ SHA_getseters, /* tp_getset */
+};
+
+
+/* The single module-level function: new() */
+
+PyDoc_STRVAR(SHA512_new__doc__,
+"Return a new SHA-512 hash object; optionally initialized with a string.");
+
+static PyObject *
+SHA512_new(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = {"string", NULL};
+ SHAobject *new;
+ unsigned char *cp = NULL;
+ int len;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
+ &cp, &len)) {
+ return NULL;
+ }
+
+ if ((new = newSHA512object()) == NULL)
+ return NULL;
+
+ sha512_init(new);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(new);
+ return NULL;
+ }
+ if (cp)
+ sha512_update(new, cp, len);
+
+ return (PyObject *)new;
+}
+
+PyDoc_STRVAR(SHA384_new__doc__,
+"Return a new SHA-384 hash object; optionally initialized with a string.");
+
+static PyObject *
+SHA384_new(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ static char *kwlist[] = {"string", NULL};
+ SHAobject *new;
+ unsigned char *cp = NULL;
+ int len;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist,
+ &cp, &len)) {
+ return NULL;
+ }
+
+ if ((new = newSHA384object()) == NULL)
+ return NULL;
+
+ sha384_init(new);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(new);
+ return NULL;
+ }
+ if (cp)
+ sha512_update(new, cp, len);
+
+ return (PyObject *)new;
+}
+
+
+/* List of functions exported by this module */
+
+static struct PyMethodDef SHA_functions[] = {
+ {"sha512", (PyCFunction)SHA512_new, METH_VARARGS|METH_KEYWORDS, SHA512_new__doc__},
+ {"sha384", (PyCFunction)SHA384_new, METH_VARARGS|METH_KEYWORDS, SHA384_new__doc__},
+ {NULL, NULL} /* Sentinel */
+};
+
+
+/* Initialize this module. */
+
+#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
+
+PyMODINIT_FUNC
+init_sha512(void)
+{
+ PyObject *m;
+
+ SHA384type.ob_type = &PyType_Type;
+ if (PyType_Ready(&SHA384type) < 0)
+ return;
+ SHA512type.ob_type = &PyType_Type;
+ if (PyType_Ready(&SHA512type) < 0)
+ return;
+ m = Py_InitModule("_sha512", SHA_functions);
+}
+
+#endif
diff --git a/Modules/shamodule.c b/Modules/shamodule.c
index 1b3b76a..1de61c4 100644
--- a/Modules/shamodule.c
+++ b/Modules/shamodule.c
@@ -7,11 +7,16 @@
Andrew Kuchling (amk@amk.ca)
Greg Stein (gstein@lyra.org)
+
+ Copyright (C) 2005 Gregory P. Smith (greg@electricrain.com)
+ Licensed to PSF under a Contributor Agreement.
+
*/
/* SHA objects */
#include "Python.h"
+#include "structmember.h"
/* Endianness testing and definitions */
@@ -453,26 +458,78 @@
};
static PyObject *
-SHA_getattr(PyObject *self, char *name)
+SHA_get_block_size(PyObject *self, void *closure)
{
- if (strcmp(name, "blocksize")==0)
- return PyInt_FromLong(1);
- if (strcmp(name, "digest_size")==0 || strcmp(name, "digestsize")==0)
- return PyInt_FromLong(20);
-
- return Py_FindMethod(SHA_methods, self, name);
+ return PyInt_FromLong(SHA_BLOCKSIZE);
}
+static PyObject *
+SHA_get_digest_size(PyObject *self, void *closure)
+{
+ return PyInt_FromLong(SHA_DIGESTSIZE);
+}
+
+static PyObject *
+SHA_get_name(PyObject *self, void *closure)
+{
+ return PyString_FromStringAndSize("SHA1", 4);
+}
+
+static PyGetSetDef SHA_getseters[] = {
+ {"digest_size",
+ (getter)SHA_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {"block_size",
+ (getter)SHA_get_block_size, NULL,
+ NULL,
+ NULL},
+ {"name",
+ (getter)SHA_get_name, NULL,
+ NULL,
+ NULL},
+ /* the old md5 and sha modules support 'digest_size' as in PEP 247.
+ * the old sha module also supported 'digestsize'. ugh. */
+ {"digestsize",
+ (getter)SHA_get_digest_size, NULL,
+ NULL,
+ NULL},
+ {NULL} /* Sentinel */
+};
+
static PyTypeObject SHAtype = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
- "sha.SHA", /*tp_name*/
+ "_sha.sha", /*tp_name*/
sizeof(SHAobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
SHA_dealloc, /*tp_dealloc*/
0, /*tp_print*/
- SHA_getattr, /*tp_getattr*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc*/
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ SHA_methods, /* tp_methods */
+ 0, /* tp_members */
+ SHA_getseters, /* tp_getset */
};
@@ -516,7 +573,6 @@
static struct PyMethodDef SHA_functions[] = {
{"new", (PyCFunction)SHA_new, METH_VARARGS|METH_KEYWORDS, SHA_new__doc__},
- {"sha", (PyCFunction)SHA_new, METH_VARARGS|METH_KEYWORDS, SHA_new__doc__},
{NULL, NULL} /* Sentinel */
};
@@ -526,12 +582,14 @@
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
PyMODINIT_FUNC
-initsha(void)
+init_sha(void)
{
PyObject *m;
SHAtype.ob_type = &PyType_Type;
- m = Py_InitModule("sha", SHA_functions);
+ if (PyType_Ready(&SHAtype) < 0)
+ return;
+ m = Py_InitModule("_sha", SHA_functions);
/* Add some symbolic constants to the module */
insint("blocksize", 1); /* For future use, in case some hash
diff --git a/setup.py b/setup.py
index 1f86700..9910236 100644
--- a/setup.py
+++ b/setup.py
@@ -400,15 +400,6 @@
# select(2); not on ancient System V
exts.append( Extension('select', ['selectmodule.c']) )
- # The md5 module implements the RSA Data Security, Inc. MD5
- # Message-Digest Algorithm, described in RFC 1321. The
- # necessary files md5c.c and md5.h are included here.
- exts.append( Extension('md5', ['md5module.c', 'md5c.c']) )
-
- # The sha module implements the SHA checksum algorithm.
- # (NIST's Secure Hash Algorithm.)
- exts.append( Extension('sha', ['shamodule.c']) )
-
# Helper module for various ascii-encoders
exts.append( Extension('binascii', ['binascii.c']) )
@@ -506,6 +497,32 @@
libraries = ['ssl', 'crypto'],
depends = ['socketmodule.h']), )
+ if (ssl_incs is not None and
+ ssl_libs is not None):
+ # The _hashlib module wraps optimized implementations
+ # of hash functions from the OpenSSL library.
+ exts.append( Extension('_hashlib', ['_hashopenssl.c'],
+ include_dirs = ssl_incs,
+ library_dirs = ssl_libs,
+ libraries = ['ssl', 'crypto']) )
+ else:
+ # The _sha module implements the SHA1 hash algorithm.
+ exts.append( Extension('_sha', ['shamodule.c']) )
+ # The _md5 module implements the RSA Data Security, Inc. MD5
+ # Message-Digest Algorithm, described in RFC 1321. The
+ # necessary files md5c.c and md5.h are included here.
+ exts.append( Extension('_md5', ['md5module.c', 'md5c.c']) )
+
+ # always compile these for now under the assumption that
+ # OpenSSL does not support them (it doesn't in common OpenSSL
+ # 0.9.7e installs at the time of this writing; OpenSSL 0.9.8
+ # does). In the future we could make this conditional on
+ # OpenSSL version or support. The hashlib module uses the
+ # better implementation regardless.
+ exts.append( Extension('_sha256', ['sha256module.c']) )
+ exts.append( Extension('_sha512', ['sha512module.c']) )
+
+
# Modules that provide persistent dictionary-like semantics. You will
# probably want to arrange for at least one of them to be available on
# your machine, though none are defined by default because of library