Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Security

The RIPEMD-160 Cryptographic Hash Function

Antoon Bosselaers, and

, January 01, 1997


Dr. Dobb's Journal January 1997: The RIPEMD-160 Cryptographic Hash Function

The RIPEMD-160 Cryptographic Hash Function

Antoon and Bart are with the COSIC research group of the Department of Electrical Engineering of the Katholieke Universiteit Leuven. They can be contacted at [email protected] and [email protected]., respectively. Bart is also an N.F.W.O. postdoctoral researcher, sponsored by the National Fund for Scientific Research (Belgium). Hans is with the German Information Security Agency. He can be contacted at [email protected].


Sidebar: "Examining the Birthday Paradox"

A cryptographic hash function takes an input string (message) of arbitrary size and reduces it to a short string of typically 16 or 20 bytes. The hash value of an input string is equivalent to the fingerprint of a person. It is often also called a "message digest." Hash functions are used for digital signatures such as RSA and DSA, but also for the construction of MACs (message authentication codes), the protection of passwords, and for the derivation of independent secret keys from a single master key. Cryptographic hash functions are an essential building block for applications that require data integrity, such as detectors of computer viruses, Internet security (for example PGP or IPSEC), and the security of electronic commerce and banking. Well-known hash functions designed by Ron Rivest include MD4 and its successor, MD5. However, recent research has questioned their security. We have designed a hash function called "RIPEMD-160," a secure replacement for MD4 and MD5.

A hash function must be a one-way function, which means that finding an input corresponding to a given output string is difficult: Even an opponent who wants to spend a significant amount of money, say $10 million, will have a negligible success probability. Given a specific input and its hash value, finding a different input hashing to the same value should also be difficult (this is called a "second preimage").

For some applications, such as digital signatures, it should also be difficult to find two different inputs with the same hash value. Such a pair is called a "collision." This might seem the same as finding a second preimage, but it turns out that this problem is a lot easier to solve. A simple analogy is the following: You will need, on average, to talk to 365/2=182 people before finding someone who is born on the same day as you. But, in a group of 23 people, odds are 2:1 that there are two people with the same birthday. This surprising observation is known as the "birthday paradox." See the accompanying text box entitled "Examining the Birthday Paradox." In practice, the probabilities are even higher, since birthdays are not evenly distributed over the year.

By the same reasoning, finding collisions for a hash function with a 16-byte (128-bit) result (as MD4 and MD5) requires about = 264 21019 evaluations of the function. For MD4 and MD5, this brute-force job can be done in about a month with a $10 million investment. These calculations have been made rigorous by Paul van Oorschot and Mike Wiener, two cryptographers from Nortel. For 20-byte hash results, the same amount of money will only bring success after a few thousand years (but this ball-park estimate does not take into account that computers become faster every year). Thus, if you select a hash function for digital-signature schemes, you better go for one with a 20-byte result. After all, the overhead in storage and computation is relatively small.

Another reason to move away from MD4 and MD5 are the analytic attacks found by Hans Dobbertin. By outfoxing the internal structure of the respective hash algorithm, a collision pair for MD4 can be constructed in less than a second on a PC, and collisions for a modified version of MD5 (with a different so-called "initial value") can be found in about ten hours on a PC. These results show that a more conservative approach to the design of hash functions is required; new hash functions need more rounds and will be slower than the previous ones.

RIPEMD-160 is just such a hash function. It is a strengthened version of RIPEMD, which was developed in the framework of the EU project RIPE ("Race Integrity Primitives Evaluation, '88-'92"). RIPEMD has only a 16-byte result, and the new attacks proposed by Dobbertin apply to a reduced version of RIPEMD.

RIPEMD-160 is a fast cryptographic hash function that is expected to be secure for the next ten years or more. The design philosophy is to build as much as possible on the experience gained by evaluating MD4, MD5, and RIPEMD. Like its predecessors, RIPEMD-160 is tuned for 32-bit processors, which we feel will remain important in the coming decade. The algorithm will work on 8- and 16-bit microprocessors, but will be slower. It also does not take full advantage of 64-bit processors.

