Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f21a5f7

Browse files
committed
[ 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.
1 parent 33a5f2a commit f21a5f7

21 files changed

Lines changed: 2587 additions & 51 deletions

Doc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ Joakim Sernbrant
164164
Justin Sheehy
165165
Michael Simcich
166166
Ionel Simionescu
167+
Gregory P. Smith
167168
Roy Smith
168169
Clay Spence
169170
Nicholas Spies

Doc/Makefile.deps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ LIBFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
202202
lib/librgbimg.tex \
203203
lib/libossaudiodev.tex \
204204
lib/libcrypto.tex \
205+
lib/libhashlib.tex \
205206
lib/libmd5.tex \
206207
lib/libsha.tex \
207208
lib/libhmac.tex \

Doc/lib/lib.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ \chapter*{Front Matter\label{front}}
303303

304304
\input{libcrypto} % Cryptographic Services
305305
\input{libhmac}
306+
\input{libhashlib}
306307
\input{libmd5}
307308
\input{libsha}
308309

Doc/lib/libhmac.tex

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ \section{\module{hmac} ---
1414
\begin{funcdesc}{new}{key\optional{, msg\optional{, digestmod}}}
1515
Return a new hmac object. If \var{msg} is present, the method call
1616
\code{update(\var{msg})} is made. \var{digestmod} is the digest
17-
module for the HMAC object to use. It defaults to the
18-
\refmodule{md5} module.
17+
constructor or module for the HMAC object to use. It defaults to
18+
the \code{\refmodule{hashlib}.md5} constructor. \note{The md5 hash
19+
has known weaknesses but remains the default for backwards compatibility.
20+
Choose a better one for your application.}
1921
\end{funcdesc}
2022

2123
An HMAC object has the following methods:
@@ -29,14 +31,14 @@ \section{\module{hmac} ---
2931

3032
\begin{methoddesc}[hmac]{digest}{}
3133
Return the digest of the strings passed to the \method{update()}
32-
method so far. This is a 16-byte string (for \refmodule{md5}) or a
33-
20-byte string (for \refmodule{sha}) which may contain non-\ASCII{}
34-
characters, including NUL bytes.
34+
method so far. This string will be the same length as the
35+
\var{digest_size} of the digest given to the constructor. It
36+
may contain non-\ASCII{} characters, including NUL bytes.
3537
\end{methoddesc}
3638

3739
\begin{methoddesc}[hmac]{hexdigest}{}
38-
Like \method{digest()} except the digest is returned as a string of
39-
length 32 for \refmodule{md5} (40 for \refmodule{sha}), containing
40+
Like \method{digest()} except the digest is returned as a string
41+
twice the length containing
4042
only hexadecimal digits. This may be used to exchange the value
4143
safely in email or other non-binary environments.
4244
\end{methoddesc}
@@ -46,3 +48,7 @@ \section{\module{hmac} ---
4648
efficiently compute the digests of strings that share a common
4749
initial substring.
4850
\end{methoddesc}
51+
52+
\begin{seealso}
53+
\seemodule{hashlib}{The python module providing secure hash functions.}
54+
\end{seealso}

Doc/lib/libmd5.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ \section{\module{md5} ---
44
\declaremodule{builtin}{md5}
55
\modulesynopsis{RSA's MD5 message digest algorithm.}
66

7+
\deprecated{2.5}{Use the \refmodule{hashlib} module instead.}
78

89
This module implements the interface to RSA's MD5 message digest
910
\index{message digest, MD5}

Doc/lib/libsha.tex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ \section{\module{sha} ---
55
\modulesynopsis{NIST's secure hash algorithm, SHA.}
66
\sectionauthor{Fred L. Drake, Jr.}{[email protected]}
77

8+
\deprecated{2.5}{Use the \refmodule{hashlib} module instead.}
9+
810

911
This module implements the interface to NIST's\index{NIST} secure hash
1012
algorithm,\index{Secure Hash Algorithm} known as SHA-1. SHA-1 is an

Doc/whatsnew/whatsnew25.tex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,15 @@ \section{New, Improved, and Deprecated Modules}
247247
a different directory as the extraction target, and to unpack only a
248248
subset of the archive's members. (Contributed by Lars Gust\"abel.)
249249

250+
\item A new \module{hashlib} module has been added to replace the
251+
\module{md5} and \module{sha} modules and adds support for additional
252+
secure hashes such as SHA-256 and SHA-512. The \module{hashlib} module
253+
uses OpenSSL for fast platform optimized implementations of algorithms
254+
when available. The old \module{md5} and \module{sha} modules still
255+
exist as wrappers around hashlib to preserve backwards compatibility.
256+
257+
(Contributed by Gregory P. Smith.)
258+
250259
\end{itemize}
251260

252261

Lib/hashlib.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# $Id$
2+
#
3+
# Copyright (C) 2005 Gregory P. Smith ([email protected])
4+
# Licensed to PSF under a Contributor Agreement.
5+
#
6+
7+
__doc__ = """hashlib module - A common interface to many hash functions.
8+
9+
new(name, string='') - returns a new hash object implementing the
10+
given hash function; initializing the hash
11+
using the given string data.
12+
13+
Named constructor functions are also available, these are much faster
14+
than using new():
15+
16+
md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
17+
18+
More algorithms may be available on your platform but the above are
19+
guaranteed to exist.
20+
21+
Choose your hash function wisely. Some have known weaknesses.
22+
sha384 and sha512 will be slow on 32 bit platforms.
23+
"""
24+
25+
26+
def __get_builtin_constructor(name):
27+
if name in ('SHA1', 'sha1'):
28+
import _sha
29+
return _sha.new
30+
elif name in ('MD5', 'md5'):
31+
import _md5
32+
return _md5.new
33+
elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
34+
import _sha256
35+
bs = name[3:]
36+
if bs == '256':
37+
return _sha256.sha256
38+
elif bs == '224':
39+
return _sha256.sha224
40+
elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
41+
import _sha512
42+
bs = name[3:]
43+
if bs == '512':
44+
return _sha512.sha512
45+
elif bs == '384':
46+
return _sha512.sha384
47+
48+
raise ValueError, "unsupported hash type"
49+
50+
51+
def __py_new(name, string=''):
52+
"""new(name, string='') - Return a new hashing object using the named algorithm;
53+
optionally initialized with a string.
54+
"""
55+
return __get_builtin_constructor(name)(string)
56+
57+
58+
def __hash_new(name, string=''):
59+
"""new(name, string='') - Return a new hashing object using the named algorithm;
60+
optionally initialized with a string.
61+
"""
62+
try:
63+
return _hashlib.new(name, string)
64+
except ValueError:
65+
# If the _hashlib module (OpenSSL) doesn't support the named
66+
# hash, try using our builtin implementations.
67+
# This allows for SHA224/256 and SHA384/512 support even though
68+
# the OpenSSL library prior to 0.9.8 doesn't provide them.
69+
return __get_builtin_constructor(name)(string)
70+
71+
72+
try:
73+
import _hashlib
74+
# use the wrapper of the C implementation
75+
new = __hash_new
76+
77+
for opensslFuncName in filter(lambda n: n.startswith('openssl_'), dir(_hashlib)):
78+
funcName = opensslFuncName[len('openssl_'):]
79+
try:
80+
# try them all, some may not work due to the OpenSSL
81+
# version not supporting that algorithm.
82+
f = getattr(_hashlib, opensslFuncName)
83+
f()
84+
# Use the C function directly (very fast)
85+
exec funcName + ' = f'
86+
except ValueError:
87+
try:
88+
# Use the builtin implementation directly (fast)
89+
exec funcName + ' = __get_builtin_constructor(funcName)'
90+
except ValueError:
91+
# this one has no builtin implementation, don't define it
92+
pass
93+
# clean up our locals
94+
del f
95+
del opensslFuncName
96+
del funcName
97+
98+
except ImportError:
99+
# We don't have the _hashlib OpenSSL module?
100+
# use the built in legacy interfaces via a wrapper function
101+
new = __py_new
102+
103+
# lookup the C function to use directly for the named constructors
104+
md5 = __get_builtin_constructor('md5')
105+
sha1 = __get_builtin_constructor('sha1')
106+
sha224 = __get_builtin_constructor('sha224')
107+
sha256 = __get_builtin_constructor('sha256')
108+
sha384 = __get_builtin_constructor('sha384')
109+
sha512 = __get_builtin_constructor('sha512')
110+

Lib/hmac.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,33 @@ def __init__(self, key, msg = None, digestmod = None):
2828
2929
key: key for the keyed hash object.
3030
msg: Initial input for the hash, if provided.
31-
digestmod: A module supporting PEP 247. Defaults to the md5 module.
31+
digestmod: A module supporting PEP 247. *OR*
32+
A hashlib constructor returning a new hash object.
33+
Defaults to hashlib.md5.
3234
"""
3335

3436
if key is _secret_backdoor_key: # cheap
3537
return
3638

3739
if digestmod is None:
38-
import md5
39-
digestmod = md5
40+
import hashlib
41+
digestmod = hashlib.md5
4042

41-
self.digestmod = digestmod
42-
self.outer = digestmod.new()
43-
self.inner = digestmod.new()
44-
self.digest_size = digestmod.digest_size
43+
if callable(digestmod):
44+
self.digest_cons = digestmod
45+
else:
46+
self.digest_cons = lambda d='': digestmod.new(d)
47+
48+
self.outer = self.digest_cons()
49+
self.inner = self.digest_cons()
50+
self.digest_size = self.inner.digest_size
4551

4652
blocksize = 64
4753
ipad = "\x36" * blocksize
4854
opad = "\x5C" * blocksize
4955

5056
if len(key) > blocksize:
51-
key = digestmod.new(key).digest()
57+
key = self.digest_cons(key).digest()
5258

5359
key = key + chr(0) * (blocksize - len(key))
5460
self.outer.update(_strxor(key, opad))
@@ -70,7 +76,7 @@ def copy(self):
7076
An update to this copy won't affect the original object.
7177
"""
7278
other = HMAC(_secret_backdoor_key)
73-
other.digestmod = self.digestmod
79+
other.digest_cons = self.digest_cons
7480
other.digest_size = self.digest_size
7581
other.inner = self.inner.copy()
7682
other.outer = self.outer.copy()

Lib/md5.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# $Id$
2+
#
3+
# Copyright (C) 2005 Gregory P. Smith ([email protected])
4+
# Licensed to PSF under a Contributor Agreement.
5+
6+
from hashlib import md5
7+
new = md5
8+
9+
blocksize = 1 # legacy value (wrong in any useful sense)
10+
digest_size = 16

0 commit comments

Comments
 (0)