Vorherige Seite Nächste Seite Inhalt

14. Anhang

Hier sind einige Implementierungen aus dem World Wide Web. Beschränkt auf Algorithmen, die auf Ron Rivest MD4 basieren, sind trotzdem die wichtigsten (MD5, SHA) enthalten. Die Kommentare sind etwas nachbearbeitet und übersetzt, leider waren diese Codes aber schon im Original nicht besonders dokumentiert. Bis auf eine sehr übersichltiche RIPE-MD-Implementierung, bei der die Kommentare im englischen Original sind.

14.1 MD5-Implementierung

/* Dies ist eine Implementierung des Message-Digest-Algorithmus
 * MD5 von Ron Rivest. Die Header-Datei MD5.h beinhaltet
 * Funktionsaufrufe und Variablendefinitionen. Die Datei MD5.c
 * besteht nur aus dem MD5-Algorithmus und beinhaltet keine
 * main-Funktion. D.h. der Algorithmus kann beliebig in Programme
 * eingefügt. Zu einem lauffähigen Programm muß ein MD5-Kontext
 * aus einer Datei eingelesen werden, durch die Funktionen MD5Init
 * initialisiert und durch MD5Update aufgefüllt und in Blöcke werden.
 * MD5Final schreibt den Hashwert in ein 16-byte-Array.
 * Der Code wurde 1993 von Colin Plumb ohne Copyright geschrieben
 * und stammt aus dem World Wide Web. */



/* Header-Datei MD5.h */

#ifndef MD5_H

#define MD5_H



#ifdef __alpha

typedef unsigned int uint32;

#else

typedef unsigned long uint32;

#endif



struct MD5Context {

        uint32 buf[4];

        uint32 bits[2];

        unsigned char in[64];

};



void MD5Init(struct MD5Context *context);

void MD5Update(struct MD5Context *context, unsigned char const *buf,

         unsigned len);

void MD5Final(unsigned char digest[16], struct MD5Context
*context);

void MD5Transform(uint32 buf[4], uint32 const in[16]);



typedef struct MD5Context MD5_CTX;



#endif /* !MD5_H */





/* Datei MD5.c */



#include <string.h>             /* for memcpy() */

#include "md5.h"



#ifndef HIGHFIRST

#define byteReverse(buf, len)   /* Nothing */

#else

void byteReverse(unsigned char *buf, unsigned longs);



#ifndef ASM_MD5

/* Auf Little-Endian-Machinen bringt dieser Code

* keinen Schaden. (aber Portabilität auch auf Big Endian) */

void byteReverse(unsigned char *buf, unsigned longs)

{

uint32 t;

do {

        t = (uint32) ((unsigned) buf[3] << 8 |
buf[2]) << 16 |

         ((unsigned) buf[1] << 8 | buf[0]);

        *(uint32 *) buf = t;

        buf += 4;

} while (--longs);

}

#endif

#endif



/* Start der MD5-Akkumulation. Setzt den Bit-Zähler auf 0

* und initialisiert die MD5-Konstanten */

void MD5Init(struct MD5Context *ctx)

{

ctx->buf[0] = 0x67452301;

ctx->buf[1] = 0xefcdab89;

ctx->buf[2] = 0x98badcfe;

ctx->buf[3] = 0x10325476;



ctx->bits[0] = 0;

ctx->bits[1] = 0;

}



/* Update des Kontexts */

void MD5Update(struct MD5Context *ctx, unsigned char const *buf,
unsigned len)

{

uint32 t;



/* Update bitcount */



t = ctx->bits[0];

if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)

        ctx->bits[1]++;         

ctx->bits[1] += len >> 29;



t = (t >> 3) & 0x3f;

if (t) {

        unsigned char *p = (unsigned char *) ctx->in + t;



        t = 64 - t;

        if (len < t) {

         memcpy(p, buf, len);

         return;

        }

        memcpy(p, buf, t);

        byteReverse(ctx->in, 16);

        MD5Transform(ctx->buf, (uint32 *) ctx->in);

        buf += t;

        len -= t;

}

/* Erstellen der 64-byte Blöcke */



while (len >= 64) {

        memcpy(ctx->in, buf, 64);

        byteReverse(ctx->in, 16);

        MD5Transform(ctx->buf, (uint32 *) ctx->in);

        buf += 64;

        len -= 64;

}