Overview of the Algorithm

RIPEMD-160, like all variants of MD4, operates on 32-bit words. It uses the following primitive operations:

  • Bitwise Boolean operations (AND, NOT, OR, exclusive-OR).
  • Two's complement addition of words, denoted by "+." This is modulo 232 addition.
  • Left rotation (or "left spin") of words.

RIPEMD-160 compresses an arbitrary-size input by dividing it into blocks of 64 bytes (512 bits) each. To guarantee that the total input size is a multiple of 64 bytes, the input is padded: You append a single 1 bit followed by a string of 0 bits (the number of 0 bits is between 0 and 511). The input is always padded, even if it is already a multiple of 64 bytes. The 8 bytes of the extended input contain the binary representation of the input size in bits. Each 64-byte block is converted to a 16-word block using a Little-endian convention.

The result of RIPEMD-160 is contained in five 32-bit words, which form the internal state of the algorithm. This state is initialized with a fixed string, the initial value. The main part of the algorithm is known as the "compression function:" It computes the new state from the old state and the next 16-word block.

The compression function consists of five parallel rounds, each containing 16 steps. The total number of steps is thus 5×16×2 = 160, compared to 3×16 = 48 for MD4, and 4×16 = 64 for MD5. First, two copies are made from the old state (five left and right registers of 32 bits). Both halves are processed independently. Each step computes a new value for one of the registers based on the other four registers and one message word. At the end of the compression function, we compute the new state by adding one register from the left half and one from the right half on the same processor (see Figure 1). The 20-byte hash result is obtained by converting the final value of the 5-word internal state to a string of 20 bytes using a Little-endian convention.

The C source code of RIPEMD-160 (see Listings One and Two) has been tested in many environments, including MS-DOS, Windows, and UNIX. RIPEMD-160 has been put in the public domain by its designers, so anyone can use it. Pseudocode and test values for RIPEMD-160 are available electronically; see "Availability," page 3.

Speed and Security

Highly optimized assembly code of RIPEMD-160 runs at 40 Mbit/sec on a 90-MHz Pentium. The code is about 4.2 KB in size. The fastest C versions are about two times slower when compiled with Watcom C 10.0 in native protected mode.

RIPEMD-160 is three-times slower than MD5, but note that RIPEMD-160 is a conservative design that is intended to be used for applications which require high security for an extended period of time. It would be tempting to design an algorithm with performance in between the two algorithms, but such an algorithm could not give you the same confidence.

References

Schneier, B. "One-Way Hash Functions." Dr. Dobb's Journal, September 1991.

Dobbertin, H. "Cryptanalysis of MD4." Fast Software Encryption, LNCS 1039, D. Gollmann, Ed. New York, NY: Springer-Verlag, 1996.

Bosselaers, A. and Preneel, B., eds., "Integrity Primitives for Secure Information Systems. Final Report of RACE Integrity Primitives Evaluation (RIPE-RACE 1040)." LNCS 1007. New York, NY: Springer-Verlag, 1995.

van Oorschot, P.C. and M.J. Wiener, "Parallel collision search with application to hash functions and discrete logarithms." Proc. 2nd ACM Conference on Computer and Communications Security, ACM, 1994.

DDJ

Listing One

/********************************************************************\ *  FILE:     rmd160.c
 *  CONTENTS: A sample C-implementation of the RIPEMD-160 hash-function.
 *  TARGET:   any computer with an ANSI C compiler
 *  AUTHOR:   Antoon Bosselaers, Dept. Electrical Eng.-ESAT/COSIC
 *  DATE:     1 March 1996       VERSION:  1.0
 **********************************************************************
 * Copyright (c) Katholieke Universiteit Leuven 1996, All Rights Reserved. 
 * The Katholieke Universiteit Leuven makes no representations concerning
 * either the merchantability of this software or the suitability of this 
 * software for any particular purpose. It is provided "as is" without 
 * express or implied warranty of any kind. These notices must be retained in 
 * any copies of any part of this documentation and/or software.
\********************************************************************/


