/************************************************************************* ** ** ** sha.cxx ** ** ** ** SECURE HASH ALGORITHM IMPLEMENTATION ** ** ** ** Copyright (c)1996 Markku-Juhani O. Saarinen ** ** ** ** *************************************************************************/ #include "sha.h" #include #include // makro little endian tavujen kääntämiseen (intel-koneet tarvitsevat) #define SHA_INV(x) ((x>>24) | ((x>>8) & 0xff00) | \ ((x<<8) & 0xff0000) | (x<<24) ) // muodostaa annetusta lohkosta 160-bittisen SHA digestin void sha ( unsigned char *pt, unsigned long len, void *digest ) { unsigned long a, b, c, d, e, T; unsigned long read; unsigned long W[16], *H; int i, t; read = 0; H = (unsigned long *) digest; H[0] = 0x67452301; H[1] = 0xefcdab89; H[2] = 0x98badcfe; H[3] = 0x10325476; H[4] = 0xc3d2e1f0; while ( read < (len + 0x40) ) { if ( (read + 0x40) <= len ) { for(i=0; i<16; i++) { T = *((unsigned long *)(pt+read)); W[i] = SHA_INV(T); } read += 0x40; } else { bzero( W, 64 ); if ( read < len ) { bcopy( pt+read, W, len-read ); read = len; } // lisätään viimeinen '1' bitti ((unsigned char *) W)[len & 0x3f] = 0x80; // käännetään viimeinen blokki toisinpäin for (i=0; i<16; i++) { T = W[i]; W[i] = SHA_INV(T); } // lisätään bittien lkm if ( (read & 0x3f) < 55 ) { W[15] = len << 3; read = len + 0x40; } else { read = (len + 0x40) & (~0x3f); } } a = H[0]; b = H[1]; c = H[2]; d = H[3]; e = H[4]; // ensimmäinen osa for(t = 0; t<20; t++) { if ( t >= 16 ) { T = W[(t+13)&15] ^ W[(t+8)&15] ^ W[(t+2)&15] ^ W[t&15]; W[t&15] = (T << 1) | (T >> 31); } T = ( (a<<5) | (a>>27) ) + ( (b & c) | ((~b) & d ) ) + e + W[t&15] + 0x5a827999; e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = T; } // toinen osa for(; t<40; t++) { T = W[(t+13)&15] ^ W[(t+8)&15] ^ W[(t+2)&15] ^ W[t&15]; W[t&15] = (T << 1) | (T >> 31); T = ( (a<<5) | (a>>27) ) + ( b^c^d ) + e + W[t&15] + 0x6ed9eba1; e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = T; } // kolmas osa for (; t<60; t++) { T = W[(t+13)&15] ^ W[(t+8)&15] ^ W[(t+2)&15] ^ W[t&15]; W[t&15] = (T << 1) | (T >> 31); T = ( (a<<5) | (a>>27) ) + ( ( b & c) | (b & d) | (c & d) ) + e + W[t&15] + 0x8f1bbcdc; e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = T; } // neljäs osa for(; t<80; t++) { T = W[(t+13)&15] ^ W[(t+8)&15] ^ W[(t+2)&15] ^ W[t&15]; W[t&15] = (T << 1) | (T >> 31); T = ( (a<<5) | (a>>27) ) + ( b^c^d ) + e + W[t&15] + 0xca62c1d6; e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = T; } // lisätään lohkosta saadut (a, b, c, d, e) päädigestiin H[0] += a; H[1] += b; H[2] += c; H[3] += d; H[4] += e; } // nollataan mahdollisesti olennaista tietoa sisältävä vektori W bzero(W, sizeof(W)); // käännetään tulosvektori H[0] = SHA_INV(H[0]); H[1] = SHA_INV(H[1]); H[2] = SHA_INV(H[2]); H[3] = SHA_INV(H[3]); H[4] = SHA_INV(H[4]); }