/* Handle any remaining bytes of data. */



memcpy(ctx->in, buf, len);

}



/* Schließlich - Auffüllen zu einer 64-byte-Abgrenzung mit
dem Muster

* 1 0 (64-bit Zähler, MSB-first) */

void MD5Final(unsigned char digest[16], struct MD5Context *ctx)

{

unsigned count;

unsigned char *p;



/* Berechne die Anzahl der Bytes mod 64 */

count = (ctx->bits[0] >> 3) & 0x3F;



/* Zuerst wird mit 0x80 aufgefüllt, weil immer mindestens ein Byte

* frei ist */

p = ctx->in + count;

*p++ = 0x80;



/* Bytes um auf 64 bytes aufzufüllen */

count = 64 - 1 - count;



/* Auffüllen bis auf 56 mod 64 */

if (count < 8) {

        /* Fülle den ersten Block auf 64 bytes */

        memset(p, 0, count);

        byteReverse(ctx->in, 16);

        MD5Transform(ctx->buf, (uint32 *) ctx->in);



        /* Fülle den nächsten Block mit 56 bytes */

        memset(ctx->in, 0, 56);

} else {

        memset(p, 0, count - 8);

}

byteReverse(ctx->in, 14);



/* Hängt die Länge Nachricht an */

((uint32 *) ctx->in)[14] = ctx->bits[0];

((uint32 *) ctx->in)[15] = ctx->bits[1];



MD5Transform(ctx->buf, (uint32 *) ctx->in);

byteReverse((unsigned char *) ctx->buf, 4);

memcpy(digest, ctx->buf, 16);

memset(ctx, 0, sizeof(ctx));    

}



#ifndef ASM_MD5



/* Die vier Kernfunktionen des Algorithmus */



#define F1(x, y, z) (x & y | ~x & z)

#define F2(x, y, z) F1(z, x, y)

#define F3(x, y, z) (x ^ y ^ z)

#define F4(x, y, z) (y ^ (x | ~z))



/* Der zentrale Schritt des Algorithmus*/

#define MD5STEP(f, w, x, y, z, data, s) \

        ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )



/* Dies ist der Kern des MD5-Algorithmus. Hier werden die einzelnen

* Blöcke verarbeitet. */



void MD5Transform(uint32 buf[4], uint32 const in[16])

{

register uint32 a, b, c, d;



a = buf[0];

b = buf[1];

c = buf[2];

d = buf[3];



MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);

MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);

MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);

MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);

MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);

MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);

MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);

MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);

MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);

MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);

MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);

MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);

MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);

MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);

MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);

MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);



MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);

MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);

MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);

MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);

MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);

MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);

MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);

MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);

MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);

MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);

MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);

MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);

MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);

MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);

MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);

MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);



MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);

MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);

MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);

MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);

MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);

MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);

MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);

MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);

MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);

MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);

MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);

MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);

MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);

MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);

MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);

MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);



MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);

MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);

MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);

MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);

MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);

MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);

MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);

MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);

MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);

MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);

MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);

MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);

MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);

MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);

MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);

MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);



buf[0] += a;

buf[1] += b;

buf[2] += c;

buf[3] += d;

}



#endif

14.2 SHA-Implementierung


/* NIST Secure Hash Algorithm

* Eine Peter C. Gutmanns-Implementierung, die von Uwe

* Hollerbach modifiziert und ohne Copyright im WWW zu

* finden ist.

* Wie schon zuvor wurde die main-Funktion nicht implementiert,

* so daß der Code in jedes beliebige Programm eingefügt werden

* kann. Die Funktionen SHA_init, SHA_update und SHA_final

* sind denen von MD5 pronzipiell ähnlich, nur das die Kernfunktionen

* natürlich unterschiedlich sind */





/* Die Header-Datei SHA.h mit nützlich Definition

* und Strukturen */



#ifndef SHA_H

#define SHA_H



typedef unsigned char BYTE;     

typedef unsigned long LONG;

#define SHA_BLOCKSIZE           64

#define SHA_DIGESTSIZE          20



