algorithm - Adapt existing GOST code in C to hash a file -


i trying hand-code gost hash function using c. came across following code markku-juhani saarinen (from link).

/*  *  gosthash.c   *  21 apr 1998  markku-juhani saarinen <mjos@ssh.fi>  *   *  gost r 34.11-94, russian standard hash function  *  *  copyright (c) 1998 ssh communications security, finland  *  rights reserved.  */  #include <stdio.h> #include <stdlib.h> #include <string.h> #include "gosthash.h"  /* lookup tables : each of these has 2 rotated 4-bit s-boxes */  unsigned long gost_sbox_1[256]; unsigned long gost_sbox_2[256]; unsigned long gost_sbox_3[256]; unsigned long gost_sbox_4[256];  /* initialize lookup tables */  void gosthash_init() {   int a, b, i;   unsigned long ax, bx, cx, dx;    /* 4-bit s-boxes */     unsigned long sbox[8][16] =     {     {  4, 10,  9,  2, 13,  8,  0, 14,  6, 11,  1, 12,  7, 15,  5,  3 },     { 14, 11,  4, 12,  6, 13, 15, 10,  2,  3,  8,  1,  0,  7,  5,  9 },     {  5,  8,  1, 13, 10,  3,  4,  2, 14, 15, 12,  7,  6,  0,  9, 11 },     {  7, 13, 10,  1,  0,  8,  9, 15, 14,  4,  6, 12, 11,  2,  5,  3 },     {  6, 12,  7,  1,  5, 15, 13,  8,  4, 10,  9, 14,  0,  3, 11,  2 },     {  4, 11, 10,  0,  7,  2,  1, 13,  3,  6,  8,  5,  9, 12, 15, 14 },     { 13, 11,  4,  1,  3, 15,  5,  9,  0, 10, 14,  7,  6,  8,  2, 12 },     {  1, 15, 13,  0,  5,  7, 10,  4,  9,  2,  3, 14,  6, 11,  8, 12 }       };    /* s-box precomputation */    = 0;   (a = 0; < 16; a++)     {       ax = sbox[1][a] << 15;             bx = sbox[3][a] << 23;       cx = sbox[5][a];               cx = (cx >> 1) | (cx << 31);       dx = sbox[7][a] << 7;        (b = 0; b < 16; b++)     {       gost_sbox_1[i] = ax | (sbox[0][b] << 11);              gost_sbox_2[i] = bx | (sbox[2][b] << 19);       gost_sbox_3[i] = cx | (sbox[4][b] << 27);          gost_sbox_4[i++] = dx | (sbox[6][b] << 3);     }     } }  /*  *  macro performs full encryption round of gost 28147-89.  *  temporary variable t assumed , variables r , l left , right  *  blocks  */   #define gost_encrypt_round(k1, k2) \ t = (k1) + r; \ l ^= gost_sbox_1[t & 0xff] ^ gost_sbox_2[(t >> 8) & 0xff] ^ \ gost_sbox_3[(t >> 16) & 0xff] ^ gost_sbox_4[t >> 24]; \ t = (k2) + l; \ r ^= gost_sbox_1[t & 0xff] ^ gost_sbox_2[(t >> 8) & 0xff] ^ \ gost_sbox_3[(t >> 16) & 0xff] ^ gost_sbox_4[t >> 24]; \  /* encrypt block given key */  #define gost_encrypt(key) \ gost_encrypt_round(key[0], key[1]) \ gost_encrypt_round(key[2], key[3]) \ gost_encrypt_round(key[4], key[5]) \ gost_encrypt_round(key[6], key[7]) \ gost_encrypt_round(key[0], key[1]) \ gost_encrypt_round(key[2], key[3]) \ gost_encrypt_round(key[4], key[5]) \ gost_encrypt_round(key[6], key[7]) \ gost_encrypt_round(key[0], key[1]) \ gost_encrypt_round(key[2], key[3]) \ gost_encrypt_round(key[4], key[5]) \ gost_encrypt_round(key[6], key[7]) \ gost_encrypt_round(key[7], key[6]) \ gost_encrypt_round(key[5], key[4]) \ gost_encrypt_round(key[3], key[2]) \ gost_encrypt_round(key[1], key[0]) \ t = r; \ r = l; \ l = t;  /*   *  "chi" compression function. result stored on h  */  void gosthash_compress(unsigned long *h, unsigned long *m) {   int i;   unsigned long l, r, t, key[8], u[8], v[8], w[8], s[8];    memcpy(u, h, sizeof(u));   memcpy(v, m, sizeof(u));    (i = 0; < 8; += 2)     {               w[0] = u[0] ^ v[0];          /* w = u xor v */       w[1] = u[1] ^ v[1];       w[2] = u[2] ^ v[2];       w[3] = u[3] ^ v[3];       w[4] = u[4] ^ v[4];       w[5] = u[5] ^ v[5];       w[6] = u[6] ^ v[6];       w[7] = u[7] ^ v[7];              /* p-transformation */        key[0] = (w[0]  & 0x000000ff) | ((w[2] & 0x000000ff) << 8) |     ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24);       key[1] = ((w[0] & 0x0000ff00) >> 8)  | (w[2]  & 0x0000ff00) |     ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16);       key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) |     (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8);       key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) |     ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000);         key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) |     ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24);       key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3]  & 0x0000ff00) |     ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16);       key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) |     (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8);       key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) |     ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);          r = h[i];                /* encriphering transformation */       l = h[i + 1];             gost_encrypt(key);        s[i] = r;       s[i + 1] = l;        if (i == 6)     break;        l = u[0] ^ u[2];             /* u = a(u) */       r = u[1] ^ u[3];       u[0] = u[2];       u[1] = u[3];       u[2] = u[4];       u[3] = u[5];       u[4] = u[6];       u[5] = u[7];       u[6] = l;       u[7] = r;        if (i == 2)              /* constant c_3 */     {       u[0] ^= 0xff00ff00;        u[1] ^= 0xff00ff00;        u[2] ^= 0x00ff00ff;       u[3] ^= 0x00ff00ff;       u[4] ^= 0x00ffff00;       u[5] ^= 0xff0000ff;       u[6] ^= 0x000000ff;       u[7] ^= 0xff00ffff;            }        l = v[0];                /* v = a(a(v)) */       r = v[2];       v[0] = v[4];       v[2] = v[6];       v[4] = l ^ r;       v[6] = v[0] ^ r;       l = v[1];       r = v[3];       v[1] = v[5];       v[3] = v[7];       v[5] = l ^ r;       v[7] = v[1] ^ r;     }    /* 12 rounds of lfsr (computed product matrix) , xor in m */    u[0] = m[0] ^ s[6];   u[1] = m[1] ^ s[7];   u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^      (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^     (s[7] & 0xffff0000) ^ (s[7] >> 16);   u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^      (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^     (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^      (s[7] << 16) ^ (s[7] >> 16);   u[4] = m[4] ^      (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^      (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^     (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^      (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);   u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^     (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^     (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^  (s[6] << 16) ^      (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16);   u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^     (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^      (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16);   u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^      (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^     (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^      (s[7] << 16) ^ (s[7] >> 16);    /* 16 * 1 round of lfsr , xor in h */    v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16);   v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16);   v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16);   v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16);   v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16);   v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16);   v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16);   v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^     (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);    /* 61 rounds of lfsr, mixing h (computed product matrix) */    h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^      (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^     (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^      (v[7] & 0xffff);   h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^      v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^      (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16);   h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^      (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^     (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^     (v[7] >> 16);   h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^      (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^      (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^      (v[7] & 0xffff) ^ (v[7] >> 16);   h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^      (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^      v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16);   h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^      (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^      (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^     (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000);   h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^      (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^      (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7];   h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^     (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^     (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7]; }  /* clear state of given context structure. */  void gosthash_reset(gosthashctx *ctx) {   memset(ctx->sum, 0, 32);   memset(ctx->hash, 0, 32);   memset(ctx->len, 0, 32);   memset(ctx->partial, 0, 32);   ctx->partial_bytes = 0;   }  /* mix in 32-byte chunk ("stage 3") */  void gosthash_bytes(gosthashctx *ctx, const unsigned char *buf, size_t bits) {   int i, j;   unsigned long a, b, c, m[8];    /* convert bytes long words , compute sum */    j = 0;   c = 0;   (i = 0; < 8; i++)     {       = ((unsigned long) buf[j]) |      (((unsigned long) buf[j + 1]) << 8) |      (((unsigned long) buf[j + 2]) << 16) |      (((unsigned long) buf[j + 3]) << 24);       j += 4;       m[i] = a;       b = ctx->sum[i];       c = + c + ctx->sum[i];       ctx->sum[i] = c;       c = ((c < a) || (c < b)) ? 1 : 0;          }    /* compress */    gosthash_compress(ctx->hash, m);    /* 64-bit counter should sufficient */    ctx->len[0] += bits;   if (ctx->len[0] < bits)     ctx->len[1]++;   }  /* mix in len bytes of data given buffer. */  void gosthash_update(gosthashctx *ctx, const unsigned char *buf, size_t len) {   size_t i, j;    = ctx->partial_bytes;   j = 0;   while (i < 32 && j < len)     ctx->partial[i++] = buf[j++];    if (i < 32)     {       ctx->partial_bytes = i;       return;     }     gosthash_bytes(ctx, ctx->partial, 256);    while ((j + 32) < len)     {       gosthash_bytes(ctx, &buf[j], 256);       j += 32;     }    = 0;   while (j < len)     ctx->partial[i++] = buf[j++];   ctx->partial_bytes = i; }   /* compute , save 32-byte digest. */  void gosthash_final(gosthashctx *ctx, unsigned char *digest) {   int i, j;   unsigned long a;    /* adjust , mix in last chunk */    if (ctx->partial_bytes > 0)     {       memset(&ctx->partial[ctx->partial_bytes], 0, 32 - ctx->partial_bytes);       gosthash_bytes(ctx, ctx->partial, ctx->partial_bytes << 3);           }    /* mix in length , sum */    gosthash_compress(ctx->hash, ctx->len);     gosthash_compress(ctx->hash, ctx->sum);      /* convert output bytes */    j = 0;   (i = 0; < 8; i++)     {       = ctx->hash[i];       digest[j] = (unsigned char) a;       digest[j + 1] = (unsigned char) (a >> 8);       digest[j + 2] = (unsigned char) (a >> 16);       digest[j + 3] = (unsigned char) (a >> 24);           j += 4;     }   } 

