177 lines
6.2 KiB
Python
177 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# ===================================================================
|
|
# The contents of this file are dedicated to the public domain. To
|
|
# the extent that dedication to the public domain is not available,
|
|
# everyone is granted a worldwide, perpetual, royalty-free,
|
|
# non-exclusive license to exercise all rights associated with the
|
|
# contents of this file for any purpose whatsoever.
|
|
# No rights are reserved.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
# ===================================================================
|
|
|
|
"""Hashing algorithms
|
|
|
|
Hash functions take arbitrary binary strings as input, and produce a random-like output
|
|
of fixed size that is dependent on the input; it should be practically infeasible
|
|
to derive the original input data given only the hash function's
|
|
output. In other words, the hash function is *one-way*.
|
|
|
|
It should also not be practically feasible to find a second piece of data
|
|
(a *second pre-image*) whose hash is the same as the original message
|
|
(*weak collision resistance*).
|
|
|
|
Finally, it should not be feasible to find two arbitrary messages with the
|
|
same hash (*strong collision resistance*).
|
|
|
|
The output of the hash function is called the *digest* of the input message.
|
|
In general, the security of a hash function is related to the length of the
|
|
digest. If the digest is *n* bits long, its security level is roughly comparable
|
|
to the the one offered by an *n/2* bit encryption algorithm.
|
|
|
|
Hash functions can be used simply as a integrity check, or, in
|
|
association with a public-key algorithm, can be used to implement
|
|
digital signatures.
|
|
|
|
The hashing modules here all support the interface described in `PEP
|
|
247`_ , "API for Cryptographic Hash Functions".
|
|
|
|
.. _`PEP 247` : http://www.python.org/dev/peps/pep-0247/
|
|
|
|
:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512
|
|
"""
|
|
|
|
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
|
|
'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC']
|
|
|
|
__revision__ = "$Id$"
|
|
|
|
import sys
|
|
if sys.version_info[0] == 2 and sys.version_info[1] == 1:
|
|
from Crypto.Util.py21compat import *
|
|
from Crypto.Util.py3compat import *
|
|
|
|
def new(algo, *args):
|
|
"""Initialize a new hash object.
|
|
|
|
The first argument to this function may be an algorithm name or another
|
|
hash object.
|
|
|
|
This function has significant overhead. It's recommended that you instead
|
|
import and use the individual hash modules directly.
|
|
"""
|
|
|
|
# Try just invoking algo.new()
|
|
# We do this first so that this is the fastest.
|
|
try:
|
|
new_func = algo.new
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
return new_func(*args)
|
|
|
|
# Try getting the algorithm name.
|
|
if isinstance(algo, str):
|
|
name = algo
|
|
else:
|
|
try:
|
|
name = algo.name
|
|
except AttributeError:
|
|
raise ValueError("unsupported hash type %r" % (algo,))
|
|
|
|
# Got the name. Let's see if we have a PyCrypto implementation.
|
|
try:
|
|
new_func = _new_funcs[name]
|
|
except KeyError:
|
|
# No PyCrypto implementation. Try hashlib.
|
|
try:
|
|
import hashlib
|
|
except ImportError:
|
|
# There is no hashlib.
|
|
raise ValueError("unsupported hash type %s" % (name,))
|
|
return hashlib.new(name, *args)
|
|
else:
|
|
# We have a PyCrypto implementation. Instantiate it.
|
|
return new_func(*args)
|
|
|
|
# This dict originally gets the following _*_new methods, but its members get
|
|
# replaced with the real new() methods of the various hash modules as they are
|
|
# used. We do it without locks to improve performance, which is safe in
|
|
# CPython because dict access is atomic in CPython. This might break PyPI.
|
|
_new_funcs = {}
|
|
|
|
def _md2_new(*args):
|
|
from Crypto.Hash import MD2
|
|
_new_funcs['MD2'] = _new_funcs['md2'] = MD2.new
|
|
return MD2.new(*args)
|
|
_new_funcs['MD2'] = _new_funcs['md2'] = _md2_new
|
|
del _md2_new
|
|
|
|
def _md4_new(*args):
|
|
from Crypto.Hash import MD4
|
|
_new_funcs['MD4'] = _new_funcs['md4'] = MD4.new
|
|
return MD4.new(*args)
|
|
_new_funcs['MD4'] = _new_funcs['md4'] = _md4_new
|
|
del _md4_new
|
|
|
|
def _md5_new(*args):
|
|
from Crypto.Hash import MD5
|
|
_new_funcs['MD5'] = _new_funcs['md5'] = MD5.new
|
|
return MD5.new(*args)
|
|
_new_funcs['MD5'] = _new_funcs['md5'] = _md5_new
|
|
del _md5_new
|
|
|
|
def _ripemd160_new(*args):
|
|
from Crypto.Hash import RIPEMD160
|
|
_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
|
|
_new_funcs['RIPEMD'] = _new_funcs['ripemd'] = RIPEMD160.new
|
|
return RIPEMD160.new(*args)
|
|
_new_funcs['RIPEMD160'] = _new_funcs['ripemd160'] = \
|
|
_new_funcs['RIPEMD'] = _new_funcs['ripemd'] = _ripemd160_new
|
|
del _ripemd160_new
|
|
|
|
def _sha1_new(*args):
|
|
from Crypto.Hash import SHA1
|
|
_new_funcs['SHA1'] = _new_funcs['sha1'] = \
|
|
_new_funcs['SHA'] = _new_funcs['sha'] = SHA1.new
|
|
return SHA1.new(*args)
|
|
_new_funcs['SHA1'] = _new_funcs['sha1'] = \
|
|
_new_funcs['SHA'] = _new_funcs['sha'] = _sha1_new
|
|
del _sha1_new
|
|
|
|
def _sha224_new(*args):
|
|
from Crypto.Hash import SHA224
|
|
_new_funcs['SHA224'] = _new_funcs['sha224'] = SHA224.new
|
|
return SHA224.new(*args)
|
|
_new_funcs['SHA224'] = _new_funcs['sha224'] = _sha224_new
|
|
del _sha224_new
|
|
|
|
def _sha256_new(*args):
|
|
from Crypto.Hash import SHA256
|
|
_new_funcs['SHA256'] = _new_funcs['sha256'] = SHA256.new
|
|
return SHA256.new(*args)
|
|
_new_funcs['SHA256'] = _new_funcs['sha256'] = _sha256_new
|
|
del _sha256_new
|
|
|
|
def _sha384_new(*args):
|
|
from Crypto.Hash import SHA384
|
|
_new_funcs['SHA384'] = _new_funcs['sha384'] = SHA384.new
|
|
return SHA384.new(*args)
|
|
_new_funcs['SHA384'] = _new_funcs['sha384'] = _sha384_new
|
|
del _sha384_new
|
|
|
|
def _sha512_new(*args):
|
|
from Crypto.Hash import SHA512
|
|
_new_funcs['SHA512'] = _new_funcs['sha512'] = SHA512.new
|
|
return SHA512.new(*args)
|
|
_new_funcs['SHA512'] = _new_funcs['sha512'] = _sha512_new
|
|
del _sha512_new
|