typedef struct {

LONG digest[5];         /* message digest */

LONG count_lo, count_hi;        /* 64-bit bit count */

LONG data[16];          /* SHA data buffer */

int local;                      /* unprocessed amount in data */

} SHA_INFO;



void sha_init(SHA_INFO *);

void sha_update(SHA_INFO *, BYTE *, int);

void sha_final(SHA_INFO *);



#endif /* SHA_H */







/* Die Datei SHA.c des NIST Secure Hash Algorithm */



#include <string.h>

#include "sha.h"



/* Der Algorithmus ist für Little-Endian-Maschinen geschrieben

* (Intel, Vax). Die Funktion maybe_byte_reverse
ändert den Ablauf

* des Algorithmus für Big-Endian */



#define LITTLE_ENDIAN



/* NIST's vorgeschlagene Verbesserung von SHA am 11.07.94

* könnte man durch die Definition USE_MODIFIED_SHA

* einfügen */

#undef USE_MODIFIED_SHA



/* Die fünf nichtlinearen SHA f()-Funktions */



#define f1(x,y,z)       ((x & y) | (~x & z))

#define f2(x,y,z)       (x ^ y ^ z)

#define f3(x,y,z)       ((x & y) | (x & z) | (y & z))

#define f4(x,y,z)       (x ^ y ^ z)



/* Die vier rundenabhängigen SHA-Konstanten */



#define CONST1          0x5a827999L

#define CONST2          0x6ed9eba1L

#define CONST3          0x8f1bbcdcL

#define CONST4          0xca62c1d6L



/* Definition einer 32-bit Rotation */



#define ROT32(x,n)      ((x << n) | (x >> (32 - n)))



#define FUNC(n,i)                                               \

temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] +
CONST##n;       \

E = D; D = C; C = ROT32(B,30); B = A; A = temp



/* SHA Transformation */



static void sha_transform(SHA_INFO *sha_info)

{

int i;

LONG temp, A, B, C, D, E, W[80];



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

        W[i] = sha_info->data[i];

}

for (i = 16; i < 80; ++i) {

        W[i] = W[i-3] ^ W[i-8] ^
W[i-14] ^ W[i-16];

#ifdef USE_MODIFIED_SHA

        W[i] = ROT32(W[i], 1);

#endif /* USE_MODIFIED_SHA */

}

A = sha_info->digest[0];

B = sha_info->digest[1];

C = sha_info->digest[2];

D = sha_info->digest[3];

E = sha_info->digest[4];



/* Aufruf der Funktionen abhängig von der Zahl

* der Operationen */



for (i = 0; i < 20; ++i) {

        FUNC(1,i);

}

for (i = 20; i < 40; ++i) {

        FUNC(2,i);

}

for (i = 40; i < 60; ++i) {

        FUNC(3,i);

}

for (i = 60; i < 80; ++i) {

        FUNC(4,i);

}

/* Addieren der gehashten Teilblöcke zu den

* Verkettungsvariablen */



sha_info->digest[0] += A;

sha_info->digest[1] += B;

sha_info->digest[2] += C;

sha_info->digest[3] += D;

sha_info->digest[4] += E;

}



#ifdef LITTLE_ENDIAN



/* change endianness of data */



static void maybe_byte_reverse(LONG *buffer, int count)

{

int i;

BYTE ct[4], *cp;



count /= sizeof(LONG);

cp = (BYTE *) buffer;

for (i = 0; i < count; ++i) {

        ct[0] = cp[0];

        ct[1] = cp[1];

        ct[2] = cp[2];

        ct[3] = cp[3];

        cp[0] = ct[3];

        cp[1] = ct[2];

        cp[2] = ct[1];

        cp[3] = ct[0];

        cp += sizeof(LONG);

}

}



#else /* !LITTLE_ENDIAN */



#define maybe_byte_reverse(a,b) 



#endif /* LITTLE_ENDIAN */



/* Initialisierung des SHA-Kontext */



void sha_init(SHA_INFO *sha_info)

{

sha_info->digest[0] = 0x67452301L;

sha_info->digest[1] = 0xefcdab89L;

sha_info->digest[2] = 0x98badcfeL;

sha_info->digest[3] = 0x10325476L;

sha_info->digest[4] = 0xc3d2e1f0L;

sha_info->count_lo = 0L;

sha_info->count_hi = 0L;

sha_info->local = 0;

}