however, there no main() function can use compile executable. wanted main of type main(int argc, char *argv[]) call file produced executable , have file's contents hashed.

i have gone through code on , on again stuck calling code's functions, don't know how proceed. please, ideas on how can fill main function run code?

edit

i tried following main() code not seem work:

void main(int argc, char *argv[]){     if (argc!=2) {         fprintf(stderr, "error: provide name of 1 source file.\n");         exit(exit_failure);     }      char *clear_file = argv[1];     const char *filename_in = clear_file;      file *infile;     infile = fopen(filename_in, "r");      gosthashctx *ctx = malloc(sizeof(gosthashctx));     unsigned char *digest, *buf;     char c;      if(infile == null){         fprintf(stderr, "error: source file not found.\n");         exit(exit_failure);     }      gosthash_init();     gosthash_reset(ctx); //printf("ctx.pb=%d\n\n",ctx->partial_bytes);      int quit = 0;     while (quit == 0) {         int p = 0;         buf = malloc(256);         strcpy(buf, "");         while(((c = fgetc(infile)) != eof) && (p < 256)) {             *(buf+p) = c;             p++;         }          //*(buf+p) = '\0';         if(c == eof) quit = 1;          gosthash_update(ctx, buf, 256);         free(buf);     }      digest = malloc(256);      strcpy(digest, "");      gosthash_final(ctx, digest);      printf("%s\n", digest);      free(ctx);     free(digest); } 

to verify output, used online tool convert resulting string digest hex result incorrect known test values of gost hashing. please, ideas why might case?

ok, first have call gosthash_init fill lookup tables. allocate many contexts of type gosthashctx require - need 1 in case. can reset in advance make sure context filled 0 values.

now call gosthash_update 1 or multiple times hash bytes in file (sequentially, of course). call gosthash_final create hash. these steps perform actual hashing.

if want hash else, first call gosthash_reset, , gosthash_update , gosthash_final again.


Comments

Popular posts from this blog

python - Healpy: From Data to Healpix map -

c - Bitwise operation with (signed) enum value -

xslt - Unnest parent nodes by child node -