I'm trying to implement the AWS V4 signature in C, but am failing to calculate the hash in the string to sign. The test example here has:
key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'
producing
kSecret = '41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559'
kDate = '969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d'
kRegion = '69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c'
kService = 'f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa'
kSigning = 'f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d'
But, for some reason my implementation drops the last few characters of the final element, and I get:
kSecret : 41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559
kDate : 969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d
kRegion : 69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c
kService : f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa
kSigning : f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a0
I'm just using an example for the HMAC_SHA256 calculation from https://stackoverflow.com/a/29862424/993874, I can't see what I'm missing. For other calculations (i.e. ones performing requests for my own AWS data etc) I also see that some of the hmac outputs are not 32 characters in length.
Can anyone help address this (and also confirm whether I need to convert all the char arrays to hex strings for AWS requests)?
Example code:
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
void printHex(const char* preface, const char* toPrint) {
printf("%s\t: ", preface);
for(size_t i = 0; i < strlen(toPrint); i++) {
printf("%02x", toPrint[i] & 0xff);
}
printf("\n");
}
void hmac_sha256(const unsigned char* key,
const unsigned char* text,
unsigned char* result) {
unsigned int resultLen;
HMAC(EVP_sha256(), key, strlen(key), text, strlen(text), result, &resultLen);
}
void amazonV4Sign(const unsigned char* accessSecret,
const unsigned char* amzDate,
const unsigned char* region,
const unsigned char* service) {
unsigned char kDate[BUFSIZ];
unsigned char kRegion[BUFSIZ];
unsigned char kService[BUFSIZ];
unsigned char kSigning[BUFSIZ];
unsigned char kSecret[BUFSIZ];
sprintf(kSecret, "AWS4%s", accessSecret);
unsigned char request[BUFSIZ];
sprintf(request, "aws4_request");
hmac_sha256(kSecret, amzDate, kDate);
hmac_sha256(kDate, region, kRegion);
hmac_sha256(kRegion, service, kService);
hmac_sha256(kService, request, kSigning);
printHex("kSecret", kSecret);
printHex("kDate", kDate);
printHex("kRegion", kRegion);
printHex("kService", kService);
printHex("kSigning", kSigning);
}
int main(int argc, char* argv[]) {
unsigned char* key = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
unsigned char* dateStamp = "20120215";
unsigned char* regionName = "us-east-1";
unsigned char* serviceName = "iam";
amazonV4Sign(key, dateStamp, regionName, serviceName);
return 0;
}
You cannot use strlen to print the HMAC output because byte array may contain 0 byte.
Hence you can use the md_len returned by HMAC as below to print the byte array.
HMAC returns the length of md and syntax is.
unsigned char *HMAC(const EVP_MD *evp_md, const void *key,
int key_len, const unsigned char *d, int n,
unsigned char *md, unsigned int *md_len);
Hence use md_len to print the array.
void printHex(const char* preface, const char* toPrint, int len) {
printf("%s\t: ", preface);
for(size_t i = 0; i < len; i++) {
printf("%02x", toPrint[i] & 0xff);
}
printf("\n");
}
int hmac_sha256(const unsigned char* key,
const unsigned char* text,
unsigned char* result) {
unsigned int resultLen;
HMAC(EVP_sha256(), key, strlen(key), text, strlen(text), result, &resultLen);
printf("%d\n", resultLen);
return resultLen;
}
void amazonV4Sign(const unsigned char* accessSecret,
const unsigned char* amzDate,
const unsigned char* region,
const unsigned char* service) {
unsigned char kDate[EVP_MAX_MD_SIZE] = {0};
unsigned char kRegion[EVP_MAX_MD_SIZE] = {0};
unsigned char kService[EVP_MAX_MD_SIZE] = {0};
unsigned char kSigning[EVP_MAX_MD_SIZE] = {0};
unsigned char kSecret[BUFSIZ];
sprintf(kSecret, "AWS4%s", accessSecret);
printf("%s\n", kSecret);
unsigned char request[BUFSIZ];
sprintf(request, "aws4_request");
int len = hmac_sha256(kSecret, amzDate, kDate);
printHex("kSecret", kSecret,strlen(kSecret));
printHex("kDate", kDate,len);
len = hmac_sha256(kDate, region, kRegion);
printHex("kRegion", kRegion,len);
len = hmac_sha256(kRegion, service, kService);
printHex("kService", kService,len);
len = hmac_sha256(kService, request, kSigning);
printHex("kSigning", kSigning,len);
}
Output:
kSecret : 41575334774a616c725855746e46454d492f4b374d44454e472b62507852666943594558414d504c454b4559
kDate : 969fbb94feb542b71ede6f87fe4d5fa29c789342b0f407474670f0c2489e0a0d
kRegion : 69daa0209cd9c5ff5c8ced464a696fd4252e981430b10e3d3fd8e2f197d7a70c
kService : f72cfd46f26bc4643f06a11eabb6c0ba18780c19a8da0c31ace671265e3c87fa
kSigning : f4780e2d9f65fa895f9c67b32ce1baf0b0d8a43505a000a1a9e090d414db404d
Your loop in PrintHex is up to strlen(toPrint). It's a byte array, not a string, so you cannot use strlen( ). The loop needs to go up to 32.
Related
I try to add a nonce to my blockchain program. But when I test a program performance by trying to repeat the result (I need to be able to do to verify my chain), I do not get an identical result.
First I have a function which transform a structure to unsigned array pointer :
struct Test{
unsigned char data[4];
unsigned char nonce[4];
unsigned char hash[32];
}*prev,*next;
unsigned char *toStringTest(struct Test data)
{
unsigned char *str=malloc(sizeof(unsigned char)*sizeof(data));
memcpy(str,&data,sizeof(data));
return str;
}
Then, I have a program which give me a hash and nonce:
In this function:
I concatenated unsigned char pointer from toStringTest() with unsigned char arrat nonce.
I calculated hash of this concatenation.
If the hash starts by 0x00 I save hash and nonce into next block. If not, I repeat the function.
void hash_with_nonce(struct Test* message,struct Test* new_message){
unsigned char nonce[4]; //number only used once
unsigned char buffer[32];
while(1){
RAND_bytes(nonce, 4); //this function puts 4 cryptographically strong pseudo-random bytes into nonce.
unsigned char* str=toStringTest(*message);
int len = sizeof(unsigned char)*sizeof(*str)+sizeof(unsigned char)*sizeof(nonce);
unsigned char* message_with_nonce = malloc(len);
memcpy(message_with_nonce,str,sizeof(*str));
memcpy(message_with_nonce+sizeof(unsigned char)*sizeof(*str),nonce,sizeof(nonce));
//I concatenated toStringTest(*message) with nonce
SHA256(message_with_nonce, sizeof(message_with_nonce), buffer); //calculation of hash
free(message_with_nonce);
unsigned char var[1] = {0x00}; //rule for nonce decision, I want what hash start by 0x00
if((int *)var[0] == (int *)buffer[0]){
memcpy(new_message->hash,buffer, 32);
memcpy(new_message->nonce, nonce,sizeof(nonce));
return;
}
}
}
This is my main:
int main(int argc, char **argv)
{
unsigned char hash[32];
prev=malloc(sizeof(struct Test));
RAND_bytes(prev->data, 4);
RAND_bytes(prev->nonce, 4);
SHA256("",sizeof(""),prev->hash);
next=malloc(sizeof(struct Test));
RAND_bytes(next->data, 4);
//I just have filled this block with random data
hash_with_nonce(prev,next);
unsigned char* str=toStringTest(*prev);
int len = sizeof(unsigned char)*sizeof(*str)+sizeof(unsigned char)*sizeof(next->nonce);
unsigned char* message_with_nonce = malloc(len);
memcpy(message_with_nonce,str,sizeof(*str));
memcpy(message_with_nonce+sizeof(unsigned char)*sizeof(*str),next->nonce,sizeof(next->nonce));
SHA256(message_with_nonce, sizeof(message_with_nonce), hash);
}
prev and next are just 2 blocks which I use to check if function hash_with_nonce is working.
A problem is that the unsigned char hash[32] of the main is not the identical to next->hash. SHA256() and RAND_bytes() are openssl functions.
To check if 2 hashs are same, I have this function:
void PrintHex(unsigned char data[], int size)
{
unsigned char tmp[size];
for (int i=0; i<size; i++)
{
sprintf(tmp, "%02x",data[i]);
printf("%s", tmp);
}
printf("\n");
}
I'm writing simple aes decoder/encoder using libtomcrypt. I need to story symmetric keys used in encoding, to decode data later. The problem is that the value of key which I access from "storage" struct changes comparing to the key that was used in encoder.
I've tried to assign key value to element of global symmetric_key array elem, but the value is still different from original
#include <tomcrypt.h>
typedef struct {
unsigned char * data;
unsigned char * crc_value;
symmetric_key skey;
}
aes_info_set;
aes_info_set aes_encrypter(unsigned char * data, unsigned char * key, int buf_size, int keysize, int rounds);
void main() {
unsigned char * data = "hallo world";
aes_info_set test;
test = aes_encrypter(data, key, 80, 32, 14);
printf("struct skey: %x \n", test.skey);
}
aes_info_set aes_encrypter(unsigned char * data, unsigned char * key, int buf_size, int keysize, int rounds) {
aes_info_set info_pack;
unsigned char * text = data;
unsigned char enc_out[buf_size];
unsigned char * crc_value = (unsigned char * ) malloc(4 * sizeof(unsigned char));
symmetric_key skey;
crc_value = crc_check(text, strlen(text));
aes_keysize( & keysize);
aes_setup(key, keysize, rounds, & skey);
aes_ecb_encrypt(text, enc_out, & skey);
printf("FROM FUNC\n");
info_pack.data = enc_out;
info_pack.crc_value = crc_value;
info_pack.skey = skey;
printf("func skey: %x \n", skey);
return info_pack;
}
//Output
>func skey: a15b56e0
>
>struct skey: a15b7890
I expected them to be the same
If I understand correctly you're confusing the key you need to encrypt/decrypt your file and the "key" that is used internally by the library to do what you want.
The key that you want to store is the one that is passed as first argument to aes_setup(), whereas the instance of a symmetric_key is not important.
See the examples in e.g. the AES tests aes.c:647 on how rijndael_setup() is used (rijndael_setup() is the same as aes_setup()).
Current main() below, which is working now, is used to modify the size & values of an input array, and to generate an output array.
int main()
{
unsigned char input_text[] = {0x00, 0x01, 0x02 ....};
int ilength = sizeof(input_text)/sizeof(input_text[0]);
int *olength;
olength = &ilength;
unsigned char* output_text = (unsigned char*)malloc(sizeof(unsigned char)*(*olength));
int option = 1;
switch(option)
{ // array size and some elements values will be changed below
case 1:
change_output_method_1(&output_text, input_text, ilength, olength);
// void change_output_method_1(unsigned char** output, unsigned char* input, int inlen, int *olen);
}
return 0;
}
Now, I want to revise above main() as a call function named change( ), which reads input_text and option values from new main( ), and return output_text value to new main().
Of course, create another new main( ) to call change( ).
unsigned char* change(unsigned char input_text, int option)
{
int ilen = sizeof(input_text)/sizeof(input_text[0]);
(same as before)
return output_text;
}
int main()
{
int opt = 1;
unsigned char input[] = {same};
unsigned char output[] = change(input, opt);
// IMPORTANT: output[] size is unknown before receiving the return value from change( )
}
I meet some errors when define char arrays because of pointer issues. How to revise the new code?
This does not work:
unsigned char output[] = change(input, opt);
...
unsigned char* change(unsigned char input_text, int option)
You cannot pass an array to your change function. You have to pass a pointer to the array (technically exact: to the first element of the array), together with the size:
unsigned char output[] = change(input, sizeof(input), opt);
...
unsigned char* change(unsigned char *input_text, int ilen, int option) {
Furthermore, you cannot return an array, either. You can for example return a dynamically allocated buffer and pass the size of the output buffer in an output parameter:
int output_size;
char *output = change(input, sizeof(input), &output_size, opt);
...
unsigned char* change(unsigned char *input_text, int ilen, int *olen, int option) {
char *ret = malloc(SIZE);
*olen = SIZE;
return ret;
}
There are of course other possibilities, it depends on the exact situation.
You need the following
unsigned char * change( const unsigned char *input_text, size_t n, int option )
{
unsigned char *output_text = malloc( n * sizeof(unsigned char) );
(same as before)
return output_text;
}
and call it like
unsigned char *output_text = change( input_text,
sizeof( input_text ) / sizeof( *input_text ),
option );
Arrays used as function arguments are implicitly converted to pointers to their first elements.
And a function parameter declared as an array is adjusted by the compiler to pointer to the array element type.
That is within the function input_text is a pointer. You have to pass explicitly the size of the array.
If the size of the output array can differ from the size of the input array then the approach can be the following.
Within main you declare a pointer
unsigned char *output_text = NULL;
The function declaration in this case will look like
size_t change( const unsigned char *input_text, unsigned char **output_text, size_t n, int option )
{
size_t size = /* some initializer expression */;
*output_text = malloc( size * sizeof(unsigned char) );
(same as before)
return size; // where size is the size of the array output_text
}
and the function will be called like
size_t olength = change( input_text,
sizeof( input_text ) / sizeof( *input_text ),
&output_text,
option );
im trying to convert a string message to hex value in C.
For example if i have a message like "abc" i want to have it by 162636 etc. My code is below. In this code, i have to do some concat operation to store them all but now i can store only 36. How can i store them?
unsigned char swapNibbles(char x)
{
return ( (x & 0x0F)<<4 | (x & 0xF0)>>4 );
}
void encode(char *message, char password[40]) {
unsigned char *reversedInput = malloc(strlen(message));
for (int i = 0; i < strlen(message); ++i) {
reversedInput=swapNibbles(message[i]);
}
printf("%2x TERS ",reversedInput);
//unsigned char *bitwiseMessage = (unsigned char*)message;
//printf("DÜZ %s\n",bitwiseMessage);
//printf("TERS %u\n", swapNibbles(bitwiseMessage));
}
Edit
My solution for hex-encoding: IDEOne
If you want your text to be hex-encoded, you will have to allocate twice as much space as the original message:
"abc" (3 bytes) ==> "616263" (6 bytes)
So you will need:
unsigned char *reversedInput = malloc(2*strlen(message)+1); // +1 for the final NULL-terminator
#include <string.h>
#include <malloc.h>
char* HexEncode(char* txt)
{
char* hexTxt = calloc(2*strlen(txt)+1,1);
for(char* p=hexTxt; *txt; p+=2)
{
sprintf(p, "%02x", *txt++);
}
return hexTxt;
}
int main() {
char* hexText = HexEncode("Hello World");
printf("Hexed is %s\n", hexText);
free(hexText);
return 0;
}
Output
Hexed is 48656c6c6f20576f726c64
I have a function which takes unsigned char* as input.
Say for example that I have:
unsigned char* data = (unsigned char*) "\xdd";
int a = 221;
How can I convert my integer a to unsigned char* such that data and my converted a is indistinguishable?
I have tried playing around with sprintf but without any luck, I'm not sure how to handle the "\x" part.
Since 221 is not guaranteed to be a valid value for a char type, the closest thing you can do is:
int a = 221;
unsigned char buffer[10];
sprintf((char*)buffer, "%c", a);
Here's an example program and its output:
#include <stdio.h>
int main()
{
unsigned char* data = (unsigned char*) "\xdd";
int a = 221;
unsigned char buffer[10];
sprintf((char*)buffer, "%c", a);
printf("%d\n", buffer[0] == data[0]);
printf("%d\n", buffer[0]);
printf("%d\n", data[0]);
}
Output:
1
221
221
Update
Perhaps I misunderstood your question. You can also use:
int a = 221;
unsigned char buffer[10] = {0};
buffer[0] = a;
As stated the question does not make sense and is not possible - you don't actually want to convert to const char *, which is a pointer type. Instead you want to convert into an array of chars and then take the address of that array by using its name.
int x = 221;
char buf[5];
snprintf(buf, sizeof buf, "\\x%.2x", x);
/* now pass buf to whatever function you want, e.g.: */
puts(buf);