/* Den SHA-Kontext in Blöcke teilen*/



void sha_update(SHA_INFO *sha_info, BYTE *buffer,
int count)

{

int i;



if ((sha_info->count_lo + ((LONG) count << 3))
< sha_info->count_lo) {

        ++sha_info->count_hi;

}

sha_info->count_lo += (LONG) count << 3;

sha_info->count_hi += (LONG) count >> 29;

if (sha_info->local) {

        i = SHA_BLOCKSIZE - sha_info->local;

        if (i > count) {

         i = count;

        }

        memcpy(((BYTE *) sha_info->data) +
sha_info->local, buffer, i);

        count -= i;

        buffer += i;

        sha_info->local += i;

        if (sha_info->local == SHA_BLOCKSIZE) {

         maybe_byte_reverse(sha_info->data,
SHA_BLOCKSIZE);

         sha_transform(sha_info);

        } else {

         return;

        }

}

while (count >= SHA_BLOCKSIZE) {

        memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);

        buffer += SHA_BLOCKSIZE;

        count -= SHA_BLOCKSIZE;

        maybe_byte_reverse(sha_info->data,
SHA_BLOCKSIZE);

        sha_transform(sha_info);

}

memcpy(sha_info->data, buffer, count);

sha_info->local = count;

}



/* Hashwert berechnen */



void sha_final(SHA_INFO *sha_info)

{

int count;

LONG lo_bit_count, hi_bit_count;



lo_bit_count = sha_info->count_lo;

hi_bit_count = sha_info->count_hi;

count = (int) ((lo_bit_count >> 3) & 0x3f);

((BYTE *) sha_info->data)[count++] = 0x80;

if (count > SHA_BLOCKSIZE - 8) {

        memset(((BYTE *) sha_info->data) + count, 0,
SHA_BLOCKSIZE - count);

        maybe_byte_reverse(sha_info->data,
SHA_BLOCKSIZE);

        sha_transform(sha_info);

        memset((BYTE *) sha_info->data, 0, SHA_BLOCKSIZE
- 8);

} else {

        memset(((BYTE *) sha_info->data) + count, 0,

         SHA_BLOCKSIZE - 8 - count);

}

maybe_byte_reverse(sha_info->data,
SHA_BLOCKSIZE);

sha_info->data[14] = hi_bit_count;

sha_info->data[15] = lo_bit_count;

sha_transform(sha_info);

}

14.3 RIPE-MD-Implementierung

/********************************************************************\
 *
 * FILE: rmd128.h
 *
 * CONTENTS: Header file for a sample C-implementation of the
 * RIPEMD-128 hash-function. This function is a
 * plug-in substitute for RIPEMD. A 160-bit hash
 * result is obtained using RIPEMD-160.
 * TARGET: any computer with an ANSI C compiler
 *
 * AUTHOR: Antoon Bosselaers, ESAT-COSIC
 * DATE: 1 March 1996
 * VERSION: 1.0
 *
 * Copyright (c) Katholieke Universiteit Leuven
 * 1996, All Rights Reserved
 *
\********************************************************************/



#ifndef RMD128H /* make sure this file is read only once */

#define RMD128H



/********************************************************************/



/* typedef 8, 16 and 32 bit types, resp. */

/* adapt these, if necessary,

for your operating system and compiler */

typedef unsigned char byte; /* unsigned 8-bit type */

typedef unsigned short word; /* unsigned 16-bit type */

typedef unsigned long dword; /* unsigned 32-bit type */





/********************************************************************/



/* macro definitions */



/* collect four bytes into one word: */

#define BYTES_TO_DWORD(strptr) \

(((dword) *((strptr)+3) << 24) | \

((dword) *((strptr)+2) << 16) | \

((dword) *((strptr)+1) << 8) | \

((dword) *(strptr)))



/* ROL(x, n) cyclically rotates x over n bits to the left */

/* x must be of an unsigned 32 bits type and 0 <= n < 32. */

#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))



/* the three basic functions F(), G() and H() */

#define F(x, y, z) ((x) ^ (y) ^ (z))

#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))

#define H(x, y, z) (((x) | ~(y)) ^ (z))

#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))

/* the eight basic operations FF() through III() */

#define FF(a, b, c, d, x, s) {\

(a) += F((b), (c), (d)) + (x);\

(a) = ROL((a), (s));\

}

#define GG(a, b, c, d, x, s) {\

(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\

(a) = ROL((a), (s));\

}

#define HH(a, b, c, d, x, s) {\

(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\

(a) = ROL((a), (s));\

}

#define II(a, b, c, d, x, s) {\

(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\

(a) = ROL((a), (s));\

}

#define FFF(a, b, c, d, x, s) {\

(a) += F((b), (c), (d)) + (x);\

(a) = ROL((a), (s));\

}

#define GGG(a, b, c, d, x, s) {\

(a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\

(a) = ROL((a), (s));\

}

#define HHH(a, b, c, d, x, s) {\

(a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\

(a) = ROL((a), (s));\

}

#define III(a, b, c, d, x, s) {\

(a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\

(a) = ROL((a), (s));\

}



/********************************************************************/



/* function prototypes */



void MDinit(dword *MDbuf);

/*

* initializes MDbuffer to "magic constants"

*/



void compress(dword *MDbuf, dword *X);

/*

* the compression function.

* transforms MDbuf using message bytes X[0] through
X[15]

*/



void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen);

/*

* puts bytes from strptr into X and pad out; appends length

* and finally, compresses the last block(s)

* note: length in bits == 8 * (lswlen + 2^32 mswlen).

* note: there are (lswlen mod 64) bytes left in strptr.

*/



#endif /* RMD128H */



/*********************** end of file rmd128.h ***********************/







/********************************************************************\

*

* FILE: rmd128.c

*

* CONTENTS: A sample C-implementation of the RIPEMD-128

* hash-function. This function is a plug-in substitute

* for RIPEMD. A 160-bit hash result is obtained using

* RIPEMD-160.

* TARGET: any computer with an ANSI C compiler

*

* AUTHOR: Antoon Bosselaers, ESAT-COSIC

* DATE: 1 March 1996

* VERSION: 1.0

*

* Copyright (c) Katholieke Universiteit Leuven

* 1996, All Rights Reserved

*

\********************************************************************/



/* header files */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "rmd128.h"



/********************************************************************/



void MDinit(dword *MDbuf)

{

MDbuf[0] = 0x67452301UL;

MDbuf[1] = 0xefcdab89UL;

MDbuf[2] = 0x98badcfeUL;

MDbuf[3] = 0x10325476UL;



return;

}



/********************************************************************/



void compress(dword *MDbuf, dword *X)

