class sha1 { public: sha1 () { init (); } void init (); void update (const void *data, unsigned int len); void final (byte digest[20]); protected: static void transform (dword state [5], const byte buffer [64]); dword state [5]; dword count [2]; byte buffer [64]; };
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))/* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #ifndef WORDS_BIGENDIAN # define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF)) #else # define blk0(i) block->l[i] #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1))/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); /* Hash a single 512-bit block. This is the core of the algorithm. */inline void sha1::transform (dword state [5], const byte buffer [64]) { dword a, b, c, d, e; typedef union { byte c [64]; ui32_t l[16]; } CHAR64LONG16; CHAR64LONG16 *block;#ifdef SHA1HANDSOFF static byte workspace[64]; block = (CHAR64LONG16 *) workspace; memcpy (block, buffer, 64); #else block = (CHAR64LONG16 *) buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a, b, c, d, e, 0x00); R0(e, a, b, c, d, 0x01); R0(d, e, a, b, c, 0x02); R0(c, d, e, a, b, 0x03); R0(b, c, d, e, a, 0x04); R0(a, b, c, d, e, 0x05); R0(e, a, b, c, d, 0x06); R0(d, e, a, b, c, 0x07); R0(c, d, e, a, b, 0x08); R0(b, c, d, e, a, 0x09); R0(a, b, c, d, e, 0x0a); R0(e, a, b, c, d, 0x0b); R0(d, e, a, b, c, 0x0c); R0(c, d, e, a, b, 0x0d); R0(b, c, d, e, a, 0x0e); R0(a, b, c, d, e, 0x0f); R1(e, a, b, c, d, 0x10); R1(d, e, a, b, c, 0x11); R1(c, d, e, a, b, 0x12); R1(b, c, d, e, a, 0x13); R2(a, b, c, d, e, 0x14); R2(e, a, b, c, d, 0x15); R2(d, e, a, b, c, 0x16); R2(c, d, e, a, b, 0x17); R2(b, c, d, e, a, 0x18); R2(a, b, c, d, e, 0x19); R2(e, a, b, c, d, 0x1a); R2(d, e, a, b, c, 0x1b); R2(c, d, e, a, b, 0x1c); R2(b, c, d, e, a, 0x1d); R2(a, b, c, d, e, 0x1e); R2(e, a, b, c, d, 0x1f); R2(d, e, a, b, c, 0x20); R2(c, d, e, a, b, 0x21); R2(b, c, d, e, a, 0x22); R2(a, b, c, d, e, 0x23); R2(e, a, b, c, d, 0x24); R2(d, e, a, b, c, 0x25); R2(c, d, e, a, b, 0x26); R2(b, c, d, e, a, 0x27); R3(a, b, c, d, e, 0x28); R3(e, a, b, c, d, 0x29); R3(d, e, a, b, c, 0x2a); R3(c, d, e, a, b, 0x2b); R3(b, c, d, e, a, 0x2c); R3(a, b, c, d, e, 0x2d); R3(e, a, b, c, d, 0x2e); R3(d, e, a, b, c, 0x2f); R3(c, d, e, a, b, 0x30); R3(b, c, d, e, a, 0x31); R3(a, b, c, d, e, 0x32); R3(e, a, b, c, d, 0x33); R3(d, e, a, b, c, 0x34); R3(c, d, e, a, b, 0x35); R3(b, c, d, e, a, 0x36); R3(a, b, c, d, e, 0x37); R3(e, a, b, c, d, 0x38); R3(d, e, a, b, c, 0x39); R3(c, d, e, a, b, 0x3a); R3(b, c, d, e, a, 0x3b); R4(a, b, c, d, e, 0x3c); R4(e, a, b, c, d, 0x3d); R4(d, e, a, b, c, 0x3e); R4(c, d, e, a, b, 0x3f); R4(b, c, d, e, a, 0x40); R4(a, b, c, d, e, 0x41); R4(e, a, b, c, d, 0x42); R4(d, e, a, b, c, 0x43); R4(c, d, e, a, b, 0x44); R4(b, c, d, e, a, 0x45); R4(a, b, c, d, e, 0x46); R4(e, a, b, c, d, 0x47); R4(d, e, a, b, c, 0x48); R4(c, d, e, a, b, 0x49); R4(b, c, d, e, a, 0x4a); R4(a, b, c, d, e, 0x4b); R4(e, a, b, c, d, 0x4c); R4(d, e, a, b, c, 0x4d); R4(c, d, e, a, b, 0x4e); R4(b, c, d, e, a, 0x4f); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* SHA1Init - Initialize new context */void sha1::init () { /* SHA1 initialization constants */ state[0] = 0x67452301; state[1] = 0xEFCDAB89; state[2] = 0x98BADCFE; state[3] = 0x10325476; state[4] = 0xC3D2E1F0; count[0] = count[1] = 0; } /* Run your data through this. */void sha1::update (const void *data, unsigned int len) { unsigned int i, j; j = count[0]; if ((count[0] += len << 3) < j) count[1] += (len >> 29) + 1; j = (j >> 3) & 63; if ((j + len) > 63) { memcpy (&buffer[j], data, (i = 64 - j)); transform (state, buffer); for (; i + 63 < len; i += 64) { transform (state, &((const byte*)data)[i]); } j = 0; } else i = 0; memcpy (&buffer[j], &((const byte *)data)[i], len - i); } /* Add padding and return the message digest. */void sha1::final (unsigned char digest[20]) { unsigned int i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char) ((count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ } update ("\200", 1); while ((count[0] & 504) != 448) { update("\0", 1); } update (finalcount, 8); /* Should cause a SHA1Transform() */ if (digest != NULL) { for (i = 0; i < 20; i++) { digest[i] = (unsigned char) ((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } } #if 0 /* Wipe variables */ i = 0; memset(context->buffer, 0, 64); memset(context->state, 0, 20); memset(context->count, 0, 8); memset(&finalcount, 0, 8); # ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ SHA1Transform(context->state, context->buffer); # endif #endif }
{
public:
sha1 ()
{
init ();
}
void init ();
void update (const void *data, unsigned int len);
void final (byte digest[20]);
protected:
static void transform (dword state [5], const byte buffer [64]); dword state [5];
dword count [2];
byte buffer [64];
};
/* I got the idea of expanding during the round function from SSLeay */
#ifndef WORDS_BIGENDIAN
# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF))
#else
# define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1))/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */inline void sha1::transform (dword state [5], const byte buffer [64])
{
dword a, b, c, d, e;
typedef union
{
byte c [64];
ui32_t l[16];
} CHAR64LONG16; CHAR64LONG16 *block;#ifdef SHA1HANDSOFF
static byte workspace[64]; block = (CHAR64LONG16 *) workspace;
memcpy (block, buffer, 64);
#else
block = (CHAR64LONG16 *) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a, b, c, d, e, 0x00); R0(e, a, b, c, d, 0x01); R0(d, e, a, b, c, 0x02); R0(c, d, e, a, b, 0x03);
R0(b, c, d, e, a, 0x04); R0(a, b, c, d, e, 0x05); R0(e, a, b, c, d, 0x06); R0(d, e, a, b, c, 0x07);
R0(c, d, e, a, b, 0x08); R0(b, c, d, e, a, 0x09); R0(a, b, c, d, e, 0x0a); R0(e, a, b, c, d, 0x0b);
R0(d, e, a, b, c, 0x0c); R0(c, d, e, a, b, 0x0d); R0(b, c, d, e, a, 0x0e); R0(a, b, c, d, e, 0x0f);
R1(e, a, b, c, d, 0x10); R1(d, e, a, b, c, 0x11); R1(c, d, e, a, b, 0x12); R1(b, c, d, e, a, 0x13);
R2(a, b, c, d, e, 0x14); R2(e, a, b, c, d, 0x15); R2(d, e, a, b, c, 0x16); R2(c, d, e, a, b, 0x17);
R2(b, c, d, e, a, 0x18); R2(a, b, c, d, e, 0x19); R2(e, a, b, c, d, 0x1a); R2(d, e, a, b, c, 0x1b);
R2(c, d, e, a, b, 0x1c); R2(b, c, d, e, a, 0x1d); R2(a, b, c, d, e, 0x1e); R2(e, a, b, c, d, 0x1f);
R2(d, e, a, b, c, 0x20); R2(c, d, e, a, b, 0x21); R2(b, c, d, e, a, 0x22); R2(a, b, c, d, e, 0x23);
R2(e, a, b, c, d, 0x24); R2(d, e, a, b, c, 0x25); R2(c, d, e, a, b, 0x26); R2(b, c, d, e, a, 0x27);
R3(a, b, c, d, e, 0x28); R3(e, a, b, c, d, 0x29); R3(d, e, a, b, c, 0x2a); R3(c, d, e, a, b, 0x2b);
R3(b, c, d, e, a, 0x2c); R3(a, b, c, d, e, 0x2d); R3(e, a, b, c, d, 0x2e); R3(d, e, a, b, c, 0x2f);
R3(c, d, e, a, b, 0x30); R3(b, c, d, e, a, 0x31); R3(a, b, c, d, e, 0x32); R3(e, a, b, c, d, 0x33);
R3(d, e, a, b, c, 0x34); R3(c, d, e, a, b, 0x35); R3(b, c, d, e, a, 0x36); R3(a, b, c, d, e, 0x37);
R3(e, a, b, c, d, 0x38); R3(d, e, a, b, c, 0x39); R3(c, d, e, a, b, 0x3a); R3(b, c, d, e, a, 0x3b);
R4(a, b, c, d, e, 0x3c); R4(e, a, b, c, d, 0x3d); R4(d, e, a, b, c, 0x3e); R4(c, d, e, a, b, 0x3f);
R4(b, c, d, e, a, 0x40); R4(a, b, c, d, e, 0x41); R4(e, a, b, c, d, 0x42); R4(d, e, a, b, c, 0x43);
R4(c, d, e, a, b, 0x44); R4(b, c, d, e, a, 0x45); R4(a, b, c, d, e, 0x46); R4(e, a, b, c, d, 0x47);
R4(d, e, a, b, c, 0x48); R4(c, d, e, a, b, 0x49); R4(b, c, d, e, a, 0x4a); R4(a, b, c, d, e, 0x4b);
R4(e, a, b, c, d, 0x4c); R4(d, e, a, b, c, 0x4d); R4(c, d, e, a, b, 0x4e); R4(b, c, d, e, a, 0x4f); /* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */void sha1::init ()
{
/* SHA1 initialization constants */
state[0] = 0x67452301;
state[1] = 0xEFCDAB89;
state[2] = 0x98BADCFE;
state[3] = 0x10325476;
state[4] = 0xC3D2E1F0;
count[0] = count[1] = 0;
}
/* Run your data through this. */void sha1::update (const void *data, unsigned int len)
{
unsigned int i, j; j = count[0];
if ((count[0] += len << 3) < j)
count[1] += (len >> 29) + 1;
j = (j >> 3) & 63;
if ((j + len) > 63)
{
memcpy (&buffer[j], data, (i = 64 - j));
transform (state, buffer);
for (; i + 63 < len; i += 64) {
transform (state, &((const byte*)data)[i]);
}
j = 0;
} else
i = 0;
memcpy (&buffer[j], &((const byte *)data)[i], len - i);
}
/* Add padding and return the message digest. */void sha1::final (unsigned char digest[20])
{
unsigned int i;
unsigned char finalcount[8]; for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char) ((count[(i >= 4 ? 0 : 1)]
>> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
}
update ("\200", 1);
while ((count[0] & 504) != 448) {
update("\0", 1);
}
update (finalcount, 8); /* Should cause a SHA1Transform() */ if (digest != NULL) {
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
}
#if 0
/* Wipe variables */
i = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
# ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
SHA1Transform(context->state, context->buffer);
# endif
#endif
}