Cryptography-Digest Digest #324, Volume #12 Tue, 1 Aug 00 05:13:01 EDT
Contents:
ripemd-160 implementation (Nikos Mavroyanopoulos)
----------------------------------------------------------------------------
From: Nikos Mavroyanopoulos <[EMAIL PROTECTED]>
Subject: ripemd-160 implementation
Date: Tue, 01 Aug 2000 11:31:18 -0700
This is a multi-part message in MIME format.
==============19064D558B29AC16701DEAC4
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
I attach a ripemd-160 implementation based on a public domain sha-1
implementation. This is the same code used in mhash library.
--
Nikos Mavroyanopoulos
==============19064D558B29AC16701DEAC4
Content-Type: text/plain; charset=iso-8859-1;
name="ripemd.c"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
filename="ripemd.c"
/* ripemd.c - Implementation of the RIPE-MD Hash Algorithm
*
* Copyright (C) 2000, Nikos Mavroyanopoulos
* This implementation is placed under the public domain.
*
* Based on the SHA-1 implementation by A.M. Kuchling
*
* Here are the quotes of the original SHA-1 implementation:
*/
/* Copyright (C) 1995, A.M. Kuchling
* Adapted to pike and some cleanup by Niels Möller.
*
* Based on SHA code originally posted to sci.crypt by Peter Gutmann
* in message <30ajo5$[EMAIL PROTECTED]>.
* Modified to test for endianness on creation of SHA objects by AMK.
* Also, the original specification of SHA was found to have a weakness
* by NSA/NIST. This code implements the fixed version of SHA.
*/
/* The RIPEMD block size and message digest sizes, in bytes */
#define RIPEMD_DATASIZE 64
#define RIPEMD_DATALEN 16
#define RIPEMD_DIGESTSIZE 20
#define RIPEMD_DIGESTLEN 5
/* The structure for storing RIPEMD info */
typedef struct ripemd_ctx {
word32 digest[RIPEMD_DIGESTLEN]; /* Message digest */
word32 count_l, count_h; /* 64-bit block count */
word8 block[RIPEMD_DATASIZE]; /* RIPEMD data buffer */
int index; /* index into buffer */
} RIPEMD_CTX;
void ripemd_init(struct ripemd_ctx *ctx);
void ripemd_update(struct ripemd_ctx *ctx, word8 *buffer, word32 len);
void ripemd_final(struct ripemd_ctx *ctx);
void ripemd_digest(struct ripemd_ctx *ctx, word8 *s);
void ripemd_copy(struct ripemd_ctx *dest, struct ripemd_ctx *src);
/* 32-bit rotate left - kludged with shifts */
#define ROTL(n,X) (((X)<<(n))|((X)>>(32-(n))))
#define f0(x,y,z) (x^y^z)
#define f16(x,y,z) ((x&y)|((~x) & z))
#define f32(x,y,z) ((x|~(y))^z)
#define f48(x,y,z) ((x&z)|(y&(~z)))
#define f64(x,y,z) (x^(y|(~z)))
#define K0 0x00000000
#define K1 0x5A827999
#define K2 0x6ED9EBA1
#define K3 0x8F1BBCDC
#define K4 0xA953FD4E
#define KK0 0x50A28BE6
#define KK1 0x5C4DD124
#define KK2 0x6D703EF3
#define KK3 0x7A6D76E9
#define KK4 0x00000000
#define h0init 0x67452301
#define h1init 0xEFCDAB89
#define h2init 0x98BADCFE
#define h3init 0x10325476
#define h4init 0xC3D2E1F0
void ripemd_copy(struct ripemd_ctx *dest, struct ripemd_ctx *src)
{
int i;
dest->count_l = src->count_l;
dest->count_h = src->count_h;
for (i = 0; i < RIPEMD_DIGESTLEN; i++)
dest->digest[i] = src->digest[i];
for (i = 0; i < src->index; i++)
dest->block[i] = src->block[i];
dest->index = src->index;
}
/* Initialize the RIPEMD values */
void ripemd_init(struct ripemd_ctx *ctx)
{
/* Set the h-vars to their initial values */
ctx->digest[0] = h0init;
ctx->digest[1] = h1init;
ctx->digest[2] = h2init;
ctx->digest[3] = h3init;
ctx->digest[4] = h4init;
/* Initialize bit count */
ctx->count_l = ctx->count_h = 0;
/* Initialize buffer */
ctx->index = 0;
}
#define subRound(a, b, c, d, e, f, k, r, data) \
( a = ROTL( r, a + f(b,c,d) + data + k) + e, c = ROTL(10, c) )
static void ripemd_transform(struct ripemd_ctx *ctx, word32 * data)
{
word32 A, B, C, D, E; /* Local vars */
word32 AA, BB, CC, DD, EE; /* Local vars */
word32 T, t;
/* Set up first buffer and local data buffer */
A = ctx->digest[0];
B = ctx->digest[1];
C = ctx->digest[2];
D = ctx->digest[3];
E = ctx->digest[4];
/* j=0...15 */
subRound(A, B, C, D, E, f0, K0, 11, data[0]);
subRound(E, A, B, C, D, f0, K0, 14, data[1]);
subRound(D, E, A, B, C, f0, K0, 15, data[2]);
subRound(C, D, E, A, B, f0, K0, 12, data[3]);
subRound(B, C, D, E, A, f0, K0, 5, data[4]);
subRound(A, B, C, D, E, f0, K0, 8, data[5]);
subRound(E, A, B, C, D, f0, K0, 7, data[6]);
subRound(D, E, A, B, C, f0, K0, 9, data[7]);
subRound(C, D, E, A, B, f0, K0, 11, data[8]);
subRound(B, C, D, E, A, f0, K0, 13, data[9]);
subRound(A, B, C, D, E, f0, K0, 14, data[10]);
subRound(E, A, B, C, D, f0, K0, 15, data[11]);
subRound(D, E, A, B, C, f0, K0, 6, data[12]);
subRound(C, D, E, A, B, f0, K0, 7, data[13]);
subRound(B, C, D, E, A, f0, K0, 9, data[14]);
subRound(A, B, C, D, E, f0, K0, 8, data[15]);
/* j=16...31 */
subRound(E, A, B, C, D, f16, K1, 7, data[7]);
subRound(D, E, A, B, C, f16, K1, 6, data[4]);
subRound(C, D, E, A, B, f16, K1, 8, data[13]);
subRound(B, C, D, E, A, f16, K1, 13, data[1]);
subRound(A, B, C, D, E, f16, K1, 11, data[10]);
subRound(E, A, B, C, D, f16, K1, 9, data[6]);
subRound(D, E, A, B, C, f16, K1, 7, data[15]);
subRound(C, D, E, A, B, f16, K1, 15, data[3]);
subRound(B, C, D, E, A, f16, K1, 7, data[12]);
subRound(A, B, C, D, E, f16, K1, 12, data[0]);
subRound(E, A, B, C, D, f16, K1, 15, data[9]);
subRound(D, E, A, B, C, f16, K1, 9, data[5]);
subRound(C, D, E, A, B, f16, K1, 11, data[2]);
subRound(B, C, D, E, A, f16, K1, 7, data[14]);
subRound(A, B, C, D, E, f16, K1, 13, data[11]);
subRound(E, A, B, C, D, f16, K1, 12, data[8]);
/* j=32...47 */
subRound(D, E, A, B, C, f32, K2, 11, data[3]);
subRound(C, D, E, A, B, f32, K2, 13, data[10]);
subRound(B, C, D, E, A, f32, K2, 6, data[14]);
subRound(A, B, C, D, E, f32, K2, 7, data[4]);
subRound(E, A, B, C, D, f32, K2, 14, data[9]);
subRound(D, E, A, B, C, f32, K2, 9, data[15]);
subRound(C, D, E, A, B, f32, K2, 13, data[8]);
subRound(B, C, D, E, A, f32, K2, 15, data[1]);
subRound(A, B, C, D, E, f32, K2, 14, data[2]);
subRound(E, A, B, C, D, f32, K2, 8, data[7]);
subRound(D, E, A, B, C, f32, K2, 13, data[0]);
subRound(C, D, E, A, B, f32, K2, 6, data[6]);
subRound(B, C, D, E, A, f32, K2, 5, data[13]);
subRound(A, B, C, D, E, f32, K2, 12, data[11]);
subRound(E, A, B, C, D, f32, K2, 7, data[5]);
subRound(D, E, A, B, C, f32, K2, 5, data[12]);
/* j=48...63 */
subRound(C, D, E, A, B, f48, K3, 11, data[1]);
subRound(B, C, D, E, A, f48, K3, 12, data[9]);
subRound(A, B, C, D, E, f48, K3, 14, data[11]);
subRound(E, A, B, C, D, f48, K3, 15, data[10]);
subRound(D, E, A, B, C, f48, K3, 14, data[0]);
subRound(C, D, E, A, B, f48, K3, 15, data[8]);
subRound(B, C, D, E, A, f48, K3, 9, data[12]);
subRound(A, B, C, D, E, f48, K3, 8, data[4]);
subRound(E, A, B, C, D, f48, K3, 9, data[13]);
subRound(D, E, A, B, C, f48, K3, 14, data[3]);
subRound(C, D, E, A, B, f48, K3, 5, data[7]);
subRound(B, C, D, E, A, f48, K3, 6, data[15]);
subRound(A, B, C, D, E, f48, K3, 8, data[14]);
subRound(E, A, B, C, D, f48, K3, 6, data[5]);
subRound(D, E, A, B, C, f48, K3, 5, data[6]);
subRound(C, D, E, A, B, f48, K3, 12, data[2]);
/* j=64...79 */
subRound(B, C, D, E, A, f64, K4, 9, data[4]);
subRound(A, B, C, D, E, f64, K4, 15, data[0]);
subRound(E, A, B, C, D, f64, K4, 5, data[5]);
subRound(D, E, A, B, C, f64, K4, 11, data[9]);
subRound(C, D, E, A, B, f64, K4, 6, data[7]);
subRound(B, C, D, E, A, f64, K4, 8, data[12]);
subRound(A, B, C, D, E, f64, K4, 13, data[2]);
subRound(E, A, B, C, D, f64, K4, 12, data[10]);
subRound(D, E, A, B, C, f64, K4, 5, data[14]);
subRound(C, D, E, A, B, f64, K4, 12, data[1]);
subRound(B, C, D, E, A, f64, K4, 13, data[3]);
subRound(A, B, C, D, E, f64, K4, 14, data[8]);
subRound(E, A, B, C, D, f64, K4, 11, data[11]);
subRound(D, E, A, B, C, f64, K4, 8, data[6]);
subRound(C, D, E, A, B, f64, K4, 5, data[15]);
subRound(B, C, D, E, A, f64, K4, 6, data[13]);
AA = A;
BB = B;
CC = C;
DD = D;
EE = E;
/* ' */
A = ctx->digest[0];
B = ctx->digest[1];
C = ctx->digest[2];
D = ctx->digest[3];
E = ctx->digest[4];
/* j=0...15 */
subRound(A, B, C, D, E, f64, KK0, 8, data[5]);
subRound(E, A, B, C, D, f64, KK0, 9, data[14]);
subRound(D, E, A, B, C, f64, KK0, 9, data[7]);
subRound(C, D, E, A, B, f64, KK0, 11, data[0]);
subRound(B, C, D, E, A, f64, KK0, 13, data[9]);
subRound(A, B, C, D, E, f64, KK0, 15, data[2]);
subRound(E, A, B, C, D, f64, KK0, 15, data[11]);
subRound(D, E, A, B, C, f64, KK0, 5, data[4]);
subRound(C, D, E, A, B, f64, KK0, 7, data[13]);
subRound(B, C, D, E, A, f64, KK0, 7, data[6]);
subRound(A, B, C, D, E, f64, KK0, 8, data[15]);
subRound(E, A, B, C, D, f64, KK0, 11, data[8]);
subRound(D, E, A, B, C, f64, KK0, 14, data[1]);
subRound(C, D, E, A, B, f64, KK0, 14, data[10]);
subRound(B, C, D, E, A, f64, KK0, 12, data[3]);
subRound(A, B, C, D, E, f64, KK0, 6, data[12]);
/* j=16...31 */
subRound(E, A, B, C, D, f48, KK1, 9, data[6]);
subRound(D, E, A, B, C, f48, KK1, 13, data[11]);
subRound(C, D, E, A, B, f48, KK1, 15, data[3]);
subRound(B, C, D, E, A, f48, KK1, 7, data[7]);
subRound(A, B, C, D, E, f48, KK1, 12, data[0]);
subRound(E, A, B, C, D, f48, KK1, 8, data[13]);
subRound(D, E, A, B, C, f48, KK1, 9, data[5]);
subRound(C, D, E, A, B, f48, KK1, 11, data[10]);
subRound(B, C, D, E, A, f48, KK1, 7, data[14]);
subRound(A, B, C, D, E, f48, KK1, 7, data[15]);
subRound(E, A, B, C, D, f48, KK1, 12, data[8]);
subRound(D, E, A, B, C, f48, KK1, 7, data[12]);
subRound(C, D, E, A, B, f48, KK1, 6, data[4]);
subRound(B, C, D, E, A, f48, KK1, 15, data[9]);
subRound(A, B, C, D, E, f48, KK1, 13, data[1]);
subRound(E, A, B, C, D, f48, KK1, 11, data[2]);
/* j=32...47 */
subRound(D, E, A, B, C, f32, KK2, 9, data[15]);
subRound(C, D, E, A, B, f32, KK2, 7, data[5]);
subRound(B, C, D, E, A, f32, KK2, 15, data[1]);
subRound(A, B, C, D, E, f32, KK2, 11, data[3]);
subRound(E, A, B, C, D, f32, KK2, 8, data[7]);
subRound(D, E, A, B, C, f32, KK2, 6, data[14]);
subRound(C, D, E, A, B, f32, KK2, 6, data[6]);
subRound(B, C, D, E, A, f32, KK2, 14, data[9]);
subRound(A, B, C, D, E, f32, KK2, 12, data[11]);
subRound(E, A, B, C, D, f32, KK2, 13, data[8]);
subRound(D, E, A, B, C, f32, KK2, 5, data[12]);
subRound(C, D, E, A, B, f32, KK2, 14, data[2]);
subRound(B, C, D, E, A, f32, KK2, 13, data[10]);
subRound(A, B, C, D, E, f32, KK2, 13, data[0]);
subRound(E, A, B, C, D, f32, KK2, 7, data[4]);
subRound(D, E, A, B, C, f32, KK2, 5, data[13]);
/* j=48...63 */
subRound(C, D, E, A, B, f16, KK3, 15, data[8]);
subRound(B, C, D, E, A, f16, KK3, 5, data[6]);
subRound(A, B, C, D, E, f16, KK3, 8, data[4]);
subRound(E, A, B, C, D, f16, KK3, 11, data[1]);
subRound(D, E, A, B, C, f16, KK3, 14, data[3]);
subRound(C, D, E, A, B, f16, KK3, 14, data[11]);
subRound(B, C, D, E, A, f16, KK3, 6, data[15]);
subRound(A, B, C, D, E, f16, KK3, 14, data[0]);
subRound(E, A, B, C, D, f16, KK3, 6, data[5]);
subRound(D, E, A, B, C, f16, KK3, 9, data[12]);
subRound(C, D, E, A, B, f16, KK3, 12, data[2]);
subRound(B, C, D, E, A, f16, KK3, 9, data[13]);
subRound(A, B, C, D, E, f16, KK3, 12, data[9]);
subRound(E, A, B, C, D, f16, KK3, 5, data[7]);
subRound(D, E, A, B, C, f16, KK3, 15, data[10]);
subRound(C, D, E, A, B, f16, KK3, 8, data[14]);
/* j=64...79 */
subRound(B, C, D, E, A, f0, KK4, 8, data[12]);
subRound(A, B, C, D, E, f0, KK4, 5, data[15]);
subRound(E, A, B, C, D, f0, KK4, 12, data[10]);
subRound(D, E, A, B, C, f0, KK4, 9, data[4]);
subRound(C, D, E, A, B, f0, KK4, 12, data[1]);
subRound(B, C, D, E, A, f0, KK4, 5, data[5]);
subRound(A, B, C, D, E, f0, KK4, 14, data[8]);
subRound(E, A, B, C, D, f0, KK4, 6, data[7]);
subRound(D, E, A, B, C, f0, KK4, 8, data[6]);
subRound(C, D, E, A, B, f0, KK4, 13, data[2]);
subRound(B, C, D, E, A, f0, KK4, 6, data[13]);
subRound(A, B, C, D, E, f0, KK4, 5, data[14]);
subRound(E, A, B, C, D, f0, KK4, 15, data[0]);
subRound(D, E, A, B, C, f0, KK4, 13, data[3]);
subRound(C, D, E, A, B, f0, KK4, 11, data[9]);
subRound(B, C, D, E, A, f0, KK4, 11, data[11]);
T = ctx->digest[1] + D + CC;
ctx->digest[1] = ctx->digest[2] + E + DD;
ctx->digest[2] = ctx->digest[3] + A + EE;
ctx->digest[3] = ctx->digest[4] + B + AA;
ctx->digest[4] = ctx->digest[0] + C + BB;
ctx->digest[0] = T;
}
#if 1
#ifndef EXTRACT_UCHAR
#define EXTRACT_UCHAR(p) (*(word8 *)(p))
#endif
#define STRING2INT(s) ((((((EXTRACT_UCHAR(s+3) << 8) \
| EXTRACT_UCHAR(s+2)) << 8) \
| EXTRACT_UCHAR(s+1)) << 8) \
| EXTRACT_UCHAR(s))
#else
word32 STRING2INT(word8 * s)
{
word32 r;
int i;
for (i = 0, r = 0; i < 4; i++)
r = (r << 8) | s[3-i];
return r;
}
#endif
static void ripemd_block(struct ripemd_ctx *ctx, word8 * block)
{
word32 data[RIPEMD_DATALEN];
int i;
/* Update block count */
if (!++ctx->count_l)
++ctx->count_h;
/* Endian independent conversion */
for (i = 0; i < RIPEMD_DATALEN; i++, block += 4)
data[i] = STRING2INT(block);
ripemd_transform(ctx, data);
}
void ripemd_update(struct ripemd_ctx *ctx, word8 * buffer, word32 len)
{
if (ctx->index) { /* Try to fill partial block */
unsigned left = RIPEMD_DATASIZE - ctx->index;
if (len < left) {
memmove(ctx->block + ctx->index, buffer, len);
ctx->index += len;
return; /* Finished */
} else {
memmove(ctx->block + ctx->index, buffer, left);
ripemd_block(ctx, ctx->block);
buffer += left;
len -= left;
}
}
while (len >= RIPEMD_DATASIZE) {
ripemd_block(ctx, buffer);
buffer += RIPEMD_DATASIZE;
len -= RIPEMD_DATASIZE;
}
if ((ctx->index = len))
/* This assignment is intended */
/* Buffer leftovers */
memmove(ctx->block, buffer, len);
}
/* Final wrapup - pad to RIPEMD_DATASIZE-byte boundary with the bit pattern
1 0* (64-bit count of bits processed, MSB-first) */
void ripemd_final(struct ripemd_ctx *ctx)
{
word32 data[RIPEMD_DATALEN];
int i;
int words;
i = ctx->index;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
ctx->block[i++] = 0x80;
/* Fill rest of word */
for (; i & 3; i++)
ctx->block[i] = 0;
/* i is now a multiple of the word size 4 */
words = i >> 2;
for (i = 0; i < words; i++)
data[i] = STRING2INT(ctx->block + 4 * i);
if (words > (RIPEMD_DATALEN - 2)) { /* No room for length in this block.
Process it and
* pad with another one */
for (i = words; i < RIPEMD_DATALEN; i++)
data[i] = 0;
ripemd_transform(ctx, data);
for (i = 0; i < (RIPEMD_DATALEN - 2); i++)
data[i] = 0;
} else
for (i = words; i < RIPEMD_DATALEN - 2; i++)
data[i] = 0;
/* Theres 512 = 2^9 bits in one block */
data[RIPEMD_DATALEN - 1] =
(ctx->count_h << 9) | (ctx->count_l >> 23);
data[RIPEMD_DATALEN - 2] = (ctx->count_l << 9) | (ctx->index << 3);
ripemd_transform(ctx, data);
}
void ripemd_digest(struct ripemd_ctx *ctx, word8 * s)
{
int i;
for (i = 0; i < RIPEMD_DIGESTLEN; i++) {
*s++ = ctx->digest[i];
*s++ = 0xff & (ctx->digest[i] >> 8);
*s++ = 0xff & (ctx->digest[i] >> 16);
*s++ = 0xff & ctx->digest[i] >> 24;
}
}
==============19064D558B29AC16701DEAC4==
------------------------------
** FOR YOUR REFERENCE **
The service address, to which questions about the list itself and requests
to be added to or deleted from it should be directed, is:
Internet: [EMAIL PROTECTED]
You can send mail to the entire list (and sci.crypt) via:
Internet: [EMAIL PROTECTED]
End of Cryptography-Digest Digest
******************************