#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) { /* Hier fehlt noch was */ } /* Bitweise: WENN z DANN x SONST y END */ unsigned int G (unsigned int x, unsigned int y, unsigned int z) { /* Hier fehlt noch was */ } /* Bitweise: (X + Y + Z) MODULO 2 */ unsigned int H (unsigned int x, unsigned int y, unsigned int z) { /* Hier fehlt noch was */ } /* Bitoperation zu folgender Tabelle: * x y z Ergebnis * 0 0 0 1 * 0 0 1 0 * 1 0 0 1 * 1 0 1 1 * 0 1 0 0 * 0 1 1 1 * 1 1 0 0 * 1 1 1 0 */ unsigned int I (unsigned int x, unsigned int y, unsigned int z) { /* Hier fehlt noch was */ } /* Die Bits in x sollen nach links rotiert werde und zwar um * bybits positionen. */ unsigned int rotl (unsigned int x, unsigned int bybits) { /* Hier fehlt noch was */ } /* Bits kraeftig durchschuetteln: * - Als erstes wird die durch den Parameter func spezifizierte * Funktion mit den Parametern p, q und r aufgerufen: F falls * func == USE_F, G falls func == USE_G usw. * - Zu diesem Ergebnis wird der Parameter o, die Konstante constant * und chunk[chunkidx] addiert. Der Parameter chunkidx gibt also an, welcher * Wert aus der gelesenen Nachricht in diesem Aufruf mit verarbeitet * wird. * - Anschliessend werden die Bits im Ergebnis um shift Positionen * nach links rotiert. * - Der Rueckgabewert ist die Summe aus dem Ergebnis des letzten Schritts * und dem Parameter p. */ unsigned int scramble (unsigned int o, unsigned int p, unsigned int q, unsigned int r, int func, unsigned int chunkidx) { unsigned int constant; unsigned int shift; constant = getconst (); shift = getshift (); /* Hier fehlt noch was */ } /* Kehrt die Reihenfolge der bytes in x um, d.h * das erste Byte wird mit dem vierten und das zweite mit dem dritten * vertauscht. */ unsigned int swapbytes (unsigned int x) { /* Hier fehlt noch was */ } /* Nach der Initialisierung der vier Variablen A, B, C und D * wird solange mit getchunk ein Block eingelesen und verarbeitet, * bis getchunk den Wert 0 zurueckliefert. * Mit jedem Block werden folgende Operationen durchgefuehrt: * 1. die alten Werte von A, B, C, und D werde gesichert. * 2. es wird 64 Mal die Funktion scramble aufgerufen und * zwar mit folgenden Parametern: * + Die ersten vier Parameter sind die Variablen A, B, C und D * allerdings werden diese bei jedem weiteren Aufruf um eins * nach rechts rotiert. Der zweite Aufruf hat also die ersten * vier Parameter D, A, B und C; der dritte C, D, A und B usw. * + Die Bestimmung des fuenften und sechsten Parameter aendert * sich nach je 16 Aufrufen gemaess folgender Tabelle: * Aufruf 4. Parameter 5. Parameter * 1-16 USE_F i-1 * 17-32 USE_G (1+5*(i-17)) MODULO 16 * 33-48 USE_H (5+3*(i-33)) MODULO 16 * 49-64 USE_I ( 7*(i-49)) MODULO 16 * Dabei ist i die Nummer des Aufruf (beginnend bei 1) * aus der ersten Spalte. * + Der Rueckgabewert wird sofort nach jedem Aufruf an die * Variable zugewiesen, die als der erste Parameter uebergeben * wurde. * 3. Zuletzt werden die in 1. gesicherten Werte von A, B, C und D * noch zu den jeweils aktuellen hinzu addiert * (A = A + gesicherte Wert von A, B = B + gesicherter Wert von B, usw.) * Nachdem alle Bloecke verarbeitet wurden, wird die Reihenfolge der * Bytes in A, B, C und D vertauscht (swapbytes!). Schliesslich * werden A, B, C und D in hexadezimal Schreibweise (16er System, Formatierung * bei printf mit %x oder %X ausgegeben. */ int main () { unsigned int A, B, C, D; /* Hier ev. zusaetzliche Variablendeklarationen einfuegen */ /* Initialisierung */ A = 0x67452301; B = 0xefcdab89; C = 0x98badcfe; D = 0x10325476; /* Hier fehlt noch was */ return 0; }