</p>
/* header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rmd160.h"


</p>
/********************************************************************/
void MDinit(word *MDbuf)
/* Initialization of 5-word MDbuf array to magic initialization constants */
{
   MDbuf[0] = 0x67452301UL;
   MDbuf[1] = 0xefcdab89UL;
   MDbuf[2] = 0x98badcfeUL;
   MDbuf[3] = 0x10325476UL;
   MDbuf[4] = 0xc3d2e1f0UL;
}
/********************************************************************/
void MDcompress(word *MDbuf, word *X)
/* The compression function is called for every complete 64-byte
 message block. The 5-word internal state MDbuf is updated using
 message words X[0] through X[15]. The conversion from a string of
 64 bytes to an array of 16 words using a Little-endian convention is
 the responsibility of the calling function. */
{
        /* make two copies of the old state */
   word aa = MDbuf[0],  bb = MDbuf[1],  cc = MDbuf[2],
        dd = MDbuf[3],  ee = MDbuf[4];
   word aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
        ddd = MDbuf[3], eee = MDbuf[4];


</p>
   /* round 1 */
   FF1(aa, bb, cc, dd, ee, X[ 0], 11);
   FF1(ee, aa, bb, cc, dd, X[ 1], 14);
   FF1(dd, ee, aa, bb, cc, X[ 2], 15);
   FF1(cc, dd, ee, aa, bb, X[ 3], 12);
   FF1(bb, cc, dd, ee, aa, X[ 4],  5);
   FF1(aa, bb, cc, dd, ee, X[ 5],  8);
   FF1(ee, aa, bb, cc, dd, X[ 6],  7);
   FF1(dd, ee, aa, bb, cc, X[ 7],  9);
   FF1(cc, dd, ee, aa, bb, X[ 8], 11);
   FF1(bb, cc, dd, ee, aa, X[ 9], 13);
   FF1(aa, bb, cc, dd, ee, X[10], 14);
   FF1(ee, aa, bb, cc, dd, X[11], 15);
   FF1(dd, ee, aa, bb, cc, X[12],  6);
   FF1(cc, dd, ee, aa, bb, X[13],  7);
   FF1(bb, cc, dd, ee, aa, X[14],  9);
   FF1(aa, bb, cc, dd, ee, X[15],  8);


</p>
   /* round 2 */
   FF2(ee, aa, bb, cc, dd, X[ 7],  7);
   FF2(dd, ee, aa, bb, cc, X[ 4],  6);
   FF2(cc, dd, ee, aa, bb, X[13],  8);
   FF2(bb, cc, dd, ee, aa, X[ 1], 13);
   FF2(aa, bb, cc, dd, ee, X[10], 11);
   FF2(ee, aa, bb, cc, dd, X[ 6],  9);
   FF2(dd, ee, aa, bb, cc, X[15],  7);
   FF2(cc, dd, ee, aa, bb, X[ 3], 15);
   FF2(bb, cc, dd, ee, aa, X[12],  7);
   FF2(aa, bb, cc, dd, ee, X[ 0], 12);
   FF2(ee, aa, bb, cc, dd, X[ 9], 15);
   FF2(dd, ee, aa, bb, cc, X[ 5],  9);
   FF2(cc, dd, ee, aa, bb, X[ 2], 11);
   FF2(bb, cc, dd, ee, aa, X[14],  7);
   FF2(aa, bb, cc, dd, ee, X[11], 13);
   FF2(ee, aa, bb, cc, dd, X[ 8], 12);


</p>
   /* round 3 */
   FF3(dd, ee, aa, bb, cc, X[ 3], 11);
   FF3(cc, dd, ee, aa, bb, X[10], 13);
   FF3(bb, cc, dd, ee, aa, X[14],  6);
   FF3(aa, bb, cc, dd, ee, X[ 4],  7);
   FF3(ee, aa, bb, cc, dd, X[ 9], 14);
   FF3(dd, ee, aa, bb, cc, X[15],  9);
   FF3(cc, dd, ee, aa, bb, X[ 8], 13);
   FF3(bb, cc, dd, ee, aa, X[ 1], 15);
   FF3(aa, bb, cc, dd, ee, X[ 2], 14);
   FF3(ee, aa, bb, cc, dd, X[ 7],  8);
   FF3(dd, ee, aa, bb, cc, X[ 0], 13);
   FF3(cc, dd, ee, aa, bb, X[ 6],  6);
   FF3(bb, cc, dd, ee, aa, X[13],  5);
   FF3(aa, bb, cc, dd, ee, X[11], 12);
   FF3(ee, aa, bb, cc, dd, X[ 5],  7);
   FF3(dd, ee, aa, bb, cc, X[12],  5);


</p>
   /* round 4 */
   FF4(cc, dd, ee, aa, bb, X[ 1], 11);
   FF4(bb, cc, dd, ee, aa, X[ 9], 12);
   FF4(aa, bb, cc, dd, ee, X[11], 14);
   FF4(ee, aa, bb, cc, dd, X[10], 15);
   FF4(dd, ee, aa, bb, cc, X[ 0], 14);
   FF4(cc, dd, ee, aa, bb, X[ 8], 15);
   FF4(bb, cc, dd, ee, aa, X[12],  9);
   FF4(aa, bb, cc, dd, ee, X[ 4],  8);
   FF4(ee, aa, bb, cc, dd, X[13],  9);
   FF4(dd, ee, aa, bb, cc, X[ 3], 14);
   FF4(cc, dd, ee, aa, bb, X[ 7],  5);
   FF4(bb, cc, dd, ee, aa, X[15],  6);
   FF4(aa, bb, cc, dd, ee, X[14],  8);
   FF4(ee, aa, bb, cc, dd, X[ 5],  6);
   FF4(dd, ee, aa, bb, cc, X[ 6],  5);
   FF4(cc, dd, ee, aa, bb, X[ 2], 12);


</p>
   /* round 5 */
   FF5(bb, cc, dd, ee, aa, X[ 4],  9);
   FF5(aa, bb, cc, dd, ee, X[ 0], 15);
   FF5(ee, aa, bb, cc, dd, X[ 5],  5);
   FF5(dd, ee, aa, bb, cc, X[ 9], 11);
   FF5(cc, dd, ee, aa, bb, X[ 7],  6);
   FF5(bb, cc, dd, ee, aa, X[12],  8);
   FF5(aa, bb, cc, dd, ee, X[ 2], 13);
   FF5(ee, aa, bb, cc, dd, X[10], 12);
   FF5(dd, ee, aa, bb, cc, X[14],  5);
   FF5(cc, dd, ee, aa, bb, X[ 1], 12);
   FF5(bb, cc, dd, ee, aa, X[ 3], 13);
   FF5(aa, bb, cc, dd, ee, X[ 8], 14);
   FF5(ee, aa, bb, cc, dd, X[11], 11);
   FF5(dd, ee, aa, bb, cc, X[ 6],  8);
   FF5(cc, dd, ee, aa, bb, X[15],  5);
   FF5(bb, cc, dd, ee, aa, X[13],  6);


</p>
   /* parallel round 1 */
   FFF5(aaa, bbb, ccc, ddd, eee, X[ 5],  8);
   FFF5(eee, aaa, bbb, ccc, ddd, X[14],  9);
   FFF5(ddd, eee, aaa, bbb, ccc, X[ 7],  9);
   FFF5(ccc, ddd, eee, aaa, bbb, X[ 0], 11);
   FFF5(bbb, ccc, ddd, eee, aaa, X[ 9], 13);
   FFF5(aaa, bbb, ccc, ddd, eee, X[ 2], 15);
   FFF5(eee, aaa, bbb, ccc, ddd, X[11], 15);
   FFF5(ddd, eee, aaa, bbb, ccc, X[ 4],  5);
   FFF5(ccc, ddd, eee, aaa, bbb, X[13],  7);
   FFF5(bbb, ccc, ddd, eee, aaa, X[ 6],  7);
   FFF5(aaa, bbb, ccc, ddd, eee, X[15],  8);
   FFF5(eee, aaa, bbb, ccc, ddd, X[ 8], 11);
   FFF5(ddd, eee, aaa, bbb, ccc, X[ 1], 14);
   FFF5(ccc, ddd, eee, aaa, bbb, X[10], 14);
   FFF5(bbb, ccc, ddd, eee, aaa, X[ 3], 12);
   FFF5(aaa, bbb, ccc, ddd, eee, X[12],  6);


</p>
   /* parallel round 2 */
   FFF4(eee, aaa, bbb, ccc, ddd, X[ 6],  9);
   FFF4(ddd, eee, aaa, bbb, ccc, X[11], 13);
   FFF4(ccc, ddd, eee, aaa, bbb, X[ 3], 15);
   FFF4(bbb, ccc, ddd, eee, aaa, X[ 7],  7);
   FFF4(aaa, bbb, ccc, ddd, eee, X[ 0], 12);
   FFF4(eee, aaa, bbb, ccc, ddd, X[13],  8);
   FFF4(ddd, eee, aaa, bbb, ccc, X[ 5],  9);
   FFF4(ccc, ddd, eee, aaa, bbb, X[10], 11);
   FFF4(bbb, ccc, ddd, eee, aaa, X[14],  7);
   FFF4(aaa, bbb, ccc, ddd, eee, X[15],  7);
   FFF4(eee, aaa, bbb, ccc, ddd, X[ 8], 12);
   FFF4(ddd, eee, aaa, bbb, ccc, X[12],  7);
   FFF4(ccc, ddd, eee, aaa, bbb, X[ 4],  6);
   FFF4(bbb, ccc, ddd, eee, aaa, X[ 9], 15);
   FFF4(aaa, bbb, ccc, ddd, eee, X[ 1], 13);
   FFF4(eee, aaa, bbb, ccc, ddd, X[ 2], 11);


</p>
   /* parallel round 3 */
   FFF3(ddd, eee, aaa, bbb, ccc, X[15],  9);
   FFF3(ccc, ddd, eee, aaa, bbb, X[ 5],  7);
   FFF3(bbb, ccc, ddd, eee, aaa, X[ 1], 15);
   FFF3(aaa, bbb, ccc, ddd, eee, X[ 3], 11);
   FFF3(eee, aaa, bbb, ccc, ddd, X[ 7],  8);
   FFF3(ddd, eee, aaa, bbb, ccc, X[14],  6);
   FFF3(ccc, ddd, eee, aaa, bbb, X[ 6],  6);
   FFF3(bbb, ccc, ddd, eee, aaa, X[ 9], 14);
   FFF3(aaa, bbb, ccc, ddd, eee, X[11], 12);
   FFF3(eee, aaa, bbb, ccc, ddd, X[ 8], 13);
   FFF3(ddd, eee, aaa, bbb, ccc, X[12],  5);
   FFF3(ccc, ddd, eee, aaa, bbb, X[ 2], 14);
   FFF3(bbb, ccc, ddd, eee, aaa, X[10], 13);
   FFF3(aaa, bbb, ccc, ddd, eee, X[ 0], 13);
   FFF3(eee, aaa, bbb, ccc, ddd, X[ 4],  7);
   FFF3(ddd, eee, aaa, bbb, ccc, X[13],  5);


</p>
   /* parallel round 4 */
   FFF2(ccc, ddd, eee, aaa, bbb, X[ 8], 15);
   FFF2(bbb, ccc, ddd, eee, aaa, X[ 6],  5);
   FFF2(aaa, bbb, ccc, ddd, eee, X[ 4],  8);
   FFF2(eee, aaa, bbb, ccc, ddd, X[ 1], 11);
   FFF2(ddd, eee, aaa, bbb, ccc, X[ 3], 14);
   FFF2(ccc, ddd, eee, aaa, bbb, X[11], 14);
   FFF2(bbb, ccc, ddd, eee, aaa, X[15],  6);
   FFF2(aaa, bbb, ccc, ddd, eee, X[ 0], 14);
   FFF2(eee, aaa, bbb, ccc, ddd, X[ 5],  6);
   FFF2(ddd, eee, aaa, bbb, ccc, X[12],  9);
   FFF2(ccc, ddd, eee, aaa, bbb, X[ 2], 12);
   FFF2(bbb, ccc, ddd, eee, aaa, X[13],  9);
   FFF2(aaa, bbb, ccc, ddd, eee, X[ 9], 12);
   FFF2(eee, aaa, bbb, ccc, ddd, X[ 7],  5);
   FFF2(ddd, eee, aaa, bbb, ccc, X[10], 15);
   FFF2(ccc, ddd, eee, aaa, bbb, X[14],  8);


</p>
   /* parallel round 5 */
   FFF1(bbb, ccc, ddd, eee, aaa, X[12] ,  8);
   FFF1(aaa, bbb, ccc, ddd, eee, X[15] ,  5);
   FFF1(eee, aaa, bbb, ccc, ddd, X[10] , 12);
   FFF1(ddd, eee, aaa, bbb, ccc, X[ 4] ,  9);
   FFF1(ccc, ddd, eee, aaa, bbb, X[ 1] , 12);
   FFF1(bbb, ccc, ddd, eee, aaa, X[ 5] ,  5);
   FFF1(aaa, bbb, ccc, ddd, eee, X[ 8] , 14);
   FFF1(eee, aaa, bbb, ccc, ddd, X[ 7] ,  6);
   FFF1(ddd, eee, aaa, bbb, ccc, X[ 6] ,  8);
   FFF1(ccc, ddd, eee, aaa, bbb, X[ 2] , 13);
   FFF1(bbb, ccc, ddd, eee, aaa, X[13] ,  6);
   FFF1(aaa, bbb, ccc, ddd, eee, X[14] ,  5);
   FFF1(eee, aaa, bbb, ccc, ddd, X[ 0] , 15);
   FFF1(ddd, eee, aaa, bbb, ccc, X[ 3] , 13);
   FFF1(ccc, ddd, eee, aaa, bbb, X[ 9] , 11);
   FFF1(bbb, ccc, ddd, eee, aaa, X[11] , 11);


</p>
   /* combine results into new state */
   ddd += cc + MDbuf[1];
   MDbuf[1] = MDbuf[2] + dd + eee;
   MDbuf[2] = MDbuf[3] + ee + aaa;
   MDbuf[3] = MDbuf[4] + aa + bbb;
   MDbuf[4] = MDbuf[0] + bb + ccc;
   MDbuf[0] = ddd;
}
/********************************************************************/
void MDfinish(word *MDbuf, byte *string, word lswlen, word mswlen)
/* The final value of the 5-word MDbuf array is calculated. lswlen and mswlen 
 contain, respectively, the least and most significant 32 bits of the message 
 bit length mod 2^64, and string is an incomplete block containing the 
 (lswlen mod 512) remaining message bits. (In case the message is already a
 multiple of 512 bits, string is not used.) The conversion of the 5-word final 
 state MDbuf to the 20-byte hash result using a Little-endian convention is the 
 responsibility of the calling function.
 */
{
   size_t i, length;
   byte   mask;
   word   X[16];


</p>
   /* clear 16-word message block */
   memset(X, 0, 16*sizeof(word));


</p>
   /* copy (lswlen mod 512) bits from string into X */
   length = ((lswlen&511)+7)/8; /* number of bytes */
   mask = (lswlen&7) ? ((byte)1 << (lswlen&7)) - 1 : 0xff;
   for (i=0; i<length; i++) {
      /* byte i goes into word X[i div 4] at bit position 8*(i mod 4) */
      if (i == length-1)
         X[i>>2] ^= (word) (*string&mask) << (8*(i&3));
      else
         X[i>>2] ^= (word) *string++ << (8*(i&3));
   }
   /* append a single 1 */
   X[(lswlen>>5)&15] ^= (word)1 << (8*((lswlen>>3)&3)+7-(lswlen&7));
   if ((lswlen & 511) > 447) {
      /* length doesn't fit in this block anymore.
         Compress, and put length in the next block */
      MDcompress(MDbuf, X);
      memset(X, 0, 16*sizeof(word));
   }
  /* append length in bits*/
   X[14] = lswlen;
   X[15] = mswlen;
   MDcompress(MDbuf, X);
}
/************************ end of file rmd160.c **********************/

