Vorherige Seite Nächste Seite Inhalt

10. Beispiel für eine einfache Hashfunktion

Dies ist ein kleines Beispiel-Programm für eine einfache Hashfunktion, die sich prinzipiell an den SHA-Algorithmus anlehnt. Es wurde nicht auf die absolute Sicherheit, die eine Hashfunktion bieten sollte geachtet, sondern auf möglichst einfache, verständliche Implementierung.

10.1 Quellcode

/* Datei: Hash.c
 * Programmierer: Jochen Baur, Florian Bühr, Christoph Gärtner
 * Datum: Irgendwann im Dezember 97
 * gedacht für ANSI-C-Compiler */

#include<stdio.h>

#include<string.h>

/* Initialisierung der Struktur von fünf 32-bit-Variablen */

typedef struct abcde {unsigned long a,b,c,d,e;} hilfevar;



/* Definition der vier SHA-Konstanten */

#define K1              0x5a827999L

#define K2              0x6ed9eba1L

#define K3              0x8f1bbcdcL

#define K4              0xca62c1d6L



/* Eine Operation von SHA, die pro Runde 20mal ausgeführt werden
soll */

void operation (hilfevar *in,unsigned char fktnr,unsigned long w )

{ unsigned long temp;

/* Auswahl einer der vier nichtlinearen Funktionen abhängig von
der Runde*/

switch(fktnr)

{

case 0: {
temp = in->e+((in->b & in->c)|(~in->b & in->d))+((in->a<<5)|(in->a<<27))+w+K1;
 

         break;}  

case 1: {
temp = in->e+(in->b^in->c^in->d)+((in->a<<5)|(in->a<<27))+w+K2;
 

         break;}  

case 2: {
temp = in->e+((in->b & in->c)|(in->b & in->d)|(in->c & in->d))+((in->a<<5)|(in->a<<27))+w+K3;
 

         break;}  

case 3: {
temp = in->e+(in->b^in->c^in->d)+((in->a<<5)|(in->a<<27))+w+K4;
 

         break;}  

}

/* Kopieren der durch die Funktionen veränderten Variablen

in->e = in->d;

in->d = in->c;

in->c = ((in->b<<30)|(in->b<<2));

in->b = in->a;

in->a = temp;  

}



/* Eine Runde von SHA, die viermal ausgeführt werden soll */

void runde (hilfevar *G,unsigned long *wert)

{ unsigned char opcounter;  

hilfevar h; /* Initialisierung der Hilfsvariablen */

h.a = G->a; /* mit den Werten der Verkettungsvariablen */

h.b = G->b;

h.c = G->c;

h.d = G->d;

h.e = G->e;



/* Schleife, die 20mal eine SHA-Operation aufruft */

for(opcounter = 0;opcounter<20;opcounter++)

{ operation(& h,opcounter%4,wert[opcounter]); }

G->a+ = h.a; /* Die in der Runde veränderten Hilfsvariablen */

G->b+ = h.b; /* werden zu den Verkettungsvariablen addiert */

G->c+ = h.c;

G->d+ = h.d;

G->e+ = h.e;  

}



/* Hauptprogramm, das File zum hashen einliest und Runden viermal
aufruft */

void main (int arg,unsigned char *filename[])

{  

FILE *in;

hilfevar H,erg;

unsigned char ch[4];

unsigned char i,j,k,n,p;

long test;

unsigned long W[20];

/* Initialisierung der Verkettungsvariablen mit den Anfangswerten */

erg.a = H.a  =  0x67452301L;

erg.b = H.b  =  0xefcdab89L;

erg.c = H.c  =  0x98badcfeL;

erg.d = H.d  =  0x10325476L;

erg.e = H.e  =  0xc3d2e1f0L;  

  

printf("\n\nHashfunktion Copyright by Baur, Buehr, Gaertner,
Herbert A.D.1997\n\n");

/* Fehlerbehandlung, falls angegebene Datei nicht vorhanden */

if ((in = fopen(filename[1], "r")) == NULL)

{

fprintf(stderr, "Konnte Datei nicht oeffnen.\n");

}

/* Setze Datei-Zeiger auf Dateiende und lese Dateilänge ein */

fseek(in,0,SEEK_END);

test = ftell(in);

/* Setze Datei-Zeiger auf Anfang */

fseek(in,0x0,SEEK_SET);

/* Schleife zum Einlesen der 32-bit-Teilblöcke (Message
Digests) */

for(j = 0;j<(long)(test/64);j++)

{ /* Schreibe in jedes Byte, das Datei länger ist als Vielfaches
von 512 bit eine '0' ...

wichtigster Unterschied zum Secure Hash Standard/Algorithm */

for (i = 0;i<16;i++)

{  

W[i] = 0;

for (n = 0; n < 4; n++)

{

ch[n] = fgetc(in);

/* Lese Byte und schreibe in W-Feld */

if(feof(in)) W[i] = 0; else

W[i] = (W[i] << 8) | ch[n];

/* wenn Ende der Datei, schreibe '0', andernfalls

rotiere um nächstes Byte anzuhängen */

}

/* Kopiere die letzten vier Teilblöcke in die ersten vier

W[16] = W[1]; W[17] = W[2];
W[18] = W[3]; W[19] = W[4]; 


}

/* Aufruf der SHA-Runden und Schreiben der Ausgabe der Runde in
endgültigen Verkettungsvariablen */

runde(& H,W);
erg.a = H.a+ = erg.a;
erg.b = H.b+ = erg.b;
erg.c = H.c+ = erg.c;
erg.d = H.d+ = erg.d;
erg.e = H.e+ = erg.e;

runde(& H,W);
erg.a = H.a+ = erg.a;
erg.b = H.b+ = erg.b;
erg.c = H.c+ = erg.c;
erg.d = H.d+ = erg.d;
erg.e = H.e+ = erg.e;

runde(& H,W);
erg.a = H.a+ = erg.a;
erg.b = H.b+ = erg.b;
erg.c = H.c+ = erg.c;
erg.d = H.d+ = erg.d;
erg.e = H.e+ = erg.e;

runde(& H,W);
erg.a = H.a+ = erg.a;
erg.b = H.b+ = erg.b;
erg.c = H.c+ = erg.c;
erg.d = H.d+ = erg.d;
erg.e = H.e+ = erg.e;

if(feof(in)) break; /* Schleifenabbruch, falls Dateiende */

}

/* Ausgabe auf 'stdout' des Hashwerts von 160 bit durch Aneinderreihen
der Verkettungsvariablen */

printf("Hashwert auf
stdout:\t%lx%lx%lx%lx%lx\n",erg.a,erg.b,erg.c,erg.d,erg.e);

fclose(in); /* Schließe Datei, die gehasht wurde */ 


}

Programmaufruf und Ausgabe:

C:\>hash <dateiname> (unter DOS-Prompt)

Hashfunktion copyright by Baur, Buehr, Gaertner, Herbert A.D. 1997

Hashwert auf stdout: 40-stellige hexadezimale Zahl

Beispiel mit einer Datei test01.txt, die

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" enthält:

C:\>hash test01.txt



Hashfunktion ...

Hashwert auf stdout: 67452301efcdab8998badcfb10325476c3d2e1f0

Beispiel mit einer Datei test02.txt, die

"ABBDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 0123456789101112" enthält (die fettgedruckten Zeichen sind zu test01.txt verändert):

C:\>hash test02.txt



Hashfunktion ...

Hashwert auf stdout: b680d8edca71ccb01d7eef0cb62eff2c8a729110


Vorherige Seite Nächste Seite Inhalt