# Turning a small stream cipher (ARC4) into a hash function (ARCH)!

\$ python hash.py b b
('fd5f1b4640e0f5cdda0368b67601b9077cbe4a4931a94b52fdf46bf1be0c2bf5', '3a4627878dca5c4daeb243a661b56ebbaa03c268f659b6001cd84911051c103b', 'bb', 2)

\$ python hash.py b c

\$ python hash.py c b
('2f4802585ed79a61d25c92a3d7af8fa2a16e2e269e9c6fbd21891e6a7bae15ec', '6a25a3b18a93d966d7c878f9263f053d653618782a9f7918db05b06e0fa27787', 'cb', 2)

\$ python hash.py c c
('6683682f501fdaa1c4a95e1ec6b7fb5ff49206af34e1729a17ded27fda355ea4', '7f12dc4dd32e3c9b31d03382b9c9af1efc0ea3ba620ba8e27fa9b9d8ebc1a88b', 'cc', 2)
import os,sys

def swap(s, a, b):
t = s[a] ; s[a] = s[b] ; s[b] = t
return s

def init(mesg, leng):
j = 0 ; skey = []
for i in range(0, 256):
skey.append(i)
for i in range(0, 256+leng):
k = (i % 256) ; m = (i % leng)
l = (((i + 1 + ord(mesg[m])) * leng) % 256)
j = ((j + skey[k] + skey[l]) % 256)
swap(skey, k, j)
return skey

def arch(skey):
i = 0 ; j = 0
l = 0 ; rnds = 4 ; outp = ""
for z in range(0, 256*rnds):
i = ((i + 1) % 256)
j = ((j + skey[i]) % 256)
swap(skey, i, j)
for z in range(0, 32):
i = ((i + 1) % 256)
j = ((j + skey[i]) % 256)
swap(skey, i, j)
k = ((skey[i] + skey[j] + skey[l]) % 256)
outp += chr(skey[k])
l = (l ^ ord(outp[z]))
return outp

def hmac(mesg, mlen, skey, klen):
block_size = 64 ; ikey = "" ; okey = ""
tkey = skey ; tlen = klen
if (klen > block_size):
zkey = init(skey, klen)
tkey = arch(zkey)
tlen = len(tkey)
for x in range(0, block_size):
c = 0
if (x < tlen):
c = ord(tkey[x])
zkey = init(ikey+mesg, block_size+mlen)
ihsh = arch(zkey)
ilen = len(ihsh)
zkey = init(okey+ihsh, block_size+ilen)
ohsh = arch(zkey)
return ohsh

def stoh(inpt):
o = ""
for c in inpt:
s = hex(ord(c))[2:]
if len(s) != 2:
s = "0" + s
o += s
return o

m = sys.argv[1] ; l = len(m)
k = sys.argv[2] ; n = len(k)
z = init(m+k, l+n)
print(stoh(hmac(m, l, k, n)), stoh(arch(z)), m+k, l+n)