Thread: How to convert char string of Hex characters to unsigned char string of binary data

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    124

    How to convert char string of Hex characters to unsigned char string of binary data

    I am trying to convert a hexadecimal character array to a binary string (unsigned char) that I can use in crypto functions using Cryptlib or OpenSSL. Basically I have a Hex representation of a key like (02726d40f378e716981c4321d60ba3a3) which as a character string is 32 characters but as a binary string should be 16 bytes.

    The character string is being read in from a file, how can I convert it to its binary representation as an unsigned char array?

    Thanks.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    If it's being read in as characters, read in two at a time and write one byte.

  3. #3
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    How?

    The string is being read from a file with fgets() and being stored in a char*

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Then go through the stored string in your char* two at a time and write out one byte at a time.

  5. #5
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    I don't think that will work. I'm reading in characters from a file and I need to convert them to binary. I need one character in an unsigned char array to represent one byte (two characters) from a char array.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by maxhavoc View Post
    I don't think that will work. I'm reading in characters from a file and I need to convert them to binary. I need one character in an unsigned char array to represent one byte (two characters) from a char array.
    Of course it's possible; in fact, it's trivial. If you need it spelled out, well, let's spell it out:
    1. Decide the numerical value of the first character in a byte pair (0-15).
    2. Shift this value over four bits to the left.
    3. Add the numerical value of the second character in a byte pair (0-15).
    4. Lather, rinse, repeat.

    If you can come up with a way to only give strtoul two characters at a time, it becomes even more trivial.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Or do repeated
    Code:
    sscanf(&input_string[i], "%02x", &number);
    byte_string[j] = (unsigned char)number
    every 2 bytes.

  8. #8
    Registered User
    Join Date
    Jun 2004
    Posts
    124
    Ok, sorry guys, I'm a bit slow. Here's the function I've put together based on nonoob's answer:

    Code:
    void stringToHex(unsigned char* hexString, char* string, int stringLength)
    {
    	unsigned char uChar = 0;
    	
    	for (int x = 0; x < stringLength; x++)
    	{
    		sscanf_s(&string[x], "%02x", &uChar);
    		hexString[x] = uChar;
    	}
    }
    I'm getting a runtime error about stack corruption on uChar. What am I doing wrong?

  9. #9
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You need to put the result into an int first. Then cast it and assign to char like in my example. Your x should go up by 2 indexing string[]. But where your destination is into hexString the index should go up by 1s.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    sscanf is really the best option here, of course - this is just an example of doing it 'by hand':

    Code:
    int
    hex_char_to_binary( char ch, char* ret )
    {
          ch = tolower( ch );      
          if( isdigit( ch ) )
                *ret = ch - '0';             
          else if( ch >= 'a' && ch <= 'f' )
                *ret = ( ch - 'a' ) + 10;  
          else
                return *ret = 0;
          return 1;       
    }
     
    char*
    hex_to_binary_copy( const char* str, char* ret )
    {
          char
                * cpy = ret, 
                low, 
                high;
          if( strlen( str ) &#37; 2 )
          {
                *ret = 0;
                return 0;
          }
          for( const char* ptr = str; *ptr; ptr += 2 )
          {
                if
                ( 
                      !hex_char_to_binary( *ptr, &high ) 
                      ||
                      !hex_char_to_binary( *( ptr + 1 ), &low ) 
                )
                {
                      *ret = 0;
                      return 0;
                }
                *cpy++ = low | ( high << 4 );  
          }
          *cpy = 0;
          return ret;                              
    }
    [edit]
    Or perhaps better yet:
    [/edit]

    Code:
    int
    hex_to_binary( const char* str, void* buf, int* siz )
    {
          char
                * cpy = ( char* )buf, 
                low, 
                high;
          const char
                * ptr = str;
          int
                unused,
                len = strlen( str ), 
                half = len / 2, 
                odd = len % 2;
          if( siz == 0 )
                siz = &unused;
          if( odd )
          {
          /*
                a bit of a hack...
          */
                --ptr;
                ++half;
                high = 0;
                goto skip;
          }
          for( ; *ptr; ptr += 2 )
          {
                if( !hex_char_to_binary( *ptr, &high ) ) 
                      return *siz = 0;
                skip:                  
                if( !hex_char_to_binary( *( ptr + 1 ), &low ) )
                      return *siz = 0;
                *cpy++ = low | ( high << 4 );  
          }
          return *siz = half;                              
    }
    Last edited by Sebastiani; 10-04-2008 at 12:52 PM. Reason: additions, corrections
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    Registered User
    Join Date
    Jun 2011
    Posts
    1

    Thanks Guys

    I know this post was a while ago but thanks for your answers! Specially to nonoob...
    Saved me time and effort...

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Click the "like" link then, instead of digging up dead threads, as mentioned in the rules as something NOT to do.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 04-25-2008, 02:45 PM
  2. get keyboard and mouse events
    By ratte in forum Linux Programming
    Replies: 10
    Last Post: 11-17-2007, 05:42 PM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM