//This program is free software: you can redistribute it and/or modify it under the terms #of the GNU General Public License as published by the Free Software Foundation, either #version 3 of the License, or (at your option) any later version. //This program is distributed in the hope that it will be useful, but WITHOUT ANY #WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A #PARTICULAR PURPOSE. See the GNU General Public License for more details. //You should have received a copy of the GNU General Public License along with this #program. If not, see /* NHASH.C Implementation of N-Hash as a function. Modifications Copyright 1994 Willis E. Howard, III */ #include #include "nhash.h" /* function prototypes */ static void encrypt (unsigned char *, unsigned char *); static unsigned char sbox (unsigned char); /* local working arrays */ static unsigned char X1[16]; static unsigned char X2[16]; /* hash128() uses the NHASH algorithm to operate on a count*16 byte input array of unsigned char type. The 16 byte init array of unsigned char type can have any initial values. The 16 byte output array of unsigned char type will contain the results of the hash. If count<=0 then the output is set equal to the input. */ void hash128 (int count, unsigned char *input, unsigned char *init, unsigned char *output) { int i; int loop; unsigned char message[16]; unsigned char result[16]; for (i = 0; i < 16; i++) { X2[i] = init[i]; /* local copy of init */ result[i] = input[i]; /* setup return if count<=0 */ } for (loop = 0; loop < count; loop++) { for (i = 0; i < 16; i++) message[i] = input[16 * loop + i]; encrypt (message, result); for (i = 0; i < 16; i++) X2[i] = result[i]; } for (i = 0; i < 16; i++) /* clear local data */ { /* and set return value */ output[i] = result[i]; X1[i] = 0; X2[i] = 0; result[i] = 0; message[i] = 0; } } static void encrypt (unsigned char *data, unsigned char *output) { unsigned char block[16]; unsigned char work[4]; unsigned char V; register int loop; register int i; for (i = 0; i < 16; i++) X1[i] = data[i]; for (i = 0; i < 8; i++) block[i] = X2[i] ^ X1[i + 8] ^ 0xaa; for (i = 0; i < 8; i++) block[i + 8] = X2[i + 8] ^ X1[i] ^ 0xaa; V = 0; for (loop = 0; loop < 8; loop++) { for (i = 0; i < 4; i++) work[i] = block[i] ^ X1[i]; /* P1 */ ++V; work[3] ^= V; work[1] ^= work[0]; work[2] ^= work[3]; work[1] = sbox ((unsigned char) (work[1] + work[2] + 1)); work[2] = sbox ((unsigned char) (work[2] + work[1])); work[0] = sbox ((unsigned char) (work[0] + work[1])); work[3] = sbox ((unsigned char) (work[3] + work[2] + 1)); for (i = 0; i < 4; i++) work[i] ^= block[i + 4]; for (i = 0; i < 4; i++) block[i + 12] ^= work[i]; for (i = 0; i < 4; i++) work[i] ^= X1[i + 4]; /* P2 */ ++V; work[3] ^= V; work[1] ^= work[0]; work[2] ^= work[3]; work[1] = sbox ((unsigned char) (work[1] + work[2] + 1)); work[2] = sbox ((unsigned char) (work[2] + work[1])); work[0] = sbox ((unsigned char) (work[0] + work[1])); work[3] = sbox ((unsigned char) (work[3] + work[2] + 1)); for (i = 0; i < 4; i++) block[i + 8] ^= work[i] ^ block[i]; /******************************/ for (i = 0; i < 4; i++) work[i] = block[i + 8] ^ X1[i + 8]; /* P3 */ ++V; work[3] ^= V; work[1] ^= work[0]; work[2] ^= work[3]; work[1] = sbox ((unsigned char) (work[1] + work[2] + 1)); work[2] = sbox ((unsigned char) (work[2] + work[1])); work[0] = sbox ((unsigned char) (work[0] + work[1])); work[3] = sbox ((unsigned char) (work[3] + work[2] + 1)); for (i = 0; i < 4; i++) work[i] ^= block[i + 12]; for (i = 0; i < 4; i++) block[i + 4] ^= work[i]; for (i = 0; i < 4; i++) work[i] ^= X1[i + 12]; /* P4 */ ++V; work[3] ^= V; work[1] ^= work[0]; work[2] ^= work[3]; work[1] = sbox ((unsigned char) (work[1] + work[2] + 1)); work[2] = sbox ((unsigned char) (work[2] + work[1])); work[0] = sbox ((unsigned char) (work[0] + work[1])); work[3] = sbox ((unsigned char) (work[3] + work[2] + 1)); for (i = 0; i < 4; i++) block[i] ^= work[i] ^ block[i + 8]; } for (i = 0; i < 16; i++) output[i] = block[i] ^ X1[i] ^ X2[i]; } static unsigned char sbox (unsigned char data) { union { unsigned int DATA; struct { unsigned char low; unsigned char high; } reg; } s; s.reg.high = 0; s.reg.low = data; s.DATA <<= 2; return (s.reg.high | s.reg.low); } #ifdef TEST static unsigned char MESSAGE[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; static unsigned char INITIAL[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static unsigned char INITIAL2[16] = { 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25}; static unsigned char OUT[16]; static int BL = 2; void main() { int i; hash128( BL, MESSAGE, INITIAL, OUT); printf ("Test Output of N-Hash\n"); for (i = 0; i < 16; i++) printf (" %02X", OUT[i]); hash128( BL, MESSAGE, INITIAL2, OUT); printf("\n"); for (i = 0; i < 16; i++) printf (" %02X", OUT[i]); printf("\n"); } /* output: 6a 98 56 20 b4 41 e3 b4 68 03 17 d9 5c 20 97 66 93 71 0a 64 64 2b 87 b4 72 0f 8c 11 09 0b ff 72 */ #endif