Back to Article

Listing Two

/********************************************************************\ *  FILE:     rmd160.h
 *  CONTENTS: Header file for a C implementation of RIPEMD-160 hash-function.
 *  AUTHOR:   Antoon Bosselaers, Dept. Electrical Eng.-ESAT/COSIC
 *  DATE:     1 March 1996       VERSION:  1.0
\********************************************************************/


</p>
#ifndef  RMD160H           /* make sure this file is read only once */
#define  RMD160H


</p>
/********************************************************************/
/* Type definitions of an 8 and a 32-bit integer type, respectively.
 *  Adapt these, if necessary, for your operating system and compiler */
typedef    unsigned char        byte;   /* unsigned 8-bit integer */
typedef    unsigned long        word;   /* unsigned 32-bit integer */


</p>
/****** Macro definitions ******/
/* 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))))


</p>
/* The five basic RIPEMD-160 functions F1(), F2(), F3(), F4(), and F5() */
#define F1(x, y, z)        ((x) ^ (y) ^ (z))
#define F2(x, y, z)        (((x) & (y)) | (~(x) & (z)))
#define F3(x, y, z)        (((x) | ~(y)) ^ (z))
#define F4(x, y, z)        (((x) & (z)) | ((y) & ~(z)))
#define F5(x, y, z)        ((x) ^ ((y) | ~(z)))


