RE: HAMC SHA1 with CryptoAPI
From: Marco van Nieuwenhoven (Mvnieuw_at_community.nospam)
Date: 06/14/05
- Next message: Frank Perry: "Re: Diffie-Hellman problem"
- Previous message: Michaelson Eitan: "HAMC SHA1 with CryptoAPI"
- In reply to: Michaelson Eitan: "HAMC SHA1 with CryptoAPI"
- Next in thread: Michaelson Eitan: "Re: HAMC SHA1 with CryptoAPI"
- Reply: Michaelson Eitan: "Re: HAMC SHA1 with CryptoAPI"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Date: Tue, 14 Jun 2005 03:17:02 -0700
Hi Eitan,
Here we go! This is the FIPS PUB 180-1 real implementation. I use it and it
works! Special thanks goes to Dominik Reichl.
Make sure to test the testvectors (Really important!)
grtx,
Marco van Nieuwenhoven.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CSHA1.cpp
/*
100% free public domain implementation of the SHA-1
algorithm by Dominik Reichl <dominik.reichl@t-online.de>
=== Test Vectors (from FIPS PUB 180-1) ===
SHA1("abc") =
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
SHA1(A million repetitions of "a") =
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#include "CSHA1.h"
#define MAX_FILE_READ_BUFFER 8000
// Rotate x bits to the left
#ifndef ROL32
#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
#endif
#ifdef SHA1_LITTLE_ENDIAN
#define SHABLK0(i) (m_block->l[i] = \
(ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) &
0x00FF00FF))
#else
#define SHABLK0(i) (m_block->l[i])
#endif
#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^
m_block->l[(i+8)&15] \
^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))
// SHA-1 rounds
#define _R0(v,w,x,y,z,i) {
z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5);
w=ROL32(w,30); }
#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5);
w=ROL32(w,30); }
#define _R3(v,w,x,y,z,i) {
z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5);
w=ROL32(w,30); }
CSHA1::CSHA1()
{
m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
Reset();
}
CSHA1::~CSHA1()
{
Reset();
}
void CSHA1::Reset()
{
// SHA1 initialization constants
m_state[0] = 0x67452301;
m_state[1] = 0xEFCDAB89;
m_state[2] = 0x98BADCFE;
m_state[3] = 0x10325476;
m_state[4] = 0xC3D2E1F0;
m_count[0] = 0;
m_count[1] = 0;
}
void CSHA1::Transform(unsigned long state[5], unsigned char buffer[64])
{
unsigned long a = 0, b = 0, c = 0, d = 0, e = 0;
memcpy(m_block, buffer, 64);
// Copy 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, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3);
_R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7);
_R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11);
_R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15);
_R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19);
_R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23);
_R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27);
_R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31);
_R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35);
_R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39);
_R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43);
_R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47);
_R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51);
_R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55);
_R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59);
_R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63);
_R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67);
_R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71);
_R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75);
_R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79);
// Add the working vars back into state[]
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
// Wipe variables
a = b = c = d = e = 0;
}
// Use this function to hash in binary data and strings
void CSHA1::Update(unsigned char *data, unsigned int len)
{
unsigned long i = 0, j;
j = (m_count[0] >> 3) & 63;
if((m_count[0] += len << 3) < (len << 3)) m_count[1]++;
m_count[1] += (len >> 29);
if((j + len) > 63)
{
memcpy(&m_buffer[j], data, (i = 64 - j));
Transform(m_state, m_buffer);
for (; i+63 < len; i += 64)
Transform(m_state, &data[i]);
j = 0;
}
else i = 0;
memcpy(&m_buffer[j], &data[i], len - i);
}
// Hash in file contents
bool CSHA1::HashFile(char *szFileName)
{
unsigned long ulFileSize = 0, ulRest = 0, ulBlocks = 0;
unsigned long i = 0;
unsigned char uData[MAX_FILE_READ_BUFFER];
FILE *fIn = NULL;
if(szFileName == NULL) return(false);
if((fIn = fopen(szFileName, "rb")) == NULL) return(false);
fseek(fIn, 0, SEEK_END);
ulFileSize = ftell(fIn);
fseek(fIn, 0, SEEK_SET);
ulRest = ulFileSize % MAX_FILE_READ_BUFFER;
ulBlocks = ulFileSize / MAX_FILE_READ_BUFFER;
for(i = 0; i < ulBlocks; i++)
{
fread(uData, 1, MAX_FILE_READ_BUFFER, fIn);
Update(uData, MAX_FILE_READ_BUFFER);
}
if(ulRest != 0)
{
fread(uData, 1, ulRest, fIn);
Update(uData, ulRest);
}
fclose(fIn);
fIn = NULL;
return(true);
}
void CSHA1::Final()
{
unsigned long i = 0, j = 0;
unsigned char finalcount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
for (i = 0; i < 8; i++)
finalcount[i] = (unsigned char)((m_count[(i >= 4 ? 0 : 1)]
>> ((3 - (i & 3)) * 8) ) & 255); // Endian independent
Update((unsigned char *)"\200", 1);
while ((m_count[0] & 504) != 448)
Update((unsigned char *)"\0", 1);
Update(finalcount, 8); // Cause a SHA1Transform()
for (i = 0; i < 20; i++)
{
m_digest[i] = (unsigned char)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) &
255);
}
// Wipe variables for security reasons
i = 0; j = 0;
memset(m_buffer, 0, 64);
memset(m_state, 0, 20);
memset(m_count, 0, 8);
memset(finalcount, 0, 8);
Transform(m_state, m_buffer);
}
// Get the final hash as a pre-formatted string
void CSHA1::ReportHash(char *szReport, unsigned char uReportType)
{
unsigned char i = 0;
char szTemp[12];
memset (szReport, 0, 42);
if(szReport == NULL) return;
if(uReportType == REPORT_HEX)
{
sprintf(szTemp, "%02X", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < 20; i++)
{
sprintf(szTemp, "%02X", m_digest[i]);
strcat(szReport, szTemp);
}
}
else if(uReportType == REPORT_DIGIT)
{
sprintf(szTemp, "%u", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < 20; i++)
{
sprintf(szTemp, " %u", m_digest[i]);
strcat(szReport, szTemp);
}
}
else strcpy(szReport, "Error: Unknown report type!");
}
// Get the raw message digest
void CSHA1::GetHash(unsigned char *uDest)
{
memcpy(uDest, m_digest, 20);
}
// Make sure that the SHA1 is not standard
void CSHA1::Kusterize()
{
char SHA1IV[] = {"Kusters Engineering BV"};
this->Update((unsigned char *)SHA1IV, strlen(SHA1IV));
}
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CSHA1.h
/*
100% free public domain implementation of the SHA-1
algorithm by Dominik Reichl <dominik.reichl@t-online.de>
=== Test Vectors (from FIPS PUB 180-1) ===
SHA1("abc") =
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
SHA1(A million repetitions of "a") =
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#ifndef ___SHA1_H___
#define ___SHA1_H___
#include <stdio.h> // Needed for file access
#include <memory.h> // Needed for memset and memcpy
#include <string.h> // Needed for strcat and strcpy
// If you're compiling big endian, just comment out the following line
#define SHA1_LITTLE_ENDIAN
typedef union
{
unsigned char c[64];
unsigned long l[16];
} SHA1_WORKSPACE_BLOCK;
class CSHA1
{
public:
// Two different formats for ReportHash(...)
enum
{
REPORT_HEX = 0,
REPORT_DIGIT = 1
};
// Constructor and Destructor
CSHA1();
virtual ~CSHA1();
unsigned long m_state[5];
unsigned long m_count[2];
unsigned char m_buffer[64];
unsigned char m_digest[20];
void Reset();
// Update the hash value
void Update(unsigned char *data, unsigned int len);
bool HashFile(char *szFileName);
// Finalize hash and report
void Final();
void ReportHash(char *szReport, unsigned char uReportType = REPORT_HEX);
void GetHash(unsigned char *uDest);
void Kusterize();
private:
// Private SHA-1 transformation
void Transform(unsigned long state[5], unsigned char buffer[64]);
// Member variables
unsigned char m_workspace[64];
SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
};
#endif
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
"Michaelson Eitan" wrote:
> Can someone here be kind and post a sample (C code) that implements
> HAMC SHA1 signing.
> Can't make it work.. here is what I have so far (just few samples I've
> picked while browsing this group)
>
> Note a: And yes, I know there is a simple class in the .Net framework,
> but I need a Win32 code.
>
> Note b: My code compiles and run but I know something isn't right by
> comparing to a (known to be working) sample code I have (created the
> with .Net framework class)
>
> Eitan.
>
> #include <stdio.h>
> #include <windows.h>
> #include <Wincrypt.h>
>
>
> void main(void)
> {
>
> char *pKey = "key";
> char *pData = "data";
>
>
> HCRYPTPROV hProv = NULL;
> HCRYPTHASH hHash = NULL;
> HCRYPTHASH hHash2 = NULL;
> HCRYPTKEY hKey = NULL;
>
> if(CryptAcquireContext(&hProv, NULL,
> NULL, PROV_RSA_FULL, 0))
> printf("CryptAcquireContext->OK\n");
> else
> return;
>
> if(CryptCreateHash(hProv, CALG_SHA1, 0,
> 0, &hHash))
> printf("CryptCreateHash->OK\n");
> else
> return;
>
>
> if(CryptHashData(hHash, (BYTE*)pKey, 3, 0))
> printf("CryptHashData->OK\n");
> else
> return;
>
> if(CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
> printf("CryptDeriveKey->OK\n");
> else
> return;
>
> if(CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash2))
> printf("CryptCreateHash->OK\n");
> else
> return;
>
> HMAC_INFO hmacInfo;
> ZeroMemory(&hmacInfo, sizeof(hmacInfo));
> hmacInfo.HashAlgid = CALG_SHA1;
>
> if(CryptSetHashParam(hHash2,
> HP_HMAC_INFO,
> (BYTE*)&hmacInfo, 0))
> printf("CryptSetHashParam->OK\n");
> else
> return;
>
>
> if(CryptHashData(hHash2, (BYTE*)pData, 4, 0))
> printf("CryptHashData->OK\n");
> else
> return;
>
> char szData[21];
> memset(szData,0x00,21);
> DWORD dwDataLen = 20;
>
> CryptGetHashParam(hHash2, HP_HASHVAL,
> (BYTE*)&szData,
> &dwDataLen, 0);
>
>
> CryptDestroyHash(hHash2);
> CryptDestroyHash(hHash);
> CryptDestroyKey(hKey);
> CryptReleaseContext(hProv, 0);
>
> printf("%d\n",dwDataLen);
>
> }
>
>
- Next message: Frank Perry: "Re: Diffie-Hellman problem"
- Previous message: Michaelson Eitan: "HAMC SHA1 with CryptoAPI"
- In reply to: Michaelson Eitan: "HAMC SHA1 with CryptoAPI"
- Next in thread: Michaelson Eitan: "Re: HAMC SHA1 with CryptoAPI"
- Reply: Michaelson Eitan: "Re: HAMC SHA1 with CryptoAPI"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [PATCH][5/6] A different KGDB stub
... static void serial_console_write(struct console *c, const char *s, ...
-static int initialized; ... (Linux-Kernel) - [PATCH][5/6] A different KGDB stub
... static void serial_console_write(struct console *c, const char *s, ...
-static int initialized; ... (Linux-Kernel) - [Hat-Squad] Computer-Associates, License Manager POC Exploit
... by the way, sending up this bad char to the bottom of what you know of some amazing
wannabel33t deface kiddies crawling my website, ... void usage; ... printf("
reverse a cmdshell on your listener. ... (Bugtraq) - [PATCH 8/14] FRV: GP-REL data support
... Declaring the variables as "const void" type also ... typedef int; ...
+extern const char linux_banner; ... (Linux-Kernel) - RE: Invalid module format?
... the driver is supposed to allocate kernel memory that's ... void ibb_rtc_wakeup;
... static int ... (Linux-Kernel)