📄 pgpripemd160.c
字号:
{
PGPUInt32 i; /* counter */
PGPUInt32 X[16]; /* message words */
pgpClearMemory( X, 16*sizeof(PGPUInt32));
/* 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] ^= (PGPUInt32) *strptr++ << (8 * (i&3));
}
/* append the bit m_n == 1 */
X[(lswlen>>2)&15] ^= (PGPUInt32)1 << (8*(lswlen&3) + 7);
if ((lswlen & 63) > 55) {
/* length goes to next block */
RMDcompress(MDbuf, X);
pgpClearMemory( X, 16*sizeof(PGPUInt32));
}
/* append length in bits*/
X[14] = lswlen << 3;
X[15] = (lswlen >> 29) | (mswlen << 3);
RMDcompress(MDbuf, X);
return;
}
/************************ end of file rmd160.c **********************/
/* Remainder provides common interface used by PGP library */
/*
* Shuffle the bytes into little-endian order within 32-bit words,
* as per the RIPEMD-160 spec (which follows MD4 conventions).
*/
static void
rmd160ByteSwap(PGPUInt32 *dest, PGPByte const *src, unsigned words)
{
do {
*dest++ = (PGPUInt32)((unsigned)src[3] << 8 | src[2]) << 16 |
((unsigned)src[1] << 8 | src[0]);
src += 4;
} while (--words);
}
/* Initialize the RIPEMD-160 values */
static void
rmd160Init(void *priv)
{
struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
/* Set the h-vars to their initial values */
RMDinit (ctx->iv);
/* Initialise bit count */
ctx->bytesHi = 0;
ctx->bytesLo = 0;
}
/* Update the RIPEMD-160 hash state for a block of data. */
static void
rmd160Update(void *priv, void const *bufIn, PGPSize len)
{
struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
unsigned i;
PGPByte *buf = (PGPByte *) bufIn;
/* Update bitcount */
PGPUInt32 t = ctx->bytesLo;
if ( ( ctx->bytesLo = t + len ) < t )
ctx->bytesHi++; /* Carry from low to high */
i = (unsigned)t % RIPEMD160_BLOCKBYTES; /* bytes already in ctx->key */
/* i is always less than RIPEMD160_BLOCKBYTES. */
if (RIPEMD160_BLOCKBYTES-i > len) {
pgpCopyMemory(buf, (PGPByte *)ctx->key + i, len);
return;
}
if (i) { /* First chunk is an odd size */
pgpCopyMemory(buf, (PGPByte *)ctx->key + i, RIPEMD160_BLOCKBYTES - i);
rmd160ByteSwap(ctx->key, (PGPByte *)ctx->key, RIPEMD160_BLOCKWORDS);
RMDcompress(ctx->iv, ctx->key);
buf += RIPEMD160_BLOCKBYTES-i;
len -= RIPEMD160_BLOCKBYTES-i;
}
/* Process data in 64-byte chunks */
while (len >= RIPEMD160_BLOCKBYTES) {
rmd160ByteSwap(ctx->key, buf, RIPEMD160_BLOCKWORDS);
RMDcompress(ctx->iv, ctx->key);
buf += RIPEMD160_BLOCKBYTES;
len -= RIPEMD160_BLOCKBYTES;
}
/* Handle any remaining bytes of data. */
if (len)
pgpCopyMemory(buf, ctx->key, len);
}
/* Final wrapup - MD4 style padding on last block. */
static void const *
rmd160Final(void *priv)
{
struct RIPEMD160Context *ctx = (struct RIPEMD160Context *)priv;
PGPByte *digest;
int i;
PGPUInt32 t;
RMDfinish(ctx->iv, (PGPByte *)ctx->key, ctx->bytesLo, ctx->bytesHi);
digest = (PGPByte *)ctx->iv;
for (i = 0; i < RIPEMD160_HASHWORDS; i++) {
t = ctx->iv[i];
digest[0] = (PGPByte)t;
digest[1] = (PGPByte)(t >> 8);
digest[2] = (PGPByte)(t >> 16);
digest[3] = (PGPByte)(t >> 24);
digest += 4;
}
/* In case it's sensitive */
/* XXX pgpClearMemory( ctx, sizeof(ctx)); */
return (PGPByte const *)ctx->iv;
}
/*
* RIPEM OID is 1.3.36.3.2.1, from URL above.
* The rest of the format is stolen from MD5. Do we need the NULL
* in there?
*/
static PGPByte const RIPEMD160DERprefix[] = {
0x30, /* Universal, Constructed, Sequence */
0x21, /* Length 33 (bytes following) */
0x30, /* Universal, Constructed, Sequence */
0x09, /* Length 9 */
0x06, /* Universal, Primitive, object-identifier */
0x05, /* Length 8 */
43, /* 43 = ISO(1)*40 + 3 */
36,
3,
2,
1,
0x05, /* Universal, Primitive, NULL */
0x00, /* Length 0 */
0x04, /* Universal, Primitive, Octet string */
0x14 /* Length 20 */
/* 20 RIPEMD-160 digest bytes go here */
};
struct PGPHashVTBL const HashRIPEMD160 = {
"RIPEMD160", kPGPHashAlgorithm_RIPEMD160,
RIPEMD160DERprefix, sizeof(RIPEMD160DERprefix),
RIPEMD160_HASHBYTES,
sizeof(struct RIPEMD160Context),
sizeof(struct{char _a; struct RIPEMD160Context _b;}) -
sizeof(struct RIPEMD160Context),
rmd160Init, rmd160Update, rmd160Final
};
#if TESTMAIN
/* --------------------------- RMD160 Test code --------------------------- */
#include <stdio.h>
#include <stdlib.h> /* For exit() */
#include <time.h>
/* Size of buffer for RMD160 speed test data */
#define TEST_BLOCK_SIZE ( RIPEMD160_HASHBYTES * 100 )
/* Number of bytes of test data to process */
#define TEST_BYTES 10000000L
#define TEST_BLOCKS ( TEST_BYTES / TEST_BLOCK_SIZE )
static char const *rmd160TestResults[] = {
"9C1185A5C5E9FC54612808977EE8F548B2258D31", /* "" */
"0BDC9D2D256B3EE9DAAE347BE6F4DC835A467FFE", /* "a" */
"8EB208F7E05D987A9B044A8E98C6B087F15A0BFC", /* "abc" */
"5D0689EF49D2FAE572B881B123A85FFA21595F36", /* "message digest" */
"F71C27109C692C1B56BBDCEB5B9D2865B3708DBC", /* "a..z" */
"12A053384A9C0C88E405A06C27DCF49ADA62EB2B", /* "abcdbcde...nopq" */
"B0E20B6E3116640286ED3A87A5713079B21F5189", /* "A..Za..z0..9" */
"9B752E45573D4B39F4DBD3323CAB82BF63326BFB", /* 8 * "1234567890" */
"52783243C1697BDBE16D37F97F68F08325DC1528", /* 1,000,000 "a" */
"52783243C1697BDBE16D37F97F68F08325DC1528", /* 1,000,000 "a" */
"52783243C1697BDBE16D37F97F68F08325DC1528" }; /* 1,000,000 "a" */
static int
compareRMD160results(PGPByte const *hash, int level)
{
char buf[41];
int i;
for (i = 0; i < RIPEMD160_HASHBYTES; i++)
sprintf(buf+2*i, "%02X", hash[i]);
if (strcmp(buf, rmd160TestResults[level-1]) == 0) {
printf("Test %d passed, result = %s\n", level, buf);
return 0;
} else {
printf("Error in RMD160 implementation: Test %d failed\n", level);
printf(" Result = %s\n", buf);
printf("Expected = %s\n", rmd160TestResults[level-1]);
return -1;
}
}
int
main(void)
{
struct RIPEMD160Context rmd160;
PGPByte data[TEST_BLOCK_SIZE];
PGPByte const *hash;
clock_t ticks;
long i;
/*
* Test output data, based on URL above.
*/
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"", 0);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 1) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"a", 1);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 2) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"abc", 3);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 3) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"message digest", 14);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 4) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"abcdefghijklmnopqrstuvwxyz", 26);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 5) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"abcdbcdecdefdefgefghfghighijhijkijkl\
jklmklmnlmnomnopnopq", 56);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 6) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
abcdefghijklmnopqrstuvwxyz0123456789", 62);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 7) < 0)
exit (-1);
rmd160Init(&rmd160);
rmd160Update(&rmd160, (PGPByte *)"123456789012345678901234567890\
12345678901234567890123456789012345678901234567890", 80);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 8) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 64's */
rmd160Init(&rmd160);
for (i = 0; i < 15625; i++)
rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 9) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 25's */
rmd160Init(&rmd160);
for (i = 0; i < 40000; i++)
rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 10) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 125's */
rmd160Init(&rmd160);
for (i = 0; i < 8000; i++)
rmd160Update(&rmd160, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125);
hash = rmd160Final(&rmd160);
if (compareRMD160results(hash, 11) < 0)
exit (-1);
/* Now perform time trial, generating MD for 10MB of data. First,
initialize the test data */
pgpClearMemory( data, TEST_BLOCK_SIZE);
/* Get start time */
printf("RMD160 time trial. Processing %ld characters...\n", TEST_BYTES);
ticks = clock();
/* Calculate RMD160 message digest in TEST_BLOCK_SIZE byte blocks */
rmd160Init(&rmd160);
for (i = TEST_BLOCKS; i > 0; i--)
rmd160Update(&rmd160, data, TEST_BLOCK_SIZE);
hash = rmd160Final(&rmd160);
/* Get finish time and print difference */
ticks = clock() - ticks;
printf("Ticks to process test input: %lu\n", (unsigned long)ticks);
return 0;
}
#endif /* Test driver */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -