Kaydet (Commit) f21a5f77 authored tarafından Gregory P. Smith's avatar Gregory P. Smith

[ 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.
üst 33a5f2af
......@@ -164,6 +164,7 @@ Joakim Sernbrant
Justin Sheehy
Michael Simcich
Ionel Simionescu
Gregory P. Smith
Roy Smith
Clay Spence
Nicholas Spies
......
......@@ -202,6 +202,7 @@ LIBFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
lib/librgbimg.tex \
lib/libossaudiodev.tex \
lib/libcrypto.tex \
lib/libhashlib.tex \
lib/libmd5.tex \
lib/libsha.tex \
lib/libhmac.tex \
......
......@@ -303,6 +303,7 @@ and how to embed it in other applications.
\input{libcrypto} % Cryptographic Services
\input{libhmac}
\input{libhashlib}
\input{libmd5}
\input{libsha}
......
......@@ -14,8 +14,10 @@ This module implements the HMAC algorithm as described by \rfc{2104}.
\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 @@ An HMAC object has the following methods:
\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 @@ An HMAC object has the following methods:
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}
......@@ -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}
......
......@@ -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
......
......@@ -247,6 +247,15 @@ archive into the current working directory. It's also possible to set
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}
......
# $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')
......@@ -28,27 +28,33 @@ class HMAC:
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 @@ class HMAC:
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()
......
# $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
# $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
......@@ -1090,6 +1090,9 @@ class _ExpectedSkips:
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')
......
# 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()
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]')
......@@ -105,9 +105,10 @@ class SanityTestCase(unittest.TestCase):
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 @@ class CopyTestCase(unittest.TestCase):
# 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),
......
This diff is collapsed.
......@@ -10,6 +10,7 @@
/* MD5 objects */
#include "Python.h"
#include "structmember.h"
#include "md5.h"
typedef struct {
......@@ -150,15 +151,46 @@ static PyMethodDef md5_methods[] = {
};
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 PyInt_FromLong(64);
}
static PyObject *
md5_get_digest_size(PyObject *self, void *closure)
{
return PyInt_FromLong(16);
}
return Py_FindMethod(md5_methods, (PyObject *)self, name);
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 @@ copy() -- return a copy of the current md5 object");
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 @@ static PyTypeObject MD5type = {
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 @@ is made.");
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 @@ static PyMethodDef md5_functions[] = {
/* 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);
......
This diff is collapsed.
This diff is collapsed.
......@@ -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 PyMethodDef SHA_methods[] = {
};
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 PyInt_FromLong(SHA_BLOCKSIZE);
}
return Py_FindMethod(SHA_methods, self, name);
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 @@ SHA_new(PyObject *self, PyObject *args, PyObject *kwdict)
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 @@ static struct PyMethodDef SHA_functions[] = {
#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
......
......@@ -400,15 +400,6 @@ class PyBuildExt(build_ext):
# 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 @@ class PyBuildExt(build_ext):
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment