Thread: How to Convert a Hash Digest Type Int to a String

  1. #1
    Registered User
    Join Date
    Oct 2017
    Posts
    2

    How to Convert a Hash Digest Type Int to a String

    I am trying to convert the hash digest into a string to be compared with strcmp. I did some research and found this: (slightly modified for my code)
    Code:
    for (idx=0; idx < 32; idx++)
            sprintf(&hashstr[idx], "%x",hash[idx]);
    The problem is that I get this after I enter the password, "password":
    Code:
    Digest: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
    Expected: 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
    Digest convert: 5849d2475de68c22763d6abd21e7114d68
    I was referenced a book. I read the entire book without seeing what's wrong. After, I was told it had something to do with the bit size for each character in the string. If that's the case, could you elaborate on that? Why is that the issue? Why do I do [...] to fix it? Thank you.


    Full
    Code:
    //SHA256 is accredited to the NSA
    
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <stdarg.h>
    #include <stdint.h>
    
    #define BUF_SIZE 1024
    
    
    
    #define uchar unsigned char // 8-bit byte
    #define uint unsigned int // 32-bit word
    
    // DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it
    #define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - (c)) ++b; a += c;
    #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
    #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
    
    #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
    #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
    #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
    #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
    #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
    #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
    
    typedef struct {
       uchar data[64];
       uint datalen;
       uint bitlen[2];
       uint state[8];
    } SHA256_CTX;
    
    uint k[64] = {
       0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
       0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
       0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
       0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
       0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
       0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
       0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
       0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
    };
    
    
    void sha256_transform(SHA256_CTX *ctx, uchar data[])
    {
       uint a,b,c,d,e,f,g,h,i,j,t1,t2,m[64];
    
       for (i=0,j=0; i < 16; ++i, j += 4)
          m[i] = (data[j] << 24) | (data[j+1] << 16) | (data[j+2] << 8) | (data[j+3]);
       for ( ; i < 64; ++i)
          m[i] = SIG1(m[i-2]) + m[i-7] + SIG0(m[i-15]) + m[i-16];
    
       a = ctx->state[0];
       b = ctx->state[1];
       c = ctx->state[2];
       d = ctx->state[3];
       e = ctx->state[4];
       f = ctx->state[5];
       g = ctx->state[6];
       h = ctx->state[7];
    
       for (i = 0; i < 64; ++i) {
          t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
          t2 = EP0(a) + MAJ(a,b,c);
          h = g;
          g = f;
          f = e;
          e = d + t1;
          d = c;
          c = b;
          b = a;
          a = t1 + t2;
       }
       ctx->state[0] += a;
       ctx->state[1] += b;
       ctx->state[2] += c;
       ctx->state[3] += d;
       ctx->state[4] += e;
       ctx->state[5] += f;
       ctx->state[6] += g;
       ctx->state[7] += h;
    }
    
    void sha256_init(SHA256_CTX *ctx)
    {
       ctx->datalen = 0;
       ctx->bitlen[0] = 0;
       ctx->bitlen[1] = 0;
       ctx->state[0] = 0x6a09e667;
       ctx->state[1] = 0xbb67ae85;
       ctx->state[2] = 0x3c6ef372;
       ctx->state[3] = 0xa54ff53a;
       ctx->state[4] = 0x510e527f;
       ctx->state[5] = 0x9b05688c;
       ctx->state[6] = 0x1f83d9ab;
       ctx->state[7] = 0x5be0cd19;
    }
    
    void sha256_update(SHA256_CTX *ctx, uchar data[], uint len)
    {
       uint t,i;
    
       for (i=0; i < len; ++i) {
          ctx->data[ctx->datalen] = data[i];
          ctx->datalen++;
          if (ctx->datalen == 64) {
             sha256_transform(ctx,ctx->data);
             DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],512);
             ctx->datalen = 0;
          }
       }
    }
    
    void sha256_final(SHA256_CTX *ctx, uchar hash[])
    {
       uint i;
    
       i = ctx->datalen;
    
       // Pad whatever data is left in the buffer. 
       if (ctx->datalen < 56) {
          ctx->data[i++] = 0x80;
          while (i < 56)
             ctx->data[i++] = 0x00;
       }
       else {
          ctx->data[i++] = 0x80;
          while (i < 64)
             ctx->data[i++] = 0x00;
          sha256_transform(ctx,ctx->data);
          memset(ctx->data,0,56);
       }
       // Append to the padding the total message's length in bits and transform. 
       DBL_INT_ADD(ctx->bitlen[0],ctx->bitlen[1],ctx->datalen * 8);
       ctx->data[63] = ctx->bitlen[0];
       ctx->data[62] = ctx->bitlen[0] >> 8;
       ctx->data[61] = ctx->bitlen[0] >> 16;
       ctx->data[60] = ctx->bitlen[0] >> 24;
       ctx->data[59] = ctx->bitlen[1];
       ctx->data[58] = ctx->bitlen[1] >> 8;
       ctx->data[57] = ctx->bitlen[1] >> 16;
       ctx->data[56] = ctx->bitlen[1] >> 24;
       sha256_transform(ctx,ctx->data);
    
       // Since this implementation uses little endian byte ordering and SHA uses big endian,
       // reverse all the bytes when copying the final state to the output hash. 
       for (i=0; i < 4; ++i) {
          hash[i]    = (ctx->state[0] >> (24-i*8)) & 0x000000ff;
          hash[i+4]  = (ctx->state[1] >> (24-i*8)) & 0x000000ff;
          hash[i+8]  = (ctx->state[2] >> (24-i*8)) & 0x000000ff;
          hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff;
          hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff;
          hash[i+20] = (ctx->state[5] >> (24-i*8)) & 0x000000ff;
          hash[i+24] = (ctx->state[6] >> (24-i*8)) & 0x000000ff;
          hash[i+28] = (ctx->state[7] >> (24-i*8)) & 0x000000ff;
       }
    }
    
    void print_hash(unsigned char hash[])
    {
       int idx;
       for (idx=0; idx < 32; idx++)
          printf("%02x",hash[idx]);
       printf("\n");
    }
    
    
    struct log_n {
            char uid[BUF_SIZE];
            char pwd[BUF_SIZE];
    };
    
    struct log_n acc[1] = {
            "username","5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
    };
    
    struct log_n query;
    
    
    int main() {
    
            char *hashstr;
            unsigned char hash[BUF_SIZE];
            int idx;
            SHA256_CTX ctx;
    
            do {
                    do{
                            printf("Username: ");
                            fgets(query.uid, sizeof query.uid, stdin);
                            query.uid[strcspn(query.uid, "\n")] = '\0';
                            if (strlen(query.uid) > 15) {
                                    printf("Username must be less than fifteen characters.\nTry again.\n");
                            }
                    } while (strlen(query.uid) > 15);
    
                    do{
                            printf("Password: ");
                            fgets(query.pwd, sizeof query.pwd, stdin);
                            query.pwd[strcspn(query.pwd, "\n")] = '\0';
    
    
                            sha256_init(&ctx);
                            sha256_update(&ctx,query.pwd,strlen(query.pwd));
                            sha256_final(&ctx,hash);
    
                            //conversion from int to string
                            for (idx=0; idx < 32; idx++)
                                    sprintf(&hashstr[idx], "%x",hash[idx]);
    
                            printf("Digest: ");
                            print_hash(hash);
                            printf("Expected: %s\n", acc->pwd);
                            printf("Digest convert: %s\n", hashstr);
                            if (strlen(query.pwd) < 8) {
                                    printf("Password must be atleast eight characters.\nTry again.\n");
                            }
                    } while (strlen(query.pwd) < 8);
            } while (strcmp(query.uid, acc->uid) !=0 || strcmp(hashstr, acc->pwd) !=0);
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    If you look carefully, you'll see you have the first digit of every pair of the expected result.

    So
    Code:
    sprintf(&hashstr[idx*2], "%x",hash[idx]);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2017
    Posts
    2
    Right, you are. Then:
    Code:
    for (idx=0; idx <32; idx++)
                sprintf(&hashstr[idx*2], "%02x",hash[idx]);
    is necessary. Thank you!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to convert char string to user defined data type
    By prdeepss in forum C Programming
    Replies: 5
    Last Post: 08-02-2009, 09:59 AM
  2. Convert String to enum type
    By c9dw2rm8 in forum C Programming
    Replies: 1
    Last Post: 02-23-2008, 07:00 PM
  3. wich hash type?
    By BianConiglio in forum C Programming
    Replies: 2
    Last Post: 10-02-2004, 08:07 AM
  4. How to convert type string to char/double ?
    By Hermitsky in forum C++ Programming
    Replies: 6
    Last Post: 07-08-2004, 03:25 PM
  5. Convert type string to a number
    By ejholmes in forum C# Programming
    Replies: 2
    Last Post: 04-21-2004, 01:33 AM

Tags for this Thread