Converting unsigned char array to hex - c

I want to convert unsigned char to hex (using unsigned int). This is my code so far. I have a program1 that produces an unsigned char array and the other program2 only takes in only hex (using unsigned int), so what i want to achieve is getting an input of unsigned char array and converting that array into hex.
(E.g., program1 outputs "1234567812345678", program2 should output "31323334353637383132333435363738")
Sorry if this question seems dumb. Looked around for answers here but it didn't seem to be what I wanted.
uint64_t phex (unsigned char[16], long);
int main (void) {
int i;
unsigned char key[16] = "1234567812345678";
uint64_t* keyHex = phex(key,16); //store into an array here
for(i = 0; i < 16; i++)
printf("%.2x ", keyHex[i]);
free(keyHex);
return 0;
}
uint64_t phex(unsigned char* string, long len)
{
int i;
//allocate memory for your array
uint64_t* hex = (uint64_t*)malloc(sizeof(uint64_t) * len);
for(i = 0; i < len; ++i) {
//do char to int conversion on every element of char array
hex[i] = string[i] - '0';
}
//return integer array
return hex;
}

If all you need to do is print the values, then you do not need to do any conversion. Just use printf %.2xon the original array.
int main (void) {
int i;
unsigned char key[16] = "1234567812345678";
for(i = 0; i < 16; i++)
printf("%.2x", key[i]);
return 0;
}
Even if you want to use the array in some other function, the actual bytes stored in key are the ascii characters, i.e. 0x31 0x32 etc. You can generally directly use the array key
Edit: To store the output in a character array, you can use the sprintf function.
char hex[33];
for(i = 0; i < 16; i++)
sprintf(hex+2*i, "%.2x", key[i]);
Also note that the original array key should be 17 bytes to account for the \0 at the end.

Here is my take on it - the phex() function converts any data
in memory into a newly allocated string containing the hex representation.
The main() function shows an example usage. The output is "31323334353637383930" for the example data.
#include <stdlib.h> /* malloc() */
#include <stdio.h> /* sprintf() */
#include <string.h> /* strlen(), in the example main() */
/*
* Return a hex string representing the data pointed to by `p`,
* converting `n` bytes.
*
* The string should be deallocated using `free()` by the caller.
*/
char *phex(const void *p, size_t n)
{
const unsigned char *cp = p; /* Access as bytes. */
char *s = malloc(2*n + 1); /* 2*n hex digits, plus NUL. */
size_t k;
/*
* Just in case - if allocation failed.
*/
if (s == NULL)
return s;
for (k = 0; k < n; ++k) {
/*
* Convert one byte of data into two hex-digit characters.
*/
sprintf(s + 2*k, "%02X", cp[k]);
}
/*
* Terminate the string with a NUL character.
*/
s[2*n] = '\0';
return s;
}
/*
* Sample use of `phex()`.
*/
int main(void)
{
const char *data = "1234567890"; /* Sample data */
char *h = phex(data, strlen(data)); /* Convert to hex string */
if (h != NULL)
puts(h); /* Print result */
free(h); /* Deallocate hex string */
return 0;
}

