G
gkoreman
I am trying to implement SHA1 based on the pseudo-code on Wikipedia.
The pseudo-code is on:
http://en.wikipedia.org/wiki/SHA-1
My code is working, but is not giving me the correct hashes.
This is being tested (initially) on a big-endian machine, and only
after I have it working on big-endian was I planning on making it work
on both big and little endian.
#include <stdio.h>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
typedef unsigned int word32;
class SHA1Hash
{
private:
void Process(std::vector<word32>& message)
{
// Pre-processing:
// 1. append a single "1" bit to message
// 2. append "0" bits until message length = 490 = -32
(mod 512)
// 3. append length of message (before pre-processing),
in bits as 32-bit big-endian integer to message
word32 messageLength = message.size() * 32;
// Step 1
word32 padding = 0x8000000; // 1000 0000 0000 0000
message.push_back(padding);
// Step 2
padding = 0;
while( (message.size() % 16) != 15 )
message.push_back(padding);
// Step 3
message.push_back(messageLength);
//
// Actual Hash Code
//
unsigned int chunkIndex = 0;
//Initialize variables:
h0 = 0x67452301;
h1 = 0xEFCDAB89;
h2 = 0x98BADCFE;
h3 = 0x10325476;
h4 = 0xC3D2E1F0;
// break message into 512-bit chunks
while( chunkIndex < message.size() )
{
// break chunk into sixteen 32-bit words w(i),
0 = i = 15
vector<word32> w(80, 0);
for( unsigned int i = 0; i < 16; i++ )
w = message[chunkIndex + i];
for( unsigned int i = 16; i < 80; i++ )
w = ROTL( 1, (w[i-3] ^ w[i-8] ^
w[i-14] ^ w[i-16]));
word32 a = h0;
word32 b = h1;
word32 c = h2;
word32 d = h3;
word32 e = h4;
for( unsigned int i = 0; i < 80; i++ )
{
word32 f = 0;
word32 k = 0;
if( i < 20 )
{
f = (b & c) | ((~b) & d);
k = 0x5A827999;
}
else if( i < 40 )
{
f = b ^ c ^ d;
k = 0x6ED9EBA1;
}
else if( i < 60 )
{
f = (b & c) | (b & d) | (c &
d);
k = 0x8F1BBCDC;
}
else if( i < 80 )
{
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
word32 temp = ROTL(5, a) + f + e + k +
w;
e = d;
d = c;
c = ROTL(30, b);
b = a;
a = temp;
}
// Add this chunk's hash to result so far:
h0 = h0 + a;
h1 = h1 + b;
h2 = h2 + c;
h3 = h3 + d;
h4 = h4 + e;
chunkIndex+=16;
}
}
... a public function that calls process
I have tried it with an empty vector and get
5bc0ce0 b2008157 3de49bed 97b3e936 af3f86ce
This is what I should get:
da39a3ee5e6b4b0d3255bfef95601890afd80709
I have looked through this for hours now and can't see anything wrong
with it. Can anyone give me a hand?
btw, this is NOT homework, this is a personal project.
Thanks
The pseudo-code is on:
http://en.wikipedia.org/wiki/SHA-1
My code is working, but is not giving me the correct hashes.
This is being tested (initially) on a big-endian machine, and only
after I have it working on big-endian was I planning on making it work
on both big and little endian.
#include <stdio.h>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
typedef unsigned int word32;
class SHA1Hash
{
private:
void Process(std::vector<word32>& message)
{
// Pre-processing:
// 1. append a single "1" bit to message
// 2. append "0" bits until message length = 490 = -32
(mod 512)
// 3. append length of message (before pre-processing),
in bits as 32-bit big-endian integer to message
word32 messageLength = message.size() * 32;
// Step 1
word32 padding = 0x8000000; // 1000 0000 0000 0000
message.push_back(padding);
// Step 2
padding = 0;
while( (message.size() % 16) != 15 )
message.push_back(padding);
// Step 3
message.push_back(messageLength);
//
// Actual Hash Code
//
unsigned int chunkIndex = 0;
//Initialize variables:
h0 = 0x67452301;
h1 = 0xEFCDAB89;
h2 = 0x98BADCFE;
h3 = 0x10325476;
h4 = 0xC3D2E1F0;
// break message into 512-bit chunks
while( chunkIndex < message.size() )
{
// break chunk into sixteen 32-bit words w(i),
0 = i = 15
vector<word32> w(80, 0);
for( unsigned int i = 0; i < 16; i++ )
w = message[chunkIndex + i];
for( unsigned int i = 16; i < 80; i++ )
w = ROTL( 1, (w[i-3] ^ w[i-8] ^
w[i-14] ^ w[i-16]));
word32 a = h0;
word32 b = h1;
word32 c = h2;
word32 d = h3;
word32 e = h4;
for( unsigned int i = 0; i < 80; i++ )
{
word32 f = 0;
word32 k = 0;
if( i < 20 )
{
f = (b & c) | ((~b) & d);
k = 0x5A827999;
}
else if( i < 40 )
{
f = b ^ c ^ d;
k = 0x6ED9EBA1;
}
else if( i < 60 )
{
f = (b & c) | (b & d) | (c &
d);
k = 0x8F1BBCDC;
}
else if( i < 80 )
{
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
word32 temp = ROTL(5, a) + f + e + k +
w;
e = d;
d = c;
c = ROTL(30, b);
b = a;
a = temp;
}
// Add this chunk's hash to result so far:
h0 = h0 + a;
h1 = h1 + b;
h2 = h2 + c;
h3 = h3 + d;
h4 = h4 + e;
chunkIndex+=16;
}
}
... a public function that calls process
I have tried it with an empty vector and get
5bc0ce0 b2008157 3de49bed 97b3e936 af3f86ce
This is what I should get:
da39a3ee5e6b4b0d3255bfef95601890afd80709
I have looked through this for hours now and can't see anything wrong
with it. Can anyone give me a hand?
btw, this is NOT homework, this is a personal project.
Thanks