📄 pgpsha.c
字号:
PGPByte *buf = (PGPByte *) bufIn;
unsigned i;
/* Update bitcount */
#ifdef HAVE64
i = (unsigned)ctx->bytes % SHA_BLOCKBYTES;
ctx->bytes += len;
#else
PGPUInt32 t = ctx->bytesLo;
if ( ( ctx->bytesLo = t + len ) < t )
ctx->bytesHi++; /* Carry from low to high */
i = (unsigned)t % SHA_BLOCKBYTES; /* Bytes already in ctx->key */
#endif
/* i is always less than SHA_BLOCKBYTES. */
if (SHA_BLOCKBYTES-i > len) {
memcpy((PGPByte *)ctx->key + i, buf, len);
return;
}
if (i) { /* First chunk is an odd size */
memcpy((PGPByte *)ctx->key + i, buf, SHA_BLOCKBYTES - i);
shaByteSwap(ctx->key, (PGPByte *)ctx->key, SHA_BLOCKWORDS);
pgpSHATransform(ctx->iv, ctx->key);
buf += SHA_BLOCKBYTES-i;
len -= SHA_BLOCKBYTES-i;
}
/* Process data in 64-byte chunks */
while (len >= SHA_BLOCKBYTES) {
shaByteSwap(ctx->key, buf, SHA_BLOCKWORDS);
pgpSHATransform(ctx->iv, ctx->key);
buf += SHA_BLOCKBYTES;
len -= SHA_BLOCKBYTES;
}
/* Handle any remaining bytes of data. */
if (len)
memcpy(ctx->key, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
static void const *
shaFinal(void *priv)
{
SHAContext *ctx = (SHAContext *)priv;
PGPByte *digest;
#if HAVE64
unsigned i = (unsigned)ctx->bytes % SHA_BLOCKBYTES;
#else
unsigned i = (unsigned)ctx->bytesLo % SHA_BLOCKBYTES;
#endif
PGPByte *p = (PGPByte *)ctx->key + i; /* First unused byte */
PGPUInt32 t;
/* Set the first char of padding to 0x80. There is always room. */
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes (0..63) */
i = SHA_BLOCKBYTES - 1 - i;
if (i < 8) { /* Padding forces an extra block */
pgpClearMemory( p, i);
shaByteSwap(ctx->key, (PGPByte *)ctx->key, 16);
pgpSHATransform(ctx->iv, ctx->key);
p = (PGPByte *)ctx->key;
i = 64;
}
pgpClearMemory( p, i-8);
shaByteSwap(ctx->key, (PGPByte *)ctx->key, 14);
/* Append length in bits and transform */
#if HAVE64
ctx->key[14] = (PGPUInt32)(ctx->bytes >> 29);
ctx->key[15] = (PGPUInt32)ctx->bytes << 3;
#else
ctx->key[14] = ctx->bytesHi << 3 | ctx->bytesLo >> 29;
ctx->key[15] = ctx->bytesLo << 3;
#endif
pgpSHATransform(ctx->iv, ctx->key);
digest = (PGPByte *)ctx->iv;
for (i = 0; i < SHA_HASHWORDS; i++) {
t = ctx->iv[i];
digest[0] = (PGPByte)(t >> 24);
digest[1] = (PGPByte)(t >> 16);
digest[2] = (PGPByte)(t >> 8);
digest[3] = (PGPByte)t;
digest += 4;
}
/* In case it's sensitive */
/* XXX pgpClearMemory( ctx, sizeof(ctx)); */
return (PGPByte const *)ctx->iv;
}
#if 0
/*
* Nobody knows an SHA format, so we make one up out of the
* context-dependent tag space.
*/
static PGPByte const SHADERprefix[] = {
0x82, /* context-specific [2], primitive */
0x14 /* Length 20 */
/* 20 SHA digest bytes go here */
};
#else
/*
* Actually, there is one. SHA.1 has an OID of 1.3.14.3.2.26
* (From the 1994 Open Systems Environment Implementor's Workshop (OIW))
* The rest of the format is stolen from MD5. Do we need the @#$@$
* NULL in there?
*/
PGPByte const SHADERprefix[] = {
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 */
14,
3,
2,
26,
0x05, /* Universal, Primitive, NULL */
0x00, /* Length 0 */
0x04, /* Universal, Primitive, Octet string */
0x14 /* Length 20 */
/* 20 SHA.1 digest bytes go here */
};
#endif
PGPHashVTBL const HashSHA = {
"SHA1", kPGPHashAlgorithm_SHA,
SHADERprefix, sizeof(SHADERprefix),
SHA_HASHBYTES,
sizeof(SHAContext),
sizeof(struct{char _a; SHAContext _b;}) -
sizeof(SHAContext),
shaInit, shaUpdate, shaFinal
};
#if TESTMAIN
/* ----------------------------- SHA Test code --------------------------- */
#include <stdio.h>
#include <stdlib.h> /* For exit() */
#include <time.h>
/* Size of buffer for SHA speed test data */
#define TEST_BLOCK_SIZE ( SHA_HASHBYTES * 100 )
/* Number of bytes of test data to process */
#define TEST_BYTES 10000000L
#define TEST_BLOCKS ( TEST_BYTES / TEST_BLOCK_SIZE )
#if SHA_VERSION
static char const *shaTestResults[] = {
"A9993E364706816ABA3E25717850C26C9CD0D89D",
"84983E441C3BD26EBAAE4AA1F95129E5E54670F1",
"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F",
"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F",
"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" };
#else
static char const *shaTestResults[] = {
"0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880",
"D2516EE1ACFA5BAF33DFC1C471E438449EF134C8",
"3232AFFA48628A26653B5AAA44541FD90D690603",
"3232AFFA48628A26653B5AAA44541FD90D690603",
"3232AFFA48628A26653B5AAA44541FD90D690603" };
#endif
static int
compareSHAresults(PGPByte const *hash, int level)
{
char buf[41];
int i;
for (i = 0; i < SHA_HASHBYTES; i++)
sprintf(buf+2*i, "%02X", hash[i]);
if (strcmp(buf, shaTestResults[level-1]) == 0) {
printf("Test %d passed, result = %s\n", level, buf);
return 0;
} else {
printf("Error in SHA implementation: Test %d failed\n", level);
printf(" Result = %s\n", buf);
printf("Expected = %s\n", shaTestResults[level-1]);
return -1;
}
}
int
main(void)
{
SHAContext sha;
PGPByte data[TEST_BLOCK_SIZE];
byte const * hash;
clock_t ticks;
long i;
/*
* Test output data (these are the only test data given in the
* Secure Hash Standard document, but chances are if it works
* for this it'll work for anything)
*/
shaInit(&sha);
shaUpdate(&sha, (PGPByte *)"abc", 3);
hash = shaFinal(&sha);
if (compareSHAresults(hash, 1) < 0)
exit (-1);
shaInit(&sha);
shaUpdate(&sha, (PGPByte *)"abcdbcdecdefdefgefghfghighijhijki\
jkljklmklmnlmnomnopnopq", 56);
hash = shaFinal(&sha);
if (compareSHAresults(hash, 2) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 64's */
shaInit(&sha);
for (i = 0; i < 15625; i++)
shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64);
hash = shaFinal(&sha);
if (compareSHAresults(hash, 3) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 25's */
shaInit(&sha);
for (i = 0; i < 40000; i++)
shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa", 25);
shaFinal(&sha, hash);
if (compareSHAresults(hash, 4) < 0)
exit (-1);
/* 1,000,000 bytes of ASCII 'a' (0x61), by 125's */
shaInit(&sha);
for (i = 0; i < 8000; i++)
shaUpdate(&sha, (PGPByte *)"aaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 125);
, hashshaFinal(&sha);
if (compareSHAresults(hash, 5) < 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("SHA time trial. Processing %ld characters...\n", TEST_BYTES);
ticks = clock();
/* Calculate SHA message digest in TEST_BLOCK_SIZE byte blocks */
shaInit(&sha);
for (i = TEST_BLOCKS; i > 0; i--)
shaUpdate(&sha, data, TEST_BLOCK_SIZE);
hash = shaFinal(&sha);
/* 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 + -