{

dword aa = MDbuf[0], bb = MDbuf[1], cc =
MDbuf[2], dd = MDbuf[3];

dword aaa = MDbuf[0], bbb = MDbuf[1], ccc =
MDbuf[2], ddd = MDbuf[3];



/* round 1 */

FF(aa, bb, cc, dd, X[ 0], 11);

FF(dd, aa, bb, cc, X[ 1], 14);

FF(cc, dd, aa, bb, X[ 2], 15);

FF(bb, cc, dd, aa, X[ 3], 12);

FF(aa, bb, cc, dd, X[ 4], 5);

FF(dd, aa, bb, cc, X[ 5], 8);

FF(cc, dd, aa, bb, X[ 6], 7);

FF(bb, cc, dd, aa, X[ 7], 9);

FF(aa, bb, cc, dd, X[ 8], 11);

FF(dd, aa, bb, cc, X[ 9], 13);

FF(cc, dd, aa, bb, X[10], 14);

FF(bb, cc, dd, aa, X[11], 15);

FF(aa, bb, cc, dd, X[12], 6);

FF(dd, aa, bb, cc, X[13], 7);

FF(cc, dd, aa, bb, X[14], 9);

FF(bb, cc, dd, aa, X[15], 8);

/* round 2 */

GG(aa, bb, cc, dd, X[ 7], 7);

GG(dd, aa, bb, cc, X[ 4], 6);

GG(cc, dd, aa, bb, X[13], 8);

GG(bb, cc, dd, aa, X[ 1], 13);

GG(aa, bb, cc, dd, X[10], 11);

GG(dd, aa, bb, cc, X[ 6], 9);

GG(cc, dd, aa, bb, X[15], 7);

GG(bb, cc, dd, aa, X[ 3], 15);

GG(aa, bb, cc, dd, X[12], 7);

GG(dd, aa, bb, cc, X[ 0], 12);

GG(cc, dd, aa, bb, X[ 9], 15);

GG(bb, cc, dd, aa, X[ 5], 9);

GG(aa, bb, cc, dd, X[ 2], 11);

GG(dd, aa, bb, cc, X[14], 7);

GG(cc, dd, aa, bb, X[11], 13);

GG(bb, cc, dd, aa, X[ 8], 12);



/* round 3 */

HH(aa, bb, cc, dd, X[ 3], 11);

HH(dd, aa, bb, cc, X[10], 13);

HH(cc, dd, aa, bb, X[14], 6);

HH(bb, cc, dd, aa, X[ 4], 7);

HH(aa, bb, cc, dd, X[ 9], 14);

HH(dd, aa, bb, cc, X[15], 9);

HH(cc, dd, aa, bb, X[ 8], 13);

HH(bb, cc, dd, aa, X[ 1], 15);

HH(aa, bb, cc, dd, X[ 2], 14);

HH(dd, aa, bb, cc, X[ 7], 8);

HH(cc, dd, aa, bb, X[ 0], 13);

HH(bb, cc, dd, aa, X[ 6], 6);

HH(aa, bb, cc, dd, X[13], 5);

HH(dd, aa, bb, cc, X[11], 12);

HH(cc, dd, aa, bb, X[ 5], 7);

HH(bb, cc, dd, aa, X[12], 5);



/* round 4 */

II(aa, bb, cc, dd, X[ 1], 11);

II(dd, aa, bb, cc, X[ 9], 12);

II(cc, dd, aa, bb, X[11], 14);

II(bb, cc, dd, aa, X[10], 15);

II(aa, bb, cc, dd, X[ 0], 14);

II(dd, aa, bb, cc, X[ 8], 15);

II(cc, dd, aa, bb, X[12], 9);

II(bb, cc, dd, aa, X[ 4], 8);

II(aa, bb, cc, dd, X[13], 9);

II(dd, aa, bb, cc, X[ 3], 14);

II(cc, dd, aa, bb, X[ 7], 5);

II(bb, cc, dd, aa, X[15], 6);

II(aa, bb, cc, dd, X[14], 8);

II(dd, aa, bb, cc, X[ 5], 6);

II(cc, dd, aa, bb, X[ 6], 5);

II(bb, cc, dd, aa, X[ 2], 12);



/* parallel round 1 */

III(aaa, bbb, ccc, ddd, X[ 5], 8);

III(ddd, aaa, bbb, ccc, X[14], 9);

III(ccc, ddd, aaa, bbb, X[ 7], 9);

III(bbb, ccc, ddd, aaa, X[ 0], 11);

III(aaa, bbb, ccc, ddd, X[ 9], 13);

III(ddd, aaa, bbb, ccc, X[ 2], 15);

III(ccc, ddd, aaa, bbb, X[11], 15);

III(bbb, ccc, ddd, aaa, X[ 4], 5);

III(aaa, bbb, ccc, ddd, X[13], 7);

III(ddd, aaa, bbb, ccc, X[ 6], 7);

III(ccc, ddd, aaa, bbb, X[15], 8);

III(bbb, ccc, ddd, aaa, X[ 8], 11);

III(aaa, bbb, ccc, ddd, X[ 1], 14);

III(ddd, aaa, bbb, ccc, X[10], 14);

III(ccc, ddd, aaa, bbb, X[ 3], 12);

III(bbb, ccc, ddd, aaa, X[12], 6);



/* parallel round 2 */

HHH(aaa, bbb, ccc, ddd, X[ 6], 9);

HHH(ddd, aaa, bbb, ccc, X[11], 13);

HHH(ccc, ddd, aaa, bbb, X[ 3], 15);

HHH(bbb, ccc, ddd, aaa, X[ 7], 7);

HHH(aaa, bbb, ccc, ddd, X[ 0], 12);

HHH(ddd, aaa, bbb, ccc, X[13], 8);

HHH(ccc, ddd, aaa, bbb, X[ 5], 9);

HHH(bbb, ccc, ddd, aaa, X[10], 11);

HHH(aaa, bbb, ccc, ddd, X[14], 7);

HHH(ddd, aaa, bbb, ccc, X[15], 7);

HHH(ccc, ddd, aaa, bbb, X[ 8], 12);

HHH(bbb, ccc, ddd, aaa, X[12], 7);

HHH(aaa, bbb, ccc, ddd, X[ 4], 6);

HHH(ddd, aaa, bbb, ccc, X[ 9], 15);

HHH(ccc, ddd, aaa, bbb, X[ 1], 13);

HHH(bbb, ccc, ddd, aaa, X[ 2], 11);



/* parallel round 3 */

GGG(aaa, bbb, ccc, ddd, X[15], 9);

GGG(ddd, aaa, bbb, ccc, X[ 5], 7);

GGG(ccc, ddd, aaa, bbb, X[ 1], 15);

GGG(bbb, ccc, ddd, aaa, X[ 3], 11);

GGG(aaa, bbb, ccc, ddd, X[ 7], 8);

GGG(ddd, aaa, bbb, ccc, X[14], 6);

GGG(ccc, ddd, aaa, bbb, X[ 6], 6);

GGG(bbb, ccc, ddd, aaa, X[ 9], 14);

GGG(aaa, bbb, ccc, ddd, X[11], 12);

GGG(ddd, aaa, bbb, ccc, X[ 8], 13);

GGG(ccc, ddd, aaa, bbb, X[12], 5);

GGG(bbb, ccc, ddd, aaa, X[ 2], 14);

GGG(aaa, bbb, ccc, ddd, X[10], 13);

GGG(ddd, aaa, bbb, ccc, X[ 0], 13);

GGG(ccc, ddd, aaa, bbb, X[ 4], 7);

GGG(bbb, ccc, ddd, aaa, X[13], 5);



/* parallel round 4 */

FFF(aaa, bbb, ccc, ddd, X[ 8], 15);

FFF(ddd, aaa, bbb, ccc, X[ 6], 5);

FFF(ccc, ddd, aaa, bbb, X[ 4], 8);

FFF(bbb, ccc, ddd, aaa, X[ 1], 11);

FFF(aaa, bbb, ccc, ddd, X[ 3], 14);

FFF(ddd, aaa, bbb, ccc, X[11], 14);

FFF(ccc, ddd, aaa, bbb, X[15], 6);

FFF(bbb, ccc, ddd, aaa, X[ 0], 14);

FFF(aaa, bbb, ccc, ddd, X[ 5], 6);

FFF(ddd, aaa, bbb, ccc, X[12], 9);

FFF(ccc, ddd, aaa, bbb, X[ 2], 12);

FFF(bbb, ccc, ddd, aaa, X[13], 9);

FFF(aaa, bbb, ccc, ddd, X[ 9], 12);

FFF(ddd, aaa, bbb, ccc, X[ 7], 5);

FFF(ccc, ddd, aaa, bbb, X[10], 15);

FFF(bbb, ccc, ddd, aaa, X[14], 8);



/* combine results */

ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */

MDbuf[1] = MDbuf[2] + dd + aaa;

MDbuf[2] = MDbuf[3] + aa + bbb;

MDbuf[3] = MDbuf[0] + bb + ccc;

MDbuf[0] = ddd;



return;

}



/********************************************************************/



void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen)

{

dword i; /* counter */

dword X[16]; /* message words */



memset(X, 0, 16*sizeof(dword));



/* put bytes from strptr into X */

for (i=0; i<(lswlen&63); i++) {

/* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */

X[i>>2] ^= (dword) *strptr++ << (8 *
(i&3));

}



/* append the bit m_n == 1 */

X[(lswlen>>2)&15] ^= (dword)1 <<
(8*(lswlen&3) + 7);



if ((lswlen & 63) > 55) {

/* length goes to next block */

compress(MDbuf, X);

memset(X, 0, 16*sizeof(dword));

}



/* append length in bits*/

X[14] = lswlen << 3;

X[15] = (lswlen >> 29) | (mswlen << 3);

compress(MDbuf, X);



return;

}



/************************ end of file rmd128.c **********************/


Vorherige Seite Nächste Seite Inhalt