# 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(abm)  # 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(keymessage):
    '''
    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'

~'''