Some small hash loop tweaks and I increased the number of hash rounds from 3 to 4 also:
import os,sys def tt(ll): return (ll & 0xffffffff) def sdbm(inpt, leng): hshs = 0 for x in range(0, leng): hshs = tt(ord(inpt[x]) + tt(hshs << 6) + tt(hshs << 16) - hshs) return hshs def sdbm_hash(inpt, leng): mixs = [1, 6, 16, 13, 33, 27, 67, 55, 123] hshs = [0, 0, 0, 0, 0, 0, 0, 0, 0] more = 0 mlen = len(hshs) ; rnds = (4 * mlen) for x in range(0, mlen+leng): hshs[0] = tt(mixs[x%mlen] + ord(inpt[x%leng]) + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]) more = (more ^ (hshs[0] >> 16)) i = ((x % (mlen - 1)) + 1) less = ((hshs[i] & 0xffff0000) ^ ((hshs[i] & 0xffff) << 16)) hshs[i] = (less ^ more) for z in range(0, rnds): hshs[0] = tt(z + more + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]) more = (more ^ (hshs[mlen-1] >> 16)) for y in range(mlen-1, 0, -1): hshs[y] = tt((hshs[y] << 16) | (hshs[y-1] >> 16)) hshs[y-1] = (hshs[y-1] & 0xffff) o = "" for h in hshs[1:]: for x in range(3, -1, -1): o += chr((h >> (x * 8)) & 0xff) return o def sdbm_hmac(mesg, mlen, skey, klen): inner_pad = 0x36 ; outer_pad = 0x5C block_size = 64 ; ikey = "" ; okey = "" tkey = skey ; tlen = klen if (klen > block_size): tkey = sdbm_hash(skey, klen) tlen = len(tkey) for x in range(0, block_size): c = 0 if (x < tlen): c = ord(tkey[x]) ikey += chr(inner_pad ^ c) okey += chr(outer_pad ^ c) ihsh = sdbm_hash(ikey+mesg, block_size+mlen) ilen = len(ihsh) ohsh = sdbm_hash(okey+ihsh, block_size+ilen) return ohsh def stoh(s): return "".join([hex(ord(c))[2:].rjust(2, '0') for c in s]) m = sys.argv[1] ; l = len(m) k = sys.argv[2] ; n = len(k) #print(stoh(sdbm_hash(m, l)), sdbm(m, l), m, l) print(stoh(sdbm_hmac(m, l, k, n)), sdbm(m, l), m, l, sdbm(k, n), k, n)
$ for x in b c ; do for y in b c ; do python hash.py "$x" "$y" ; echo ; done ; done ('d805c892902cf6ea0c98d1946110a61334a9a1158b430fb7d1c5ba7afb29147d', 98, 'b', 1, 98, 'b', 1) ('6eb38871cc3679cb533f1daeee4ed87ab4f154f953e5ea96d508bda6bb054abd', 98, 'b', 1, 99, 'c', 1) ('0d034f1f7627492fd57bd92a63a8a4f2d977f02c2fdf29b4e49f4b3b21a9e738', 99, 'c', 1, 98, 'b', 1) ('09b2678c7ce46cd7cd112b4a2b6fd05d50c858fe0460d29264c4ea01595968db', 99, 'c', 1, 99, 'c', 1) $ ./hash "this is a test" "b" [6b18600ee98449472dd377755dd67cd436c9c143cfc893c9a2181e0567d16cf1] [1655286693] [this is a test] [14] [98] [b] [1] $ ./hash "this is a test" "c" [bd3bc1a983e35311e5ea60db5ae8cd28a821386937dfd480eccff95fab8356b9] [1655286693] [this is a test] [14] [99] [c] [1] $ ./hash "this is a tesu" "b" [8cddc8b9f5a1a1adf41c78b035bf59b444431e772b9c39824e2cf67e2837d9b0] [1655286694] [this is a tesu] [14] [98] [b] [1] $ ./hash "this is a tesu" "c" [2554d7d9ecb47d36b7f62d5e4432a7983490aca1229a91331c16b81567c4edff] [1655286694] [this is a tesu] [14] [99] [c] [1]
#include <stdio.h> #include <string.h> unsigned int sdbm(char *inpt, int leng) { unsigned int hshs = 0; for (int x = 0; x < leng; ++x) { hshs = (inpt[x] + (hshs << 6) + (hshs << 16) - hshs); } return hshs; } void sdbm_hash(unsigned char *outp, unsigned char *inpt, int leng) { unsigned int mixs[] = {1, 6, 16, 13, 33, 27, 67, 55, 123}; unsigned int hshs[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned int less, more = 0; int i, mlen = 9, rnds = (4 * mlen); for (int x = 0; x < (mlen+leng); ++x) { hshs[0] = (mixs[x%mlen] + inpt[x%leng] + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]); more = (more ^ (hshs[0] >> 16)); i = ((x % (mlen - 1)) + 1); less = ((hshs[i] & 0xffff0000) ^ ((hshs[i] & 0xffff) << 16)); hshs[i] = (less ^ more); } for (int z = 0; z < rnds; ++z) { hshs[0] = (z + more + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]); more = (more ^ (hshs[mlen-1] >> 16)); for (int y = mlen-1; y > 0; --y) { hshs[y] = ((hshs[y] << 16) | (hshs[y-1] >> 16)); hshs[y-1] = (hshs[y-1] & 0xffff); } } for (int x = 1, y = 0; x < mlen; ++x) { for (int z = 3; z > -1; --z, ++y) { outp[y] = ((hshs[x] >> (z * 8)) & 0xff); } } } void sdbm_hmac(unsigned char *outp, unsigned char *mesg, int mlen, unsigned char *skey, int klen) { int block_size = 64, hash_size = 32; unsigned char inner_pad = 0x36, outer_pad = 0x5C; unsigned char ikey[block_size], okey[block_size], ihsh[hash_size], thsh[hash_size]; unsigned char buff[block_size+mlen+hash_size]; unsigned char *tkey = skey; int tlen = klen; if (klen > block_size) { sdbm_hash(thsh, skey, klen); tkey = thsh; tlen = hash_size; } for (int x = 0; x < block_size; ++x) { unsigned char padc = 0; if (x < tlen) { padc = tkey[x]; } ikey[x] = (inner_pad ^ padc); okey[x] = (outer_pad ^ padc); } bcopy(ikey, buff, block_size); bcopy(mesg, buff+block_size, mlen); sdbm_hash(ihsh, buff, block_size+mlen); bcopy(okey, buff, block_size); bcopy(ihsh, buff+block_size, hash_size); sdbm_hash(outp, buff, block_size+hash_size); } void stoh(char *outp, unsigned char *inpt) { char *hexs = "0123456789abcdef"; for (int x = 0, y = 0; x < 32; ++x) { outp[y] = hexs[(inpt[x] >> 4) & 0xf]; ++y; outp[y] = hexs[inpt[x] & 0xf]; ++y; } } int main(int argc, char *argv[]) { char *m = argv[1]; int l = strlen(m); char *k = argv[2]; int n = strlen(k); unsigned char h[32]; char o[65]; bzero(o, 65); sdbm_hmac(h, (unsigned char *)m, l, (unsigned char *)k, n); stoh(o, h); printf("[%s] [%u] [%s] [%d] [%u] [%s] [%d]\n", o, sdbm(m, l), m, l, sdbm(k, n), k, n); return 0; }