# hash.py David MacQuigg 27-Feb-2010
'''
Cryptographic Hash Functions
- Stinson, Chapter 4
Run this file in Python 2.6. Try the commands in the >>> examples.
~'''
### Random Bits
from random import getrandbits
a,b,m = getrandbits(512), getrandbits(512), getrandbits(384) # long integers
'''
>>> a
87638194511408989261438753250719754638828743912429765499507120091357674569882808
90862859998699808605307665820696568046132523175744106743803372585080828726L
>>> b
57579891920620594921553065324099857848201813159629630310669085501543819427295796
09887603084816533251318617299467986239404540879435342090928431485352784952L
>>> m
33980144669810108281160822352744739279623941703077092883034667556498921065193304
60680842427694402677672470050075321L
'''
### Huge exponentials like a ** b (mod m) are common in crypto systems.
exp = pow(a, b, m) # pow() is a function written in C - very fast.
'''
>>> pow(a, b, m)
26616164385017850397090293477494464399221960596510492575571803619978316656538353
42475518596170907523282061732994456L
'''
### Secure Hash
from Crypto.Hash import SHA # 160-bit hash function (SHA-1)
md = SHA.new() # a new message digest object
md.update('abcde') # stir in some text
md1 = md.hexdigest() # snapshot of the digest
md.update('f') # a little more text
md2 = md.hexdigest() # digest is completely changed
# diffusion of entropy is excellent
'''
>>> print md1, '\n', md2
03de6c570bfe24bfc328ccd7ca46b76eadaf4334
1f8ac10f23c5b5bc1167bda84b833e5c057a77d2
~'''
### Message Authentication Code
# HMAC - Stinson p.143
from random import getrandbits
ipad = eval('0x' + 64 * '36') # inner padding constant - 64 byte integer
opad = eval('0x' + 64 * '5c') # outer padding
key = getrandbits(512) # secret key - 512 bits
message = 'hello from Alice'
def HMAC(key, message):
'''
Return a 160-bit authentication code from the HMAC nested hash. Input is
a 512-bit integer key, and a message string with any number of bytes.
Output code is a hex string.
'''
Kin = hex(key ^ ipad) # convert ints to hex strings for SHA
Kout = hex(key ^ opad)
hash1 = SHA.new() # a new hashing object
hash1.update(Kin + message)
g = hash1.hexdigest() # result of inner hash - 160 bits
hash1.update(Kout + g) # 512 + 160 = 672 bits in
hmac = hash1.hexdigest() # 160 bits out
return hmac
'''
>>> HMAC(key, message)
'5476af9fce56b0ba487c6e411c48d73db6c0d1b5'
~'''