I see the function signature as
uint64_t phex (unsigned char[16], long);
so I think, you do not need array of uint64_t to transform one string, representing one number (perhaps I am wrong and you want to transform each single character from its char-representation to int and show as hexadecimal number).
First, let's consider the following code to transformation in decimal (actually, number in your example - 1234567812345678 - looks like decimal number):
uint64_t phex(unsigned char* string, long len)
{
int i;
//you do not need to allocate memory for array
uint64_t hex = 0; // just one variable
for (i = 0; i < len; ++i) {
hex *= 10; // shift
hex += string[i] - '0'; // add to the smallest rank
}
//return integer Value
return hex;
}
Then for hexadecimal the program will be:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint64_t phex(unsigned char[16], long);
int main(void) {
int i;
unsigned char key[16] = "A123B00CF1";
uint64_t keyHex = phex(key, strlen(key));
printf("%lld(dec) = %llx(hex)", keyHex, keyHex);
return 0;
}
uint64_t phex(unsigned char* string, long len)
{
int i;
uint64_t hex = 0;
for (i = 0; i < len; ++i) {
hex *= 0x10; // shift for one hexadecimal digit
// -'0' for digits 0..9 and -('A'-10) for digits `A`..`F`
hex += toupper(string[i]) - ((string[i] >= 'A') ? ('A' - 10) : '0');
// TODO: Consider making check for characters that are not hexadecimal
// e.g. use isxdigit(string[i]) in some if statement
}
return hex;
}
Note: There is a mistake in your example code - uint64_t* keyHex take the value from function that returns uint64_t (not pointer ``uint64_t*`), but if you accept my idea, you do not need pointer at all.

If the task is to transform chars ('1', '2', etc.) to their hexadecimal representation (31 for '1', 32 for '2', etc.) it is hard to understand why you need uint64_t.
But for your task code can be as follows (without uint64_t):
#include <stdio.h>
#include <string.h>
unsigned int * phex(unsigned char[16], long);
int main(void) {
int i;
unsigned char key[16] = "1234567812345678";
unsigned* keyHex = phex(key, strlen(key)); // strlen(key) to determine number of characters
for (i = 0; i < 16; i++)
printf("%.2x", keyHex[i]); // you do need space as I see from your example
free(keyHex);
return 0;
}
unsigned int * phex(unsigned char* string, long len)
{
int i;
//allocate memory for array
unsigned int * hex = (unsigned int *)malloc(sizeof(unsigned int) * len);
for (i = 0; i < len; ++i) {
//no special conversion needed
hex[i] = string[i];
}
//return array with hexadecimal representation for each character in string
return hex;
}

Related

How to write a word at a time to *char?

I'm trying to implement a version of memset to write a word at a time instead of byte-by-byte.
The code I'm currently working with is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* set in memory one word at a time
dest: destination
ch: the character to write
count: how many copies of ch to make in dest */
void wmemset(char *dest, int ch, size_t count) {
long long int word; // 64-bit word
unsigned char c = (unsigned char) ch; // explicit conversion
int i, loop, remain;
for (i = 0, word = 0; i < 8 ; ++i) {
word |= ((long long int)c << i * 8);
}
loop = count / 8;
remain = count % 8;
for (i = 0; i < loop; ++i, dest += 8) {
*dest = word; // not possible to set 64-bit to char
}
for (i = 0; i < remain; ++i, ++dest) {
*dest = c;
}
}
int main() {
char *c;
c = (char *) malloc(100);
wmemset(c, 'b', 100);
for (int i = 0; i < 100; i++)
printf("%c", c[i]);
}
I thought the 64-bit word would overflow to the rest of the byte of the pointer but it doesn't seem so.
How do I set one word at a time?
EDIT: added a few more comments and added main function.

How to store an ascii value of 0 in a character string without terminating it?

Taking an input as hex string and then converting it to char string in C. The hex string can contain 0x00 which translates to an 0 in Ascii when converted. This terminates the string. I have to store the value in an char string because the API uses that.
My code so far:
int hex_to_int(unsigned char c) {
int first =0;
int second =0;
int result=0;
if(c>=97 && c<=102)
c-=32;
first=c / 16 - 3;
second =c % 16;
result = first*10 + second;
if(result > 9) result--;
return result;
}
unsigned char hex_to_ascii(unsigned char c, unsigned char d){
unsigned char a='0';
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
a= high+low;
return a;
}
unsigned char* HextoString(unsigned char *st){
int length = strlen((const char*)st);
unsigned char* result=(unsigned char*)malloc(length/2+1);
unsigned char arr[500];
int i;
unsigned char buf = 0;
int j=0;
for(i = 0; i < length; i++)
{
if(i % 2 != 0)
{
arr[j++]=(unsigned char)hex_to_ascii(buf, st[i]);
}
else
{
buf = st[i];
}
}
arr[length/2+1]='\0';
memcpy(result,arr,length/2+1);
return result;
}
You can store any values in a char array. But if you want to store a value of 0x00, you cannot use the string functions on this array. So you have to use an integer variable to store the length of the data you want to store. You can then write functions that use this integer.
As you provided more information now, I can tell you that your function doesn't cut anything as it loops through the whole C-string which you provided for example as input "0a12345600a0020b12". The "problem" is that if you want to get the length (strlen()) of the output string after the conversion for example then it will stop at '\0' and you will get a "wrong" length in terms of your original input string.
It is exacly like it's written in the answer of Xaver save the length information and the string to work with that length and not the one you would get by the C-string functions like strlen().
To show that and in order to provide a right length information I've added a struct definition to your code that defines a string type consisting of a size_t len and an unsigned char* str called HexString. With the additional length information you can handle a 0 byte. Also I made little changes to your code, e.g. you don't need that character buffer arr on the stack.
With your input: "0a12345600a0020b12"
the following output you will see: <0a> <12> <34> <56> <00> <a0> <02> <0b> <12> <00>
if you print the C-string hexadecimal every single character. The last <00> is the null termination.
Look here on ideone for a live example.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
size_t len; /* C-string length + '\0' */
unsigned char* str;
} HexString;
int hex_to_int(unsigned char c)
{
int first =0;
int second =0;
int result=0;
if (c >= 97 && c <= 102) /* 97 = 'a'; 102 = 'f' */
c -= 32;
first = c / 16 - 3;
second = c % 16;
result = first * 10 + second;
if (result > 9) result--;
return result;
}
unsigned char hex_to_ascii(unsigned char c, unsigned char d)
{
unsigned char a = '0';
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
a = high + low;
return a;
}
HexString HextoString(const char* const st)
{
HexString result;
size_t length = strlen(st);
result.len = length/2+1;
result.str = malloc(length/2+1);
size_t i;
size_t j = 0;
unsigned char buf = 0;
for (i = 0; i < length; i++)
{
if (i % 2 != 0)
{
result.str[j++] = hex_to_ascii(buf, st[i]);
}
else
{
buf = (unsigned char)st[i];
}
}
result.str[length/2+1] = '\0';
return result;
}
int main()
{
size_t i;
HexString hexString = HextoString("0a12345600a0020b12");
for (i = 0; i < hexString.len; ++i)
{
printf("<%02x> ", hexString.str[i]);
}
free(hexString.str);
return 0;
}

How to convert literal char hex value into the hex value itself?

I'm having the literal value that should be stored on an unsigned char[64] array. How can I convert such values to it's hex equivalent?
int main() {
unsigned char arry[1] = { 0xaa }
char* str = "fe"; //I want to store 0xfe on arry[0]
arry[0] = 0xfe; // this works, but I have to type it
arry[0] = 0x + str; //obviously fails
return 0;
}
Any pointers?
arr[0] = strtol(str,NULL,16); // If one entry is big enough to hold it.
For each character c, the value is:
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return c - 'a' + 10;
if ('A' <= c && c <= 'F') return c - 'A' + 10;
// else error, invalid digit character
Now just iterate over the string from left to right, adding up the digit values, and multiplying the result by 16 each time.
(This is implemented for you by the standard library in the strto*l functions with base 16.)
Use function strtol() to convert a string to a long in a specific base: http://www.cplusplus.com/reference/cstdlib/strtol/
"Parses the C-string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number."
Example:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
int main ()
{
char szNumbers[] = "2001 60c0c0 -1101110100110100100000 0x6fffff";
char * pEnd;
long int li1, li2, li3, li4;
li1 = strtol (szNumbers,&pEnd,10);
li2 = strtol (pEnd,&pEnd,16);
li3 = strtol (pEnd,&pEnd,2);
li4 = strtol (pEnd,NULL,0);
printf ("The decimal equivalents are: %ld, %ld, %ld and %ld.\n", li1, li2, li3, li4);
return 0;
}
Put together an arbitrary length solution to and from.
Sadly the String to X is verbose: pesky dealing with non hex string, odd length, too big, etc.
#include <string.h>
#include <stdio.h>
// S assumed to be long enough.
// X is little endian
void BigXToString(const unsigned char *X, size_t Length, char *S) {
size_t i;
for (i = Length; i-- > 0; ) {
sprintf(S, "%02X", X[i]);
S += 2;
}
}
int BigStringToX(const char *S, unsigned char X[], size_t Length) {
size_t i;
size_t ls = strlen(S);
if (ls > (Length * 2)) {
return 1; //fail, too big
}
int flag = ls & 1;
size_t Unused = Length - (ls/2) - flag;
memset(&X[Length - Unused], 0, Unused); // 0 fill unused
char little[3];
little[2] = '\0';
for (i = Length - Unused; i-- > 0;) {
little[0] = *S++;
little[1] = flag ? '\0' : *S++;
flag = 0;
char *endptr;
X[i] = (unsigned char) strtol(little, &endptr, 16);
if (*endptr) return 1; // non-hex found
if (*S == '\0') break;
}
return 0;
}
int main() {
unsigned char X[64];
char S[64 * 2 + 2];
char T[64 * 2 + 2];
strcpy(S, "12345");
BigStringToX(S, X, sizeof(X));
BigXToString(X, sizeof(X), T);
printf("'%s'\n", T);
return 0;
}

printf with %s to include null characters

I need to concatenate some strings, and I need to include NULL bytes. I don't want to treat a '\0' as a terminating byte. I want to save my valuable NULL bytes!
In a code example, if
char *a = "\0hey\0\0";
I need to printf in a format that will output "\0hey\0\0".
-AUstin
How about:
int i;
for(i = 0; i < 4; i++)
printf("%c", a[i]);
If you want a 'printf-like' function to use this when you specify %s in a format string you could include the above code in your own function. But as #Neil mentioned, you'll struggle finding an alternative to looking for null bytes to determine the length of strings. For that I guess you could use some kind of escape character.
The issue here is that the length of the string a cannot be easily determined. For example, your code..
char *a = "\0hey\0\0";
.. allocates seven bytes to the string, the last being the NULL terminator. Using a function like strlen would return 0.
If you know the precise length of the string, then you can write or iterate over the bytes thus:
#ifdef ESCAPE_NULLS
int i;
for (i = 0; i <= 6; i++)
if (a[i] == 0)
printf("\\0");
else
printf("%c", a[i]);
#else
write(1, a, 6);
#endif
But you have to know about the 6.
The alternative is not to use NULL-terminated strings, and instead implement an alternative storage mechanism for your bytes; for example a length-encoded array.
#include <stdio.h>
typedef struct {
int length;
char *bytes;
} bytearr;
void my_printf(bytearr *arr)
{
#ifdef ESCAPE_NULLS
int i;
for (i = 0; i <= arr->length; i++)
if (arr->bytes[i] == 0)
printf("\\0");
else
printf("%c", arr->bytes[i]);
#else
write(1, arr->bytes, arr->length);
#endif
}
void main(void)
{
bytearr foo = {
6, "\0hey\0\0"
};
my_printf(&foo);
}
Graceless, but hopefully you get the idea.
Edit: 2011-05-31
Rereading the question I just noticed the word "concatenate". If the NULL characters are to be copied faithfully from one place in memory to another (not backslash-escape), and you know the total number of bytes in each array beforehand, then you can simply use memcpy.
#include <string.h>
char *a = "\0hey\0\0"; /* 6 */
char *b = "word\0up yo"; /* 10 */
char *c = "\0\0\0\0"; /* 4 */
void main(void)
{
char z[20];
char *zp = z;
zp = memcpy(zp, a, 6);
zp = memcpy(zp, b, 10);
zp = memcpy(zp, c, 4);
/* now z contains all 20 bytes, including 8 NULLs */
}
char *a="\0hey\0\0";
int alen = 7;
char buf[20] = {0};
int bufSize = 20;
int i=0;
int j=0;
while( i<bufSize && j<alen )
{
if(a[j]=='\0') {
buf[i++]='\\';
buf[i++]='0';
j++;
}
else {
buf[i++] = a[j++];
}
}
printf(buf);

Hex to ascii string conversion

i have an hex string and want it to be converted to ascii string in C. How can i accomplish this??
you need to take 2 (hex) chars at the same time... then calculate the int value
and after that make the char conversion like...
char d = (char)intValue;
do this for every 2chars in the hex string
this works if the string chars are only 0-9A-F:
#include <stdio.h>
#include <string.h>
int hex_to_int(char c){
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d){
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
int main(){
const char* st = "48656C6C6F3B";
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++){
if(i % 2 != 0){
printf("%c", hex_to_ascii(buf, st[i]));
}else{
buf = st[i];
}
}
}
Few characters like alphabets i-o couldn't be converted into respective ASCII chars .
like in string '6631653064316f30723161' corresponds to fedora . but it gives fedra
Just modify hex_to_int() function a little and it will work for all characters.
modified function is
int hex_to_int(char c)
{
if (c >= 97)
c = c - 32;
int first = c / 16 - 3;
int second = c % 16;
int result = first * 10 + second;
if (result > 9) result--;
return result;
}
Now try it will work for all characters.
strtol() is your friend here. The third parameter is the numerical base that you are converting.
Example:
#include <stdio.h> /* printf */
#include <stdlib.h> /* strtol */
int main(int argc, char **argv)
{
long int num = 0;
long int num2 =0;
char * str. = "f00d";
char * str2 = "0xf00d";
num = strtol( str, 0, 16); //converts hexadecimal string to long.
num2 = strtol( str2, 0, 0); //conversion depends on the string passed in, 0x... Is hex, 0... Is octal and everything else is decimal.
printf( "%ld\n", num);
printf( "%ld\n", num);
}
If I understand correctly, you want to know how to convert bytes encoded as a hex string to its form as an ASCII text, like "537461636B" would be converted to "Stack", in such case then the following code should solve your problem.
Have not run any benchmarks but I assume it is not the peak of efficiency.
static char ByteToAscii(const char *input) {
char singleChar, out;
memcpy(&singleChar, input, 2);
sprintf(&out, "%c", (int)strtol(&singleChar, NULL, 16));
return out;
}
int HexStringToAscii(const char *input, unsigned int length,
char **output) {
int mIndex, sIndex = 0;
char buffer[length];
for (mIndex = 0; mIndex < length; mIndex++) {
sIndex = mIndex * 2;
char b = ByteToAscii(&input[sIndex]);
memcpy(&buffer[mIndex], &b, 1);
}
*output = strdup(buffer);
return 0;
}

Resources