#include #include #include /* Konstanten fuer scramle */ #define USE_F 1 #define USE_G 2 #define USE_H 3 #define USE_I 4 /* Globale Variable: Hier befindet sich nach dem Aufruf von * getchunk der naechste Teil der Nachricht. */ unsigned int chunk[16]; /* getchunk liest die naechsten 64 Byte ein und deponiert sie * in der globalen Variable chunk. * Wenn nicht mehr genuegend Bytes gelesen werden koennen um ein * Haeppchen von 64 Byte ganz zu fuellen "erfindet" die Prozedur nach * einem festen Schema weitere bytes (padding). * Der Rueckgabewert ist 1, wenn noch ein weiterer Block eingelesen * werden konnte und 0, wenn das Dateiende erreicht wurde. */ int getchunk () { static unsigned int len = 0; static unsigned int len2 = 0; static unsigned int pad = 0; static int eof = 0; unsigned char c; int index, shift, i; if (eof && (pad >= 9*8) && ((len+pad) % 512 == 0)) { return 0; } for (i=0; i<16; ++i) { chunk[i] = 0; } for (i=0; i<64; ++i) { if (eof) { c = 0; pad += 8; } else { if (1 == scanf ("%c", &c)) { len += 8; if (len == 0) { len2++; } } else { eof = 1; c = 0x80; pad += 8; } } index = i/4; shift = 8 * (i % 4); chunk[index] |= (unsigned int)c << shift; } if ((pad >= 9*8) && ((pad + len) % 512 == 0)) { chunk[14] = len; chunk[15] = len2; } return 1; } /* Konstante fuer scramble berechnen. Diese Funktion muss GENAU einmal * bei jedem Aufruf von scramble aufgerufen werden. */ unsigned int getconst () { static int calls = 0; unsigned int ret; double tmp; calls++; tmp = 256.0 * 256.0 * 256.0 * 256.0; tmp *= fabs (sin (calls)); tmp = floor (tmp); ret = tmp; calls %= 64; return ret; } /* Shift fuer scramble berechnen. Diese Funktion muss GENAU einmal * bei jedem Aufruf von scramble aufgerufen werden. */ unsigned int getshift () { static int calls = 0; unsigned int ret; static unsigned int shiftconsts[4][4] = { {7, 12, 17, 22}, {5, 9, 14, 20}, {4, 11, 16, 23}, {6, 10, 15, 21} }; ret = shiftconsts[calls/16][calls%4]; calls++; calls %= 64; return ret; } /* Bitweises: WENN x DANN y SONST z END */ unsigned int F (unsigned int x, unsigned int y, unsigned int z) { return (x&y) | ((~x) & z); } /* Bitweise: WENN x DANN x SONST y END */ unsigned int G (unsigned int x, unsigned int y, unsigned int z) { return (x&z) | (y&~z); } /* Bitweise: (X + Y + Z) MODULO 2 */ unsigned int H (unsigned int x, unsigned int y, unsigned int z) { return x ^ y ^ z; } unsigned int I (unsigned int x, unsigned int y, unsigned int z) { return y ^ (x | ~z); } /* Die Bits in x sollen nach links rotiert werde und zwar um * bybits positionen. */ unsigned int rotl (unsigned int x, unsigned int bybits) { assert (bybits <= 32); return (x << bybits) | (x >> (32-bybits)); } /* Bits kraeftig durchschuetteln */ unsigned int scramble (unsigned int o, unsigned int p, unsigned int q, unsigned int r, int func, int chunkidx) { unsigned int ret = 0; unsigned int constant; unsigned int shift; assert (chunkidx < 16); constant = getconst (); shift = getshift (); switch (func) { case USE_F: ret = F(p,q,r); break; case USE_G: ret = G(p,q,r); break; case USE_H: ret = H(p,q,r); break; case USE_I: ret = I(p,q,r); break; default: assert (0); } ret += o; ret += chunk[chunkidx]; ret += constant; ret = rotl (ret, shift); ret += p; return ret; } unsigned int swapbytes (unsigned int x) { return ((x&0xff000000) >> 24) | ((x&0x00ff0000) >> 8) | ((x&0x0000ff00) << 8) | ((x&0x000000ff) << 24); } int main () { unsigned int A, B, C, D; unsigned int AA, BB, CC, DD; int chunkidx, i; A = 0x67452301; B = 0xefcdab89; C = 0x98badcfe; D = 0x10325476; while (getchunk ()) { AA = A; BB = B; CC = C; DD = D; /* Round 1 */ chunkidx = 0; for (i=0; i<4; ++i) { A = scramble (A, B, C, D, USE_F, chunkidx); chunkidx++; D = scramble (D, A, B, C, USE_F, chunkidx); chunkidx++; C = scramble (C, D, A, B, USE_F, chunkidx); chunkidx++; B = scramble (B, C, D, A, USE_F, chunkidx); chunkidx++; } /* Round 2 */ chunkidx = 1; for (i=0; i<4; ++i) { A = scramble (A, B, C, D, USE_G, chunkidx); chunkidx = (chunkidx + 5) % 16; D = scramble (D, A, B, C, USE_G, chunkidx); chunkidx = (chunkidx + 5) % 16; C = scramble (C, D, A, B, USE_G, chunkidx); chunkidx = (chunkidx + 5) % 16; B = scramble (B, C, D, A, USE_G, chunkidx); chunkidx = (chunkidx + 5) % 16; } /* Round 3 */ chunkidx = 5; for (i=0; i<4; ++i) { A = scramble (A, B, C, D, USE_H, chunkidx); chunkidx = (chunkidx + 3) % 16; D = scramble (D, A, B, C, USE_H, chunkidx); chunkidx = (chunkidx + 3) % 16; C = scramble (C, D, A, B, USE_H, chunkidx); chunkidx = (chunkidx + 3) % 16; B = scramble (B, C, D, A, USE_H, chunkidx); chunkidx = (chunkidx + 3) % 16; } /* Round 4 */ chunkidx = 0; for (i=0; i<4; ++i) { A = scramble (A, B, C, D, USE_I, chunkidx); chunkidx = (chunkidx + 7) % 16; D = scramble (D, A, B, C, USE_I, chunkidx); chunkidx = (chunkidx + 7) % 16; C = scramble (C, D, A, B, USE_I, chunkidx); chunkidx = (chunkidx + 7) % 16; B = scramble (B, C, D, A, USE_I, chunkidx); chunkidx = (chunkidx + 7) % 16; } A += AA; B += BB; C += CC; D += DD; } A = swapbytes (A); B = swapbytes (B); C = swapbytes (C); D = swapbytes (D); printf ("%08X%08X%08X%08X\n", A, B, C, D); return 0; }