</p>
/* The ten basic RIPEMD-160 transformations FF1() through FFF5() */
#define FF1(a, b, c, d, e, x, s)        {\
      (a) += F1((b), (c), (d)) + (x);\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FF2(a, b, c, d, e, x, s)        {\
      (a) += F2((b), (c), (d)) + (x) + 0x5a827999UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FF3(a, b, c, d, e, x, s)        {\
      (a) += F3((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FF4(a, b, c, d, e, x, s)        {\
      (a) += F4((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FF5(a, b, c, d, e, x, s)        {\
      (a) += F5((b), (c), (d)) + (x) + 0xa953fd4eUL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FFF1(a, b, c, d, e, x, s)        {\
      (a) += F1((b), (c), (d)) + (x);\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FFF2(a, b, c, d, e, x, s)        {\
      (a) += F2((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FFF3(a, b, c, d, e, x, s)        {\
      (a) += F3((b), (c), (d)) + (x) + 0x6d703ef3UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FFF4(a, b, c, d, e, x, s)        {\
      (a) += F4((b), (c), (d)) + (x) + 0x5c4dd124UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
#define FFF5(a, b, c, d, e, x, s)        {\
      (a) += F5((b), (c), (d)) + (x) + 0x50a28be6UL;\
      (a) = ROL((a), (s)) + (e);\
      (c) = ROL((c), 10);\
   }
/********************************************************************/
/* Function prototypes */
void MDinit(word *MDbuf);
void MDcompress(word *MDbuf, word *X);
void MDfinish(word *MDbuf, byte *string, word lswlen, word mswlen);


</p>
#endif  /* RMD160H */


</p>
/*********************** end of file rmd160.h ***********************/

Back to Article


Copyright © 1997, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.