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++)
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.
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
I have a query. I have a string of ascii value . which i am reading from Hex file. consider the string is "0004EB9C" . which is copied in unsigned char buffer.
unsigned char buff[8] = {'0','0','0','4','E','B','9','C'}
unsigned int j = 0;
Now this string or information has to be transmitted through UART communication. consider this represents my RAM address for Execution. I need to store this 8 byte ascii value in in an unsigned int . I am not finding a way can some one please focus on this.
the output after copying/converting this string should be like
printf("%x",j);
this should print
Output : 0x0004EB9C
thanks in advance!!
set answer to 0
for each character
left-shift answer by 4
if the character is between '0' and '9' inclusive
subtract '0' from it
else
subtract 'A' from it and add 10
bitwise-or this into answer
#include <stdio.h>
int main(){
char data[] = "004EB59C";
const int len = sizeof(data)/sizeof(char)-1;
int i,value[sizeof(data)/sizeof(char)-1];
unsigned int j = 0;
for(i=0;i<len;++i)
sscanf(data+i, "%1x",value + i);
for(i=0;i<len;i++)
{
j <<= 4;
j |= (0x0f & value[i]);
printf("%x\n",j);
}
return 0;
}
Corrected Code. I would request to improvise this answer if possible.
To store as unsigned j
unsigned char buff[8] = {'0','0','0','4','E','B','9','C'}
unsigned char buff2[sizeof buff + 1];
memcpy(buff2, buff, sizeof buff);
buff2[sizeof buff] = '\0';
unsigned int j = (unsigned) strtoul(buff2, 0, 16);
To print via j
printf("%#08x",j);
To print via directly via buff
fputs("0x", stdout);
for (size_t i = 0; i < sizeof buff; i++)
fputc(tolower(buff[i]), stdout);
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
I have a hexadecimal value "F69CF355B6231FDBD91EB1E22B61EA1F" in a string and I am using this value in my program by hardcoding the value in an unsigned char variable like this:
unsigned char a[] = { 0xF6 ,0x9C ,0xF3 ,0x55 ,0xB6 ,0x23 ,0x1F ,0xDB ,0xD9 ,0x1E ,0xB1 ,0xE2 ,0x2B ,0x61 ,0xEA ,0x1F};
Is there any function or any other method by which I can take the value from a string and put it into an unsigned variable in the hexadecimal format by packing it?
#include <stdio.h>
#include <ctype.h>
int hctoi(const char h){
if(isdigit(h))
return h - '0';
else
return toupper(h) - 'A' + 10;
}
int main(void){
const char cdata[]="F69CF355B6231FDBD91EB1E22B61EA1F";
unsigned char udata[(sizeof(cdata)-1)/2];
const char *p;
unsigned char *up;
for(p=cdata,up=udata;*p;p+=2,++up){
*up = hctoi(p[0])*16 + hctoi(p[1]);
}
{ //check code
int i;
for(i=0;i<sizeof(udata);++i)
printf("%02X", udata[i]);
}
return 0;
}
You can translate a hexadecimal value in a string into a value using sscanf. If you want an array of values, then you could write a function to split up the input string into two character segments and use sscanf to convert each piece. (I haven't done C for an eternity so I don't know if that's a good way to do it.)
If it's for 32 single hex-values (16 bytes, 128bit) only then you might take look at the methods provided by libuuid.
libuuid is part of the e2fsprogs package. Anyhow some linux distros, Debian for example, ship libuuid as a separate package. To use the Debian package for your developement you also need to look here.
Check this answer for doing this stuff in c++ using sscanf().
For c, it would be something like this:
char *str = "F69CF355B6231FDBD91EB1E22B61EA1F";
char substr[3] = "__";
unsigned char *a = NULL;
len = strlen(str);
a = malloc(sizeof(unsigned char)*(len/2)+1);
for ( i = 0; i < len/2; i++) {
substr[0] = str[i*2];
substr[1] = str[i*2 + 1];
sscanf( substr, "%hx", &a[i] );
}
free(a);
Introduce auxiliary functions data_length and data_get to easily iterate over your data. The following program dumps unpacked unsigned chars on stdout, one per line:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
/* htoi(H)
Return the value associated to the hexadecimal digit H. */
int
htoi(char h)
{
int a = -1;
if(isdigit(h))
{
a = h - '0';
}
else
{
a = toupper(h) - 'A' + 10;
}
return a;
}
/* data_length(D)
The length of the data stored at D. */
int
data_length(const char* d)
{
return strlen(d) / 2;
}
/* data_get(D, K)
Return the K-th unsigned char located encoded in d. */
unsigned char
data_get(const char *d, int k)
{
return htoi(d[2*k]) * 0x10 +
htoi((d+1)[2*k]);
}
int
main()
{
const char cdata[]="F69CF355B6231FDBD91EB1E22B61EA1F";
for(int i = 0; i < data_length(cdata); ++i)
{
printf("0x%02hhx\n", data_get(cdata, i));
}
return EXIT_SUCCESS;
}