/* ----------------------------------------------------------------- Software simulation of a 1024-bit hardware hash. A work-in-progress with the goal of entering the NIST cryptographic hash competition. Bits are arranged in a 32 x 32 grid, well, an 8x8 grid of 4x4-bit blocks. The hash consists of horizontal and vertical XORs, followed by the a nonlinear mix applied to every 4x4-bit block. The horizontal wires XOR bit i of block [*][i] with bit i of block [*][j], where i in 0..7, j in 0..7, and i != j. Vertical wires XOR bit i+8 of [i][*] with bit i+8 of block [j][*] where i in 0..7, j in 0..7, and i != j. The nonlinear mix of 4x4 blocks is actually an LFSR for bits 0..7, and (!s)^((w&x)|(y&z)) for bits 8..15, where w,x,y,z are all less than s. The hash is done in rounds. Each round does the horizontal and vertical XORs, then mixes the 4x4 blocks. The internal state is represented by 16 64-bit integers, x[16], where x[k] & (1<<(8*i+j)) is the kth bit of block [i][j]. This allows the nonlinear mixing to be done for all blocks simulateously, and also allows horizontal and vertical wires to be handled in bulk. ----------------------------------------------------------------- */ #include #include typedef unsigned long u4; typedef unsigned long long u8; typedef struct ranctx { u4 a; u4 b; u4 c; u4 d; } ranctx; #define rot(x,k) ((x<>(32-k))) u4 ranval( ranctx *x ) { u4 e = x->a - rot(x->b, 27); x->a = x->b ^ rot(x->c, 17); x->b = x->c + x->d; x->c = x->d + e; x->d = e + x->a; return e; } #define LEN 16 #define ROWS 8 #define COLS 8 /* do one round of the hash */ void hash(u8 x[LEN]) { u8 i, j; u8 y[LEN]; /* Horizontal linear mixing */ for (i=0; i<8; ++i) { j = x[i]; j = j ^ ((j&0x5555555555555555LL)<<1) ^ ((j&0xaaaaaaaaaaaaaaaaLL)>>1); j = j ^ ((j&0x3333333333333333LL)<<2) ^ ((j&0xccccccccccccccccLL)>>2); j = j ^ ((j&0x0f0f0f0f0f0f0f0fLL)<<4) ^ ((j&0xf0f0f0f0f0f0f0f0LL)>>4); x[i] ^= j; } /* Vertical linear mixing */ for (i=0; i<8; ++i) { j = x[i+8]; j = j ^ (j<<32) ^ (j>>32); j = j ^ (j<<16) ^ (j>>48); j = j ^ (j<<8) ^ (j>>56); x[i+8] ^= j; } for (i=0; i>1); j = j ^ ((j&0x3333333333333333LL)<<2) ^ ((j&0xccccccccccccccccLL)>>2); j = j ^ ((j&0x0f0f0f0f0f0f0f0fLL)<<4) ^ ((j&0xf0f0f0f0f0f0f0f0LL)>>4); x[i] ^= j; } /* Vertical linear mixing */ for (i=0; i<8; ++i) { j = x[i+8]; j = j ^ (j<<32) ^ (j>>32); j = j ^ (j<<16) ^ (j>>48); j = j ^ (j<<8) ^ (j>>56); x[i+8] ^= j; } } void show(u8 x[LEN]) { int i,j,k; for (i=0; i=4; ) { printf(" %s", (x[k] & (((u8)1)<<(COLS*i+j))) ? "1" : "0"); } } printf("\n"); for (j=0; j=12; ) { printf(" %s", (x[k] & (((u8)1)<<(COLS*i+j))) ? "1" : "0"); } } printf("\n"); } printf("\n"); } #define ROUNDS 10000 void showx(float x, float *worst, int verbose) { x = x/ROUNDS; if (x < *worst) *worst = x; if (verbose) printf("%3d", (int)(100*x + 0.5)); if (1.0-x < *worst) *worst = 1.0-x; } float showc(float c[ROWS][COLS][LEN], int verbose) { int i,j,k; float worst = 1.0; for (i=0; i=4; ) { showx(c[i][j][k], &worst, verbose); } if (verbose) printf(" "); } if (verbose) printf("\n"); for (j=0; j=12; ) { showx(c[i][j][k], &worst, verbose); } if (verbose) printf(" "); } if (verbose) printf("\n\n"); } /* printf(" worst = %f\n", worst); */ return worst; } int main() { ranctx rctx = {1,1,1,1}; u8 x[LEN], y[LEN]; u4 m,n,o,count,i,j,k; float val, worst = 1.0; /* see how thoroughly bit "tab[m][n] & (1<