1. Hash algorithm: C to Euphoria
- Posted by Alan Tu <ATU5713 at COMPUSERVE.COM>
Dec 23, 1998
-
Last edited Dec 24, 1998
There's a secure hash algorithm called SHA-1. I am asking help to port
this C monster to Euphoria; I think it would have several applications in
current programs, such as authentication and confirming good decrypts of
encrypted files. I don't know any C, so I'm asking for help. Maybe some
people can port portions of this to Euphoria. Thanks.
Alan
Nitty-Gritty
/* NIST Secure Hash Algorithm */
/* heavily modified by Uwe Hollerbach uh at alumni.caltech edu */
/* from Peter C. Gutmann's implementation as found in */
/* Applied Cryptography by Bruce Schneier */
/* NIST's proposed modification to SHA of 7/11/94 may be */
/* activated by defining USE_MODIFIED_SHA */
begin source:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "sha.h"
/* SHA f()-functions */
#define f1(x,y,z) ((x & y) | (~x & z))
#define f2(x,y,z) (x ^ y ^ z)
#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
#define f4(x,y,z) (x ^ y ^ z)
/* SHA constants */
#define CONST1 0x5a827999L
#define CONST2 0x6ed9eba1L
#define CONST3 0x8f1bbcdcL
#define CONST4 0xca62c1d6L
/* 32-bit rotate */
#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
#define FUNC(n,i) \
temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
E = D; D = C; C = ROT32(B,30); B = A; A = temp
/* do SHA transformation */
static void sha_transform(SHA_INFO *sha_info)
{
int i;
LONG temp, A, B, C, D, E, W[80];
for (i = 0; i < 16; ++i) {
W[i] = sha_info->data[i];
}
for (i = 16; i < 80; ++i) {
W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
#ifdef USE_MODIFIED_SHA
W[i] = ROT32(W[i], 1);
#endif /* USE_MODIFIED_SHA */
}
A = sha_info->digest[0];
B = sha_info->digest[1];
C = sha_info->digest[2];
D = sha_info->digest[3];
E = sha_info->digest[4];
#ifdef UNROLL_LOOPS
FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
#else /* !UNROLL_LOOPS */
for (i = 0; i < 20; ++i) {
FUNC(1,i);
}
for (i = 20; i < 40; ++i) {
FUNC(2,i);
}
for (i = 40; i < 60; ++i) {
FUNC(3,i);
}
for (i = 60; i < 80; ++i) {
FUNC(4,i);
}
#endif /* !UNROLL_LOOPS */
sha_info->digest[0] += A;
sha_info->digest[1] += B;
sha_info->digest[2] += C;
sha_info->digest[3] += D;
sha_info->digest[4] += E;
}
#ifdef LITTLE_ENDIAN
/* change endianness of data */
static void byte_reverse(LONG *buffer, int count)
{
int i;
BYTE ct[4], *cp;
count /= sizeof(LONG);
cp = (BYTE *) buffer;
for (i = 0; i < count; ++i) {
ct[0] = cp[0];
ct[1] = cp[1];
ct[2] = cp[2];
ct[3] = cp[3];
cp[0] = ct[3];
cp[1] = ct[2];
cp[2] = ct[1];
cp[3] = ct[0];
cp += sizeof(LONG);
}
}
#endif /* LITTLE_ENDIAN */
/* initialize the SHA digest */
void sha_init(SHA_INFO *sha_info)
{
sha_info->digest[0] = 0x67452301L;
sha_info->digest[1] = 0xefcdab89L;
sha_info->digest[2] = 0x98badcfeL;
sha_info->digest[3] = 0x10325476L;
sha_info->digest[4] = 0xc3d2e1f0L;
sha_info->count_lo = 0L;
sha_info->count_hi = 0L;
}
/* update the SHA digest */
void sha_update(SHA_INFO *sha_info, BYTE *buffer, int count)
{
if ((sha_info->count_lo + ((LONG) count << 3)) < sha_info->count_lo) {
++sha_info->count_hi;
}
sha_info->count_lo += (LONG) count << 3;
sha_info->count_hi += (LONG) count >> 29;
while (count >= SHA_BLOCKSIZE) {
memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
#ifdef LITTLE_ENDIAN
byte_reverse(sha_info->data, SHA_BLOCKSIZE);
#endif /* LITTLE_ENDIAN */
sha_transform(sha_info);
buffer += SHA_BLOCKSIZE;
count -= SHA_BLOCKSIZE;
}
memcpy(sha_info->data, buffer, count);
}
/* finish computing the SHA digest */
void sha_final(SHA_INFO *sha_info)
{
int count;
LONG lo_bit_count, hi_bit_count;
lo_bit_count = sha_info->count_lo;
hi_bit_count = sha_info->count_hi;
count = (int) ((lo_bit_count >> 3) & 0x3f);
((BYTE *) sha_info->data)[count++] = 0x80;
if (count > 56) {
memset((BYTE *) &sha_info->data + count, 0, 64 - count);
#ifdef LITTLE_ENDIAN
byte_reverse(sha_info->data, SHA_BLOCKSIZE);
#endif /* LITTLE_ENDIAN */
sha_transform(sha_info);
memset(&sha_info->data, 0, 56);
} else {
memset((BYTE *) &sha_info->data + count, 0, 56 - count);
}
#ifdef LITTLE_ENDIAN
byte_reverse(sha_info->data, SHA_BLOCKSIZE);
#endif /* LITTLE_ENDIAN */
sha_info->data[14] = hi_bit_count;
sha_info->data[15] = lo_bit_count;
sha_transform(sha_info);
}
/* compute the SHA digest of a FILE stream */
#define BLOCK_SIZE 8192
void sha_stream(SHA_INFO *sha_info, FILE *fin)
{
int i;
BYTE data[BLOCK_SIZE];
sha_init(sha_info);
while ((i = fread(data, 1, BLOCK_SIZE, fin)) > 0) {
sha_update(sha_info, data, i);
}
sha_final(sha_info);
}
/* print a SHA digest */
void sha_print(SHA_INFO *sha_info)
{
printf("%08lx %08lx %08lx %08lx %08lx\n",
sha_info->digest[0], sha_info->digest[1], sha_info->digest[2],
sha_info->digest[3], sha_info->digest[4]);
}
end source
3. Re: Hash algorithm: C to Euphoria
Adam Weeden wrote:
>I'd be willing to help.
Sounds great. See if you can make heads or tails of the C code and port it
to, like maybe, to an Euphoria function. Thanks.
Alan
5. Re: Hash algorithm: C to Euphoria
- Posted by Davi Figueiredo <davitf at USA.NET>
Dec 27, 1998
-
Last edited Dec 28, 1998
Hi Alan and all interested,
Attached is an Euphoria include file which calculates the SHA-1 digest of a
string. I didn't translate the C code posted, instead I followed the
specification I found at http://www.nist.gov/itl/div897/pubs/fip180-1.htm .
The reason I didn't try translating the code was that I know nothing about
C (and don't want to learn it either). Anyway, it seems to work ok. If you
think it's too slow, maybe someone can speed it up (if someone can
understand the code).
Regards,
Davi Figueiredo
davitf at usa.net
____________________________________________________________________
Get free e-mail and a permanent address at http://www.amexmail.com/?A=1