Following on an old question Converting hex to string in C?
The approved answer suggests to use sprintf to convert each hex to string.
I have two question on this -
1) When i have a hex like 0a i want my string to have 0a too, but following the above solution the result will have a.
2) What am i doing wrong here?
#include <stdio.h>
int main(void)
{
unsigned char readingreg[10];
readingreg[0] = 0x4a;
readingreg[1] = 0xab;
readingreg[2] = 0xab;
readingreg[3] = 0x0a;
readingreg[4] = 0x40;
unsigned char temp[10];
int i = 0;
while (i < 5)
{
sprintf(temp + i, "%x", readingreg[i]);
i++;
}
printf("String: %s\n", temp);
return 0;
}
The o/p seems to - String: 4aaa40
3) Combining both the both questions, i want my result string to be 4aabab0a40
TIA
Your code has several problems.
First unsigned char temp[10]; should be unsigned char temp[11]; to contain a string terminator.
Next is the format spec "%x" should be "%02x" so each value is 2 digits.
Then temp + i should be temp + i*2 so each pair of digits is written in the right place.
Correcting those mistakes:
#include <stdio.h>
int main(void)
{
unsigned char readingreg[10];
readingreg[0] = 0x4a;
readingreg[1] = 0xab;
readingreg[2] = 0xab;
readingreg[3] = 0x0a;
readingreg[4] = 0x40;
unsigned char temp[11];
int i = 0;
while (i < 5)
{
sprintf(temp + i*2, "%02x", readingreg[i]);
i++;
}
printf("String: %s\n", temp);
return 0;
}
Program output is now the required
String: 4aabab0a40
Related
I'm using the library OpenSSL for encrypting through AES. Since AES is a block cipher, I need to split the data in chunks of 16 bytes. Thus, if I want to recover the message, I need to unite the chunks at the end of the program.
This is my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey123";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
int i;
int k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
in[160] = '\0';
printf("IN:%s\n", in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
text_slice[0] = '\0';
enc_slice[0] = "\0";
dec_slice[0] = "\0";
memcpy(&text_slice[0], &in[15 * i], 15);
text_slice[16] = "\0";
printf("TEXT SLICE: %s \n", text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], &enc_slice[0], 16);
}
printf("ENC:%s\n", enc_out);
for (i = 0; i < k; i++) {
text_slice[0] = '\0';
enc_slice[0] = "\0";
dec_slice[0] = "\0";
memcpy(enc_slice, &enc_out[16 * i], 16);
enc_slice[16] = "\0";
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice:%s \n", dec_slice);
memcpy(&dec_out[16 * i], &dec_slice[0], 16);
}
printf("DEC OUT:%s\n", dec_out);
return 0;
}
The output of the program is the following:
IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ
TEXT SLICE: OWKKYHIDDQSCDXR
TEXT SLICE: JMOWFRXSJYBLDBE
TEXT SLICE: FSARCBYNECDYGGX
TEXT SLICE: XPKLORELLNMPAPQ
TEXT SLICE: FWKHOPKMCOQHNWN
TEXT SLICE: KUEWHSQMGBBUQCL
TEXT SLICE: JJIVSWMDKQTBXIX
TEXT SLICE: MVTRRBLJPTNSNFW
TEXT SLICE: ZQFJMAFADRRWSOF
ENC:j�Q���
𢨫�7֡���*n���R ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ
Dec slice:OWKKYHIDDQSCDXR
Dec slice:JMOWFRXSJYBLDBE
Dec slice:FSARCBYNECDYGGX
Dec slice:XPKLORELLNMPAPQ
Dec slice:FWKHOPKMCOQHNWN
Dec slice:KUEWHSQMGBBUQCL
Dec slice:JJIVSWMDKQTBXIX
Dec slice:MVTRRBLJPTNSNFW
Dec slice:ZQFJMAFADRRWSOF
DEC OUT:NWLRBBMQBHCDARZ
While dec_slice works as expected, dec_out just get a copy of the memory of the first chunk. What is more surprising for me, is that enc_out performs correctly when following the same logic as dec_out. What am I missing?
The key must have at least 16 bytes since you pass a number of bits equal to 128 in:
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
You have undefined behavior here:
in[160] = '\0';
These lines don't make sense:
enc_slice[0] = "\0";
dec_slice[0] = "\0";
text_slice[16] = "\0";
enc_slice[16] = "\0";
Why do you encode chunks of 15 characters instead of 16?
memcpy(&text_slice[0], &in[15 * i], 15);
Here is a modified version:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>
char key[] = "secretkey1234567";
int main() {
unsigned char text_slice[128];
unsigned char enc_slice[128];
unsigned char dec_slice[128];
unsigned char in[160];
unsigned char enc_out[160];
unsigned char dec_out[160];
int i, k = 10;
for (i = 0; i < 16 * k; i++) {
in[i] = 'A' + (rand() % 26);
}
printf("IN: \"%.160s\"\n", (char *)in);
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);
for (i = 0; i < k; i++) {
memcpy(text_slice, &in[16 * i], 16);
printf("TEXT SLICE: %.16s\n", (char *)text_slice);
AES_encrypt(text_slice, enc_slice, &enc_key);
memcpy(&enc_out[16 * i], enc_slice, 16);
}
printf("ENC:");
for (i = 0; i < 16 * k; i++) {
printf(" %02X\n", enc_out[i]);
}
printf("\n");
for (i = 0; i < k; i++) {
memcpy(enc_slice, &enc_out[16 * i], 16);
AES_decrypt(enc_slice, dec_slice, &dec_key);
printf("Dec slice: %.16s \n", (char *)dec_slice);
memcpy(&dec_out[16 * i], dec_slice, 16);
}
printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
return 0;
}
There are many problems in that code.
The AES_set_encrypt_key and AES_set_decrypt_key are not key derivation functions, the second parameter is supposed to represent the length in bits of the first parameter (userKey).
If you provide an arbitrary string constant like "secretkey123" with a length that is not 128 in bits, it may cause memory corruption or create a very insecure context for your encryption.
In general, for user password based encryption, we generate a key from any password using a key derivation function (for example PBKDF2, or scrypt).
This line is also bad:
in[160] = '\0';
Since the buffer has a size of 160, the last index should be 160 - 1. If you write at index 160, you are actually overflowing.
Also, you must really notice the difference between single quote and double quotes when writing C code.
This is bad:
enc_slice[0] = "\0";
dec_slice[0] = "\0";
If you use double quotes, you are not actually writing the value 0 at the first index of enc_slice and dec_slice. You are writing the address of an empty read-only constant string.
Also this:
unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";
If you want to have empty buffers, you should just do:
unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};
Hopefully this is a good start to improve your code and make it work.
I wrote a c program to perform sha256 hash on a char array and then perform ripemd160 hash on the output of sha256 hash function.
here is my code:
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
int main(){
int c;
const unsigned char* rawdata = "046EAF0968AA895ADDFEE599566F0B880242461D1377F4887C9B84631E13067B96DB18C41E0C208F8D12EBCC3F99F2522903AF6105833E4CBADE9D6A1D0F039187";
unsigned long n = strlen(rawdata);
unsigned char *d = SHA256(rawdata, strlen(rawdata), 0);
for (c = 0; c < 32; c++){
printf("%02x", d[c]);
}
putchar('\n');
unsigned char md[32];
unsigned char* pmd = RIPEMD160(d, strlen(d), md);
int i;
for (i = 0; i < 20; i++)
printf("%02x", pmd[i]);
putchar('\n');
return 0;
}
the problem is in this line :
unsigned char *d = SHA256(raw-data, strlen(raw-data), 0);
when I pass the d pointer which is the output of the sha256 function to RIPEMD160 function the resulting hash output of RIPEMD160 function becomes wrong. Can anyone tell me why this is happening? And how can correct my code to print and store my ripems160 hash in a char array?
Here is what I have tried:
the resulting hash output of the string "046EAF0968AA895ADDFEE599566F0B880242461D1377F4887C9B84631E13067B96DB18C41E0C208F8D12EBCC3F99F2522903AF6105833E4CBADE9D6A1D0F039187"
is : 37a0df85d5ccf7cb5f92b53aa3f223d76c115a844ed52d8978deecd2ecb3e406
which is correct.
But the ripemd160 hash of "37a0df85d5ccf7cb5f92b53aa3f223d76c115a844ed52d8978deecd2ecb3e406"
should be
"4ecc9d3eea56b0af96b6db612b76911858dcb40d"
but my is wrong.
here is the output of my code when compiled with this command
"gcc sha256.c -lssl -lcrypto -Wno-deprecated-declarations"
output:
37a0df85d5ccf7cb5f92b53aa3f223d76c115a844ed52d8978deecd2ecb3e406
63bb23be08e2c097008c4c272cc56c14e5656831
the second string "63bb23be08e2c097008c4c272cc56c14e5656831" is ripemd160 hash which is wrong
Your problem is on this line:
unsigned char* pmd = RIPEMD160(d, strlen(d), md);
strlen finds the length of a printable string by looking for the terminating \0. But the data in d is binary data. It is not terminated by \0 and may contain that value as part of the data. You should replace strlen(d) with the actual value for the length of a SHA256 hash (32).
Update:
It seems your "correct" output can be achieved by doing some further processing of the SHA256 output. I don't know where you got your test vector from but it seems the expected input into the RIPEMD160 function is the SHA256 output converted into a printable string - and hashing that string.
These modifications seem to achieve the output that you are expecting:
--- doublehash1.c 2020-03-21 00:50:11.882423750 +0000
+++ doublehash.c 2020-03-21 00:49:36.778485523 +0000
## -9,14 +9,16 ##
const unsigned char* rawdata = "046EAF0968AA895ADDFEE599566F0B880242461D1377F4887C9B84631E13067B96DB18C41E0C208F8D12EBCC3F99F2522903AF6105833E4CBADE9D6A1D0F039187";
unsigned long n = strlen(rawdata);
unsigned char *d = SHA256(rawdata, strlen(rawdata), 0);
+ unsigned char data[65], *p;
- for (c = 0; c < 32; c++){
- printf("%02x", d[c]);
+ for (c = 0, p = data; c < 32; c++, p += 2){
+ sprintf(p, "%02x", d[c]);
}
+ printf("%s", data);
putchar('\n');
unsigned char md[32];
- unsigned char* pmd = RIPEMD160(d, strlen(d), md);
+ unsigned char* pmd = RIPEMD160(data, strlen(data), md);
int i;
for (i = 0; i < 20; i++)
I have been trying to convert a binary number into a char, I use the following code to convert the char into binary:
void bin(char x){
int y;
for(y = 0; y < sizeof(char) * 8; y++){
fprintf(f2,"%c", ( x & (1 << y) ) ? '1' : '0' );
}}
And it works fine.
The problem is that I don't know how to undo it, I want to get this binary number and convert it to the initial char. I'm using the folliwing code but it generates a core problem.
char subbuff[9];
memcpy( subbuff, &fichero[0], 8 );
subbuff[8] = '\0';
for(int k=8;k<fichero_len;k+=8){
char c = strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
memcpy( subbuff, &fichero[k], k+8 );
subbuff[8] = '\0';
}
for exaple if i convert the string "hola" the first code shows "00010110111101100011011010000110"
but if i put that into the second code:
const char *hola="00010110111101100011011010000110";
char subbuff[16];
memcpy( subbuff, hola[0], 8 );
subbuff[8] = '\0';
for(int k=8;k<strlen(hola);k+=8){
char c = strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
memcpy( subbuff, &hola[k], k+8 );
subbuff[8] = '\0';
}
it generates a core problem
EDIT 1:
One problem is that you are copying too many bytes into subbuff with
memcpy( subbuff, &fichero[k], k+8 );
Another is that you pass a bad pointer to memcpy with
memcpy( subbuff, hola[0], 8 );
which will cause a segfault. Please enable compiler warnings.
There is no need even to do that first, outside of the loop. It can be done similar like this
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
const char *hola = "01101000011011110110110001100001";
char subbuff[9];
char result [256] = "";
unsigned char c;
int k;
int index = 0;
int fichero_len = (int)strlen(hola);
for(k = 0; k < fichero_len; k += 8) {
memcpy(subbuff, &hola[k], 8); // <--- copy 8 butes only
subbuff[8] = '\0';
c = (unsigned char)strtol(subbuff, 0, 2);
printf("%s = %c = %d = 0x%.2X\n", subbuff, c, c, c);
result[index++] = c;
result[index] = '\0';
}
printf("Result = %s\n", result);
return 0;
}
Finally your bit sequences are reversed, so you won't get the char back that you started with!
EDIT 2: after adding a few lines to the above code and reversing the bits in the hola definition, I get this output. Obviously you must make sure that result[] is long enough.
Program output:
01101000 = h = 104 = 0x68
01101111 = o = 111 = 0x6F
01101100 = l = 108 = 0x6C
01100001 = a = 97 = 0x61
Result = hola
I have a 4 byte string of hex characters and I want to convert them into a 2 byte integer in c.
I cannot use strtol, fprintf or fscanf.
I want this:-
unsigned char *hexstring = "12FF";
To be converted to this:-
unsigned int hexInt = 0x12FF
EDIT: Doh, just read azmuhak's suggested link. This is definitely a duplicate of that question. The answer in azmuhak's link is also more complete because it deals with "0x" prefixes...
The following will work with out using the standard library...
See it on ideone here
#include <stdio.h>
#define ASCII_0_VALU 48
#define ASCII_9_VALU 57
#define ASCII_A_VALU 65
#define ASCII_F_VALU 70
unsigned int HexStringToUInt(char const* hexstring)
{
unsigned int result = 0;
char const *c = hexstring;
char thisC;
while( (thisC = *c) != NULL )
{
unsigned int add;
thisC = toupper(thisC);
result <<= 4;
if( thisC >= ASCII_0_VALU && thisC <= ASCII_9_VALU )
add = thisC - ASCII_0_VALU;
else if( thisC >= ASCII_A_VALU && thisC <= ASCII_F_VALU)
add = thisC - ASCII_A_VALU + 10;
else
{
printf("Unrecognised hex character \"%c\"\n", thisC);
exit(-1);
}
result += add;
++c;
}
return result;
}
int main(void)
{
printf("\nANSWER(\"12FF\"): %d\n", HexStringToUInt("12FF"));
printf("\nANSWER(\"abcd\"): %d\n", HexStringToUInt("abcd"));
return 0;
}
The code could be made more efficient and I use the toupper library function, but you could easily implement that yourself...
Also, this won't parse strings beginning with "0x"... but you could add a quick check for that at the beginning of the function and just chew up those characters...
You could use strtol() from stdlib.h
http://www.tutorialspoint.com/c_standard_library/c_function_strtol.htm
char str[30] = "0x12FF";
char **ptr;
long val;
val = strtol(str, ptr, 16);
I have a string (unsigned char) and i want to fill it with only hex characters.
my code is
unsigned char str[STR_LEN] = {0};
for(i = 0;i<STR_LEN;i++) {
sprintf(str[i],"%x",rand()%16);
}
Of course, when running this I get segfaulted
string is an array of char-s not unsigned char-s
you are using str[i] (which is of type unsigned char) as a 1st argument to sprintf, but it requires type char * (pointer).
This should be a little better:
char str[STR_LEN + 1];
for(i = 0; i < STR_LEN; i++) {
sprintf(str + i, "%x", rand() % 16);
}
The first argument to sprintf() should be a char*, but str[i] is a char: this is the cause of the segmentation fault. The compiler should have emitted a warning about this. gcc main.c, without specifying a high warning level, emitted the following:
warning: passing argument 1 of sprintf makes pointer from integer without a cast
A hex representation of a character can be 1 or 2 characters (9 or AB for example). For formatting, set the precision to 2 and the fill character to 0. Also need to add one character for the terminating null to str and set the step of the for loop to 2 instead of 1 (to prevent overwriting previous value):
unsigned char str[STR_LEN + 1] = {0};
int i;
for (i = 0; i < STR_LEN; i += 2)
{
sprintf(&str[i], "%02X", rand() % 16);
}
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#define STR_LEN 20
int main(void)
{
unsigned char str[STR_LEN + 1] = {0};
const char *hex_digits = "0123456789ABCDEF";
int i;
for( i = 0 ; i < STR_LEN; i++ ) {
str[i] = hex_digits[ ( rand() % 16 ) ];
}
printf( "%s\n", str );
return 0;
}
There are several unclarities and problems in your code. I interpret "hex character" to mean "hex digit", i.e. a symbol from {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}, not "the hexadecimal value of an ascii character's code point". This might or might not be what you meant.
This should do it:
void hex_fill(char *buf, size_t max)
{
static const char hexdigit[16] = "0123456789abcdef";
if(max < 1)
return;
--max;
for(i = 0; i < max; ++i)
buf[i] = hexdigit[rand() % sizeof hexdigit];
buf[max] = '\0';
}
The above will always 0-terminate the string, so there's no requirement that you do so in advance. It will properly handle all buffer sizes.
My variation on some of answers below; note the time seeded rand function and instead of a char using a const size, I use a vector that is then converted to a string array.
Boost variate generator docs
std::string GetRandomHexString(unsigned int count)
{
std::vector<char> charVect = std::vector<char>(count);
//Rand generator
typedef boost::random::mt19937 RNGType;
RNGType rng(std::time(nullptr) + (unsigned int)clock());
//seeding rng
uniform_int<> range(0, 15); //Setting min max
boost::variate_generator<RNGType, boost::uniform_int<> >generate(rng, range); //Creating our generator
//Explicit chars to sample from
const char hexChars[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
//
for (int i = 0; i < count; i++)
{
charVect[i] = hexChars[generate()];
}
//
return std::string(charVect.begin(), charVect.end());;
}
Examples (count = 32):
1B62C49C416A623398B89A55EBD3E9AC
26CFD2D1C14B9F475BF99E4D537E2283
B8709C1E87F673957927A7F752D0B82A
DFED20E9C957C4EEBF4661E7F7A58460
4F86A631AE5A05467BA416C4854609F8