C++ writing TDengine database with error occasionally - tdengine

When I use below code to insert into TDengine database ,sometimes it will lose connection.
you can compile it and run to reproduce issue ,anyone could help on this ?
I use the async taos_query_a API to test the response time .:
//
// Created by jia.wen on 8/15/22.
//
//#include <fmt/format.h>
#include <chrono>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <vector>
#include <taos.h>
static unsigned long long get_nanosecs_since_epoch()
{
using namespace std::chrono;
return static_cast<unsigned long long>(duration_cast<nanoseconds>(
system_clock::now().time_since_epoch()).count());
}
static std::string format_nanosecs_since_epoch(unsigned long long nanosecs_since_epoch)
{
std::time_t secs_since_epoch(nanosecs_since_epoch / 1000000000);
std::tm secs_since_epoch_tm;
localtime_r(&secs_since_epoch, &secs_since_epoch_tm);
unsigned long long remaining_nanosecs = nanosecs_since_epoch % 1000000000;
char buffer[30];
int year = secs_since_epoch_tm.tm_year + 1900;
buffer[0] = (year / 1000) + '0';
buffer[1] = (year % 1000) / 100 + '0';
buffer[2] = (year % 100) / 10 + '0';
buffer[3] = (year % 10) + '0';
buffer[4] = '-';
int month = secs_since_epoch_tm.tm_mon + 1;
buffer[5] = (month / 10) + '0';
buffer[6] = (month % 10) + '0';
buffer[7] = '-';
buffer[8] = (secs_since_epoch_tm.tm_mday / 10) + '0';
buffer[9] = (secs_since_epoch_tm.tm_mday % 10) + '0';
buffer[10] = ' ';
buffer[11] = (secs_since_epoch_tm.tm_hour / 10) + '0';
buffer[12] = (secs_since_epoch_tm.tm_hour % 10) + '0';
buffer[13] = ':';
buffer[14] = (secs_since_epoch_tm.tm_min / 10) + '0';
buffer[15] = (secs_since_epoch_tm.tm_min % 10) + '0';
buffer[16] = ':';
buffer[17] = (secs_since_epoch_tm.tm_sec / 10) + '0';
buffer[18] = (secs_since_epoch_tm.tm_sec % 10) + '0';
buffer[19] = '.';
buffer[20] = (remaining_nanosecs / 100000000) + '0';
buffer[21] = (remaining_nanosecs % 100000000) / 10000000 + '0';
buffer[22] = (remaining_nanosecs % 10000000) / 1000000 + '0';
buffer[23] = (remaining_nanosecs % 1000000) / 100000 + '0';
buffer[24] = (remaining_nanosecs % 100000) / 10000 + '0';
buffer[25] = (remaining_nanosecs % 10000) / 1000 + '0';
buffer[26] = (remaining_nanosecs % 1000) / 100 + '0';
buffer[27] = (remaining_nanosecs % 100) / 10 + '0';
buffer[28] = (remaining_nanosecs % 10) + '0';
buffer[29] = 0;
return std::string(buffer);
}
void taos_insert_call_back(void* param, TAOS_RES* tres, int code)
{
unsigned long long* insert_time = (unsigned long long *)param;
struct timeval systemTime;
char sql[128];
if (code < 0)
{
printf("Insert failed. code:%d, cause:%s\n", code, taos_errstr(tres));
}
else if (code == 0)
{
// printf("Not inserted.\n");
}
else
{
printf("Succeed.\n");
}
taos_free_result(tres);
}
int main()
{
const char *host = "localhost:6030";
const char *user = "root";
const char *passwd = "taosdata";
const char *db = "test_lts";
uint16_t port = 0; // 0 means use the default port
TAOS *taos = taos_connect(host, user, passwd, db, port);
if (taos == NULL)
{
int errno_n = taos_errno(NULL);
auto msg = taos_errstr(NULL);
printf("%d, %s\n", errno, msg);
}
else
{
printf("connected\n");
std::string ins_sql;
std::vector<int> test_cycles_;
TAOS_RES* exec_result = NULL;
int cycles = 60;
int insert_times = 2000;
for (auto i = 0; i < cycles; ++i)
{
for (auto j = 0; j < insert_times; ++j)
{
auto local_time = format_nanosecs_since_epoch(get_nanosecs_since_epoch());
ins_sql = "INSERT INTO tick_jw VALUES ('" + local_time + "'," + std::to_string(i + 1) + ", 20221018, " + std::to_string(j)
+ ", 'test', 1.2, 200, 1000, 0, 0, 0, "
"1.15, 1.14, 1.13, 1.12, 1.11, 5, 4, 3, 2, 1, 1.16, 1.17, 1.18, 1.19, 1.20, 5, 4, 3, 2, 1)";
taos_query_a(taos, ins_sql.c_str(), taos_insert_call_back, (void *)(0));
// usleep(60);
}
std::cout << "cycles = " << i + 1 << " finished." << std::endl;
// sleep(1);
}
std::cout << "insert_times = " << insert_times << " test async finished." << std::endl;
sleep(60);
taos_close(taos);
}
taos_cleanup();
}
the core part is just :taos_query_a(taos, ins_sql.c_str(), taos_insert_call_back, (void *)(0));

Related

Adding 10-bit binary numbers

I need to 2 strings (10-bit binary numbers). I's easy when i'm adding 1+0 0+0
But how I can modify this, to situation when i'll need to make 11-bit
like
1010101010+1111111111=11010101001
i = MAX+1;
while( i!=0) {
if ((str1[i - 1] == str2[i - 1]) && (str1[i - 1] == '0' )) {
str3[i] = '0';
}
else if ((str1[i - 1] != str2[i - 1])) {
str3[i] = '1';
}
else if ((str1[i - 1] == str2[i - 1]) && (str1[i - 1] == '1')) {
str3[i] = '0';
}
i--;
}
MAX=10
It's not clear exactly what the requirements are, but I wrote a function that takes three strings, figures out their lengths using strlen, and then sets the third string equal to the sum of the first two. Here is a program that adds the two 10-bit numbers you gave and prints the expected result of "11010101001".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void binary_string_add(const char * a, const char * b, char * sum)
{
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t sumlen = strlen(sum);
int carry = 0;
for (size_t i = 0; i < sumlen; i++)
{
if (i < alen) { carry += a[alen - 1 - i] == '1'; }
if (i < blen) { carry += b[blen - 1 - i] == '1'; }
sum[sumlen - 1 - i] = '0' + (carry & 1);
carry >>= 1;
}
}
int main()
{
char str1[] = "1010101010";
char str2[] = "1111111111";
char str3[] = "xxxxxxxxxxx";
binary_string_add(str1, str2, str3);
printf("Sum: %s\n", str3);
}
By the way, each iteration of the loop actually implements a 1-bit adder.
Update: If you want an easier interface that allocates an output string for you of the appropriate length and returns it, this works:
char * binary_string_add2(const char * a, const char * b)
{
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t sumlen = (alen > blen ? alen : blen) + 1;
char * sum = malloc(sumlen + 1);
if (sum == NULL) { /** Add error handling here. **/ }
memset(sum, 'x', sumlen);
sum[sumlen] = 0;
binary_string_add(a, b, sum);
return sum;
}
#define ADDCHAR(c1,c2) (((c1) == '1') + ((c2) == '1'))
char *add(char *res, const char *n1, const char *n2)
{
size_t ln1 = strlen(n1);
size_t ln2 = strlen(n2);
char *resend = res + (ln2 > ln1 ? ln2 + 2 : ln1 + 2);
unsigned rem = 0;
*resend-- = 0;
while(ln1 || ln2)
{
unsigned pres = rem + ADDCHAR(ln1 ? n1[ln1 - 1] : '0', ln2 ? n2[ln2 - 1] : '0');
*resend-- = '0' + (pres & 1);
rem = pres >> 1;
ln1 -= !!ln1;
ln2 -= !!ln2;
}
if(rem) *resend-- = '0' + rem;
while(resend >= res) *resend-- = ' ';
return res;
}
int a = 0 ;
for(int i = 0 ; i < 10 ; i++){
str3[i] = str1[i] + str2[i] + a ;
if(str3[i] > 1){
str3[i] %= 2 ;
a = 1 ;
}
else{
a = 0 ;
}
}

Why this error happens while showing array out in C?

What I'm making is input a number that type is 'unsigned long long' and then make it to binary form and show it by 16 figures.
Here's my code and result.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
char D_PAN_ID[16];
char D_ADDRESS[16];
char S_PAN_ID[16];
char S_ADDRESS[16];
int main()
{
int bit1, bit2, bit3, bit4, k1, k2, k3, k4;
unsigned long long dec = 5;
/*
printf("8바이트 정수를 이진수로 변환\n");
scanf("%llu", &dec);
*/
printf("%llu 를(을) 이진수로 변환하면:\n", dec);
for (bit1 = 63; bit1 >= 48; bit1--)
{
k1 = dec >> bit1;
if (k1 & 1) {
D_PAN_ID[63 - bit1] = '1';
printf(&D_PAN_ID[63 - bit1]);
}
else {
D_PAN_ID[63 - bit1] = '0';
printf(&D_PAN_ID[63 - bit1]);
}
}
printf("\n\n");
for (bit2 = 47; bit2 >= 32; bit2--)
{
k2 = dec >> bit2;
if (k2 & 1) {
D_ADDRESS[47 - bit2] = '1';
printf(&D_ADDRESS[47 - bit2]);
}
else {
D_ADDRESS[47 - bit2] = '0';
printf(&D_ADDRESS[47 - bit2]);
}
}
printf("\n\n");
for (bit3 = 31; bit3 >= 16; bit3--)
{
k3 = dec >> bit3;
if (k3 & 1) {
S_PAN_ID[31 - bit3] = '1';
printf(&S_PAN_ID[31 - bit3]);
}
else {
S_PAN_ID[31 - bit3] = '0';
printf(&S_PAN_ID[31 - bit3]);
}
}
printf("\n\n");
for (bit4 = 15; bit4 >= 0; bit4--)
{
k4 = dec >> bit4;
if (k4 & 1) {
S_ADDRESS[15 - bit4] = '1';
printf(&S_ADDRESS[15 - bit4]);
}
else {
S_ADDRESS[15 - bit4] = '0';
printf(&S_ADDRESS[15 - bit4]);
}
}
return 0;
}
And what I got is this. I think it is adding upper result at back since printing second result. Like this:
result1
result2 + result1
result3 + result1 + result2
result4 + result1 + result2 + result3
How do I fix it to show like
000000000000
000000000000
000000000000
000000000101

CS50 Credit, loop if not card number

I have nearly finished the Credit task of PSET1 (CS50) although I have run into a problem trying to get the program to not allow an entry that isn't a card number (E.g "Foo" or "t" or anything other than a number) and then loop.
I have attempted various while statements and goto statements although none of these attempts have been sucessful
Also any other suggestions would be appreciated.
#include <stdio.h>
#include <cs50.h>
int main(void)
{
//gets cardnumber & counts digits entered
long long cardnumber;
int count = 0;
{
//prompts user for a cardnumber
printf("Enter a cardnumber: ");
scanf("%lld", &cardnumber);
}
//Prints count of digits entered (will likely not need this part)
//else printf("Number of digits: %d", count); printf("\n");
//Finds first 8 digits for checksum)
int digit1 = (((cardnumber % 100) / 10) * 2);
int digit2 = (((cardnumber % 10000) / 1000) * 2);
int digit3 = (((cardnumber % 1000000) / 100000) * 2);
int digit4 = (((cardnumber % 100000000) / 10000000) * 2);
int digit5 = (((cardnumber % 10000000000) / 1000000000) * 2);
int digit6 = (((cardnumber % 1000000000000) / 100000000000) * 2);
int digit7 = (((cardnumber % 100000000000000) / 10000000000000) * 2);
int digit8 = (((cardnumber % 10000000000000000) / 1000000000000000) * 2);
//Sum first 8 digits of checksum
int check1 = ((digit1 % 10) + (digit1 / 10));
check1 = (check1 + (digit2 % 10)) + (digit2 / 10);
check1 = (check1 + (digit3 % 10)) + (digit3 / 10);
check1 = (check1 + (digit4 % 10)) + (digit4 / 10);
check1 = (check1 + (digit5 % 10)) + (digit5 / 10);
check1 = (check1 + (digit6 % 10)) + (digit6 / 10);
check1 = (check1 + (digit7 % 10)) + (digit7 / 10);
check1 = (check1 + (digit8 % 10)) + (digit8 / 10);
//Sum last 8 digits of checksum & Sum of first 8 (check1)
int digit9 = ((cardnumber % 10) / 1);
int digit10 = ((cardnumber % 1000) / 100);
int digit11 = ((cardnumber % 100000) / 10000);
int digit12 = ((cardnumber % 10000000) / 1000000);
int digit13 = ((cardnumber % 1000000000) / 100000000);
int digit14 = ((cardnumber % 100000000000) / 10000000000);
int digit15 = ((cardnumber % 10000000000000) / 1000000000000);
int digit16 = ((cardnumber % 1000000000000000) / 100000000000000);
//add to remaining digits to those that were multiplied by 2
int checksum = (check1 + digit9 + digit10 + digit11 + digit12 + digit13 + digit14 + digit15 + digit16);
// Check first 2 digits
if (cardnumber / 10000000000000 == 34 || cardnumber / 10000000000000 == 37 )
goto Amex;
if (cardnumber / 100000000000000 == 51 || cardnumber / 100000000000000 == 52 || cardnumber / 100000000000000 == 53 || cardnumber / 100000000000000 == 54 || cardnumber / 100000000000000 == 55 )
goto Master;
if (cardnumber / 1000000000000000 == 4 )
goto Visa;
else
{
printf("INVALID\n");
(I = 0);
}
goto End;
// Amex start with 34 or 37
Amex:;
char A;
if (cardnumber / 10000000000000 == 34 || cardnumber / 10000000000000 == 37 )
{
A = 1;
}
else
{
A = 0;
}
goto End;
// Mastercard start with 51, 52, 53, 54, 55
Master:;
char M;
if (cardnumber / 100000000000000 == 51 || cardnumber / 100000000000000 == 52 || cardnumber / 100000000000000 == 53 || cardnumber / 100000000000000 == 54 || cardnumber / 100000000000000 == 55 )
{
M = 1;
}
else
{
M = 0;
}
goto End;
//Visa start with 4
Visa:;
char V;
if (cardnumber / 1000000000000000 == 4 )
{
V = 1;
}
else
{
V = 0;
}
goto End;
End:;
while(cardnumber != 0)
{
// cardnumber = cardnumber/10
cardnumber /= 10;
++count;
}
// if cardnumber <13 or >16 digits error "invalid card" given
if (count > 16 || count < 13)
{
printf("INVALID\n");
(I = 0);
}
// Keep track of first 2 digits & validate checksum
char T;
if (checksum % 10 == 0)
{
T = 1;
}
else
{
T = 0;
}
if (T == 0) printf("INVALID\n");
{
(I = 0);
}
// - Amex (15 digits, start with 34 or 37)
if (count == 15 && T == 1 && A == 1)
{
printf("AMEX\n");
}
// - Mastercard (16 digits, start with 51, 52, 53, 54, 55)
if (count == 16 && T == 1 && M == 1)
{
printf("MASTERCARD\n");
}
// - Visa (13 & 16 digits, start with 4)
if ((count == 13 && T == 1 && V == 1) || (count == 16 && T == 1 && V == 1))
{
printf("VISA\n");
}
}
Prompt the user to type in the credit card number, use a do while loop so that if the number is less than 0, you will keep asking the user for a card number.
int main(void)
{
long long credit_card_number;
do
{
credit_card_number = get_long_long("Enter Valid Credit Card Number: ");
}
while (credit_card_number < 0);
#include <cs50.h>
#include <math.h>
#include <stdio.h>
int main(void)
{
long long cardnumber = 0;
do
{
cardnumber = get_long("Number: ");
}
while (cardnumber < 0);
int count = 0;
long long digits = cardnumber;
while (digits > 0)
{
digits = digits/10;
count++;
}
if ((count != 13) && (count != 15) && (count != 16))
{
printf("INVALID\n");
}
int number[count];
for (int i = 0; i < count; i++)
{
number[i] = cardnumber % 10;
cardnumber = cardnumber / 10;
}
int originalnumber[count];
for (int i = 1; i < count; i++)
{
originalnumber[i] = number[i];
}
for (int i = 1; i < count; i+=2)
{
number[i] = number[i] * 2;
}
int v = 0;
int temp;
if (count == 13)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[12] == 4 && v % 10 == 0)
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
if (count == 15)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[14] == 3 && v % 10 == 0 && (originalnumber[13] == 4 || originalnumber[13] == 7))
{
printf("AMEX\n");
}
else
{
printf("INVALID\n");
}
}
if (count == 16)
{
for (int i = 0; i < count; i++)
{
temp = (number[i] % 10) + (number[i]/10 % 10);
v = v + temp;
}
if (originalnumber[15] == 4 && v % 10 == 0)
{
printf("VISA\n");
}
else if (originalnumber[15] == 5 && v % 10 == 0 && (originalnumber[14] == 1 || originalnumber[14] == 2 || originalnumber[14] == 3 || originalnumber[14] == 4 || originalnumber[14] == 5))
{
printf("MASTERCARD\n");
}
else
{
printf("INVALID\n");
}
}
}

HmacSHA256 in WebAssembly compiled with Emscripten

I'm trying to implement JWT token (encoding only) in WebAssembly, the goal is to have a very light weight wasm module. As a web developer my C knowledge is limited. For now I've implemented the following function (ported from JS) to encode url-safe Base64 encoder, which works perfectly.
char _keyStr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=";
char ret_val[200];
char* encode (char *data){
int len = strlen(data);
int i = 0;
int j = 0;
while(i<len){
char chr1 = data[i++];
int chr2Out = (i > len - 1)? 1:0;
char chr2 = data[i++];
int chr3Out = (i > len - 1)? 1:0;;
char chr3 = data[i++];
char enc1 = chr1 >> 2;
char enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
char enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
char enc4 = chr3 & 63;
if (chr2Out) {
enc3 = enc4 = 64;
} else if (chr3Out) {
enc4 = 64;
}
ret_val[j++] = _keyStr[enc1];
ret_val[j++] = _keyStr[enc2];
ret_val[j++] = _keyStr[enc3];
ret_val[j++] = _keyStr[enc4];
}
ret_val[j] = '\0';
return ret_val;
}
My next challenge is to be able to sign my JWT payload with HmacSHA256.
The following JS fiddle, describes what I want to accomplish with C.
https://jsfiddle.net/gm7boy2p/813/
I'm struggling with integrating a 3rd party code and complie it with emcc.
I'm looking for a light weight library or a snippet.
Example code or any help would be appreciated.
Update: After extra research, reading this stackoverflow question and this article, it looks like using openssl or any other external library with WebAssembly is far from trivial. So what I'm looking for now is a standalone C function that I could integrate to my existing code.
It is true that you cannot use the system libraries when using web-assembly. So the only solution is to compile them from source in a way the that is compliant with the libraries already provided by the cross-compiler (ie emscripten)
So for your question, I found the library cryptopp, satisfying your use case. The example here showcase how you can use this library.
Now how can you compile this library for your case? Since it comes with a make file, all you need to do is call
emmake make -f GNUmakefile-cross -j8
This will generate a .a file, which is actually a .bc file and can be linked with your existing C/C++ program, that you wish to run on web. Just make sure to include the headers of this file appropriately. It would even be better if you make a makefile for your project.
P.S I got this working locally in my system, by adding these line at the end of the GNUmakefile-cross file
cryptest.html: libcryptopp.a $(TESTOBJS)
$(CXX) -s DISABLE_EXCEPTION_CATCHING=0 --preload-file TestData -o $# $(strip $(CXXFLAGS)) $(TESTOBJS) ./libcryptopp.a $(LDFLAGS) $(LDLIBS)
I changed the test.cpp file to include sample code for "HMAC" and then called the following lines from the command line
emmake make -f GNUmakefile-cross cryptest.html -j8
The output ie cryptest.html, when opened in firefox worked flawlessly.
I managed to create a small (library-ish) code snippet in C. I checked the results from here.
Also shown here:
The SHA256 code is taken from here. Used in cgminer.
I just modified it a bit (removed references etc.) to make it work stand-alone. Here is the total code and test software.
sha2.h:
/*
* FIPS 180-2 SHA-224/256/384/512 implementation
* Last update: 02/02/2007
* Issue date: 04/30/2005
*
* Copyright (C) 2013, Con Kolivas <kernel#kolivas.org>
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay#a3.epfl.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef SHA2_H
#define SHA2_H
#define SHA256_DIGEST_SIZE ( 256 / 8)
#define SHA256_BLOCK_SIZE ( 512 / 8)
#define SHFR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define CH(x, y, z) ((x & y) ^ (~x & z))
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
typedef struct {
unsigned int tot_len;
unsigned int len;
unsigned char block[2 * SHA256_BLOCK_SIZE];
unsigned int h[8];
} sha256_ctx;
extern unsigned int sha256_k[64];
void sha256_init(sha256_ctx * ctx);
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len);
void sha256_final(sha256_ctx *ctx, unsigned char *digest);
void sha256(const unsigned char *message, unsigned int len,
unsigned char *digest);
#endif /* !SHA2_H */
main.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sha2.h"
#define UNPACK32(x, str) \
{ \
*((str) + 3) = (unsigned char) ((x) ); \
*((str) + 2) = (unsigned char) ((x) >> 8); \
*((str) + 1) = (unsigned char) ((x) >> 16); \
*((str) + 0) = (unsigned char) ((x) >> 24); \
}
#define PACK32(str, x) \
{ \
*(x) = ((unsigned int) *((str) + 3) ) \
| ((unsigned int) *((str) + 2) << 8) \
| ((unsigned int) *((str) + 1) << 16) \
| ((unsigned int) *((str) + 0) << 24); \
}
#define SHA256_SCR(i) \
{ \
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
}
unsigned int sha256_h0[8] =
{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
unsigned int sha256_k[64] =
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/* SHA-256 functions */
void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
unsigned int block_nb)
{
unsigned int w[64];
unsigned int wv[8];
unsigned int t1, t2;
const unsigned char *sub_block;
int i;
int j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++) {
PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++) {
SHA256_SCR(j);
}
for (j = 0; j < 8; j++) {
wv[j] = ctx->h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
ctx->h[j] += wv[j];
}
}
}
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
sha256_ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, message, len);
sha256_final(&ctx, digest);
}
void sha256_init(sha256_ctx *ctx)
{
int i;
for (i = 0; i < 8; i++) {
ctx->h[i] = sha256_h0[i];
}
ctx->len = 0;
ctx->tot_len = 0;
}
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&ctx->block[ctx->len], message, rem_len);
if (ctx->len + len < SHA256_BLOCK_SIZE) {
ctx->len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA256_BLOCK_SIZE;
shifted_message = message + rem_len;
sha256_transf(ctx, ctx->block, 1);
sha256_transf(ctx, shifted_message, block_nb);
rem_len = new_len % SHA256_BLOCK_SIZE;
memcpy(ctx->block, &shifted_message[block_nb << 6],
rem_len);
ctx->len = rem_len;
ctx->tot_len += (block_nb + 1) << 6;
}
void sha256_final(sha256_ctx *ctx, unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
< (ctx->len % SHA256_BLOCK_SIZE)));
len_b = (ctx->tot_len + ctx->len) << 3;
pm_len = block_nb << 6;
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
ctx->block[ctx->len] = 0x80;
UNPACK32(len_b, ctx->block + pm_len - 4);
sha256_transf(ctx, ctx->block, block_nb);
for (i = 0; i < 8; i++) {
UNPACK32(ctx->h[i], &digest[i << 2]);
}
}
unsigned char * HMAC_SHA256(const char * msg, const char * key)
{
unsigned int blocksize = 64;
unsigned char * Key0 = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_ipad = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_ipad_concat_text = (unsigned char *)calloc( (blocksize + strlen(msg)), sizeof(unsigned char));
unsigned char * Key0_ipad_concat_text_digest = (unsigned char *)calloc( blocksize, sizeof(unsigned char));
unsigned char * Key0_opad = (unsigned char *)calloc(blocksize, sizeof(unsigned char));
unsigned char * Key0_opad_concat_prev = (unsigned char *)calloc(blocksize + 32, sizeof(unsigned char));
unsigned char * HMAC_SHA256 = (unsigned char *)malloc(32 * sizeof(unsigned char));
if (strlen(key) < blocksize) {
for (int i = 0; i < blocksize; i++) {
if (i < strlen(key)) Key0[i] = key[i];
else Key0[i] = 0x00;
}
}
else if (strlen(key) > blocksize) {
sha256(key, strlen(key), Key0);
for (unsigned char i = strlen(key); i < blocksize; i++) {
Key0[i] = 0x00;
}
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad[i] = Key0[i] ^ 0x36;
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad_concat_text[i] = Key0_ipad[i];
}
for (int i = blocksize; i < blocksize + strlen(msg); i++) {
Key0_ipad_concat_text[i] = msg[i - blocksize];
}
sha256(Key0_ipad_concat_text, blocksize + (unsigned int)strlen(msg), Key0_ipad_concat_text_digest);
for (int i = 0; i < blocksize; i++) {
Key0_opad[i] = Key0[i] ^ 0x5C;
}
for (int i = 0; i < blocksize; i++) {
Key0_opad_concat_prev[i] = Key0_opad[i];
}
for (int i = blocksize; i < blocksize + 32; i++) {
Key0_opad_concat_prev[i] = Key0_ipad_concat_text_digest[i - blocksize];
}
sha256(Key0_opad_concat_prev, blocksize + 32, HMAC_SHA256);
return HMAC_SHA256;
}
int main()
{
unsigned char * result;
result = HMAC_SHA256("Sample #1", "MyKey");
unsigned char arr[32] = { 0 };
memcpy(arr, result, 32);
for(int i = 0; i < 32; i++) {
printf("%#02x, ", arr[i]);
}
return 0;
}
Here are the results for the sample run:
EDIT:
Info on the HMAC_SHA256 function can be found here. The one I wrote is just for demonstration purposes. One can modify it accordingly.
EDIT 2:
I added the code for Base64 format. I used the information found on Wikipedia. Sample test run works for OP's input and output. Results are as shown:
Updated main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "sha2.h"
#define HMAC_SHA256_FAIL_STRING "HMAC_SHA256 has failed." // fprintf(stderr, "%s\n", strerror(errno));
#define UNPACK32(x, str) \
{ \
*((str) + 3) = (unsigned char) ((x) ); \
*((str) + 2) = (unsigned char) ((x) >> 8); \
*((str) + 1) = (unsigned char) ((x) >> 16); \
*((str) + 0) = (unsigned char) ((x) >> 24); \
}
#define PACK32(str, x) \
{ \
*(x) = ((unsigned int) *((str) + 3) ) \
| ((unsigned int) *((str) + 2) << 8) \
| ((unsigned int) *((str) + 1) << 16) \
| ((unsigned int) *((str) + 0) << 24); \
}
#define SHA256_SCR(i) \
{ \
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
}
char Base64_Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned int sha256_h0[8] =
{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
unsigned int sha256_k[64] =
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
/* SHA-256 functions */
void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
unsigned int block_nb)
{
unsigned int w[64];
unsigned int wv[8];
unsigned int t1, t2;
const unsigned char *sub_block;
int i;
int j;
for (i = 0; i < (int)block_nb; i++) {
sub_block = message + (i << 6);
for (j = 0; j < 16; j++) {
PACK32(&sub_block[j << 2], &w[j]);
}
for (j = 16; j < 64; j++) {
SHA256_SCR(j);
}
for (j = 0; j < 8; j++) {
wv[j] = ctx->h[j];
}
for (j = 0; j < 64; j++) {
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ sha256_k[j] + w[j];
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
ctx->h[j] += wv[j];
}
}
}
void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
{
sha256_ctx ctx;
sha256_init(&ctx);
sha256_update(&ctx, message, len);
sha256_final(&ctx, digest);
}
void sha256_init(sha256_ctx *ctx)
{
int i;
for (i = 0; i < 8; i++) {
ctx->h[i] = sha256_h0[i];
}
ctx->len = 0;
ctx->tot_len = 0;
}
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&ctx->block[ctx->len], message, rem_len);
if (ctx->len + len < SHA256_BLOCK_SIZE) {
ctx->len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA256_BLOCK_SIZE;
shifted_message = message + rem_len;
sha256_transf(ctx, ctx->block, 1);
sha256_transf(ctx, shifted_message, block_nb);
rem_len = new_len % SHA256_BLOCK_SIZE;
memcpy(ctx->block, &shifted_message[block_nb << 6],
rem_len);
ctx->len = rem_len;
ctx->tot_len += (block_nb + 1) << 6;
}
void sha256_final(sha256_ctx *ctx, unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
< (ctx->len % SHA256_BLOCK_SIZE)));
len_b = (ctx->tot_len + ctx->len) << 3;
pm_len = block_nb << 6;
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
ctx->block[ctx->len] = 0x80;
UNPACK32(len_b, ctx->block + pm_len - 4);
sha256_transf(ctx, ctx->block, block_nb);
for (i = 0; i < 8; i++) {
UNPACK32(ctx->h[i], &digest[i << 2]);
}
}
char * HMAC_SHA256(char * msg, char * key)
{
size_t blocksize;
blocksize = 64;
char * Key0 = (char *)calloc(blocksize, sizeof(char));
if (Key0 == NULL) {
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_ipad = (char *)calloc(blocksize, sizeof(char));
if (Key0_ipad == NULL) {
free(Key0);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64 + strlen(msg);
char * Key0_ipad_concat_text = (char *)calloc( blocksize, sizeof(char));
if (Key0_ipad_concat_text == NULL) {
free(Key0);
free(Key0_ipad);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_ipad_concat_text_digest = (char *)calloc( blocksize, sizeof(char));
if (Key0_ipad_concat_text_digest == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * Key0_opad = (char *)calloc(blocksize, sizeof(char));
if (Key0_opad == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64 + 32;
char * Key0_opad_concat_prev = (char *)calloc(blocksize + 32, sizeof(char));
if (Key0_opad_concat_prev == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
return HMAC_SHA256_FAIL_STRING;
}
blocksize = 64;
char * HMAC_SHA256 = (char *)malloc(blocksize/2 * sizeof(char));
if (HMAC_SHA256 == NULL) {
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
free(Key0_opad_concat_prev);
return HMAC_SHA256_FAIL_STRING;
}
if (strlen(key) < blocksize) {
char * tmp = key;
char * tmp2 = Key0;
for (int i = 0; i < blocksize; i++) {
if (i < strlen(key)) *tmp2++ = *tmp++;
else *tmp2++ = 0x00;
}
}
else if (strlen(key) > blocksize) {
sha256((unsigned char *)key, strlen(key), (unsigned char *)Key0);
for (unsigned char i = strlen(key); i < blocksize; i++) {
Key0[i] = 0x00;
}
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad[i] = Key0[i] ^ 0x36;
}
for (int i = 0; i < blocksize; i++) {
Key0_ipad_concat_text[i] = Key0_ipad[i];
}
for (int i = blocksize; i < blocksize + strlen(msg); i++) {
Key0_ipad_concat_text[i] = msg[i - blocksize];
}
sha256((unsigned char *)Key0_ipad_concat_text, blocksize + (unsigned int)strlen(msg), (unsigned char *)Key0_ipad_concat_text_digest);
for (int i = 0; i < blocksize; i++) {
Key0_opad[i] = Key0[i] ^ 0x5C;
}
for (int i = 0; i < blocksize; i++) {
Key0_opad_concat_prev[i] = Key0_opad[i];
}
for (int i = blocksize; i < blocksize + 32; i++) {
Key0_opad_concat_prev[i] = Key0_ipad_concat_text_digest[i - blocksize];
}
sha256((unsigned char *)Key0_opad_concat_prev, blocksize + 32, (unsigned char *)HMAC_SHA256);
free(Key0);
free(Key0_ipad);
free(Key0_ipad_concat_text);
free(Key0_ipad_concat_text_digest);
free(Key0_opad);
free(Key0_opad_concat_prev);
return HMAC_SHA256;
}
char * Base64_Stringify(char * hash, size_t length)
{
size_t no_op = 0;
size_t Base64_size;
char * Base64;
unsigned long tmp = length;
if (tmp % 3 == 0) {
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
}
else if (tmp % 3 == 1) {
tmp += 2;
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
Base64[Base64_size - 1] = '=';
Base64[Base64_size - 2] = '=';
no_op = 2;
}
else if (tmp % 3 == 2) {
tmp += 1;
Base64_size = 4 * tmp / 3;
Base64 = (char *)calloc(Base64_size + 1, sizeof(char));
Base64[Base64_size - 1] = '=';
no_op = 1;
}
unsigned int b64_case = 0;
size_t j = 0;
for (int i = 0; i < Base64_size - no_op; i++) {
switch (b64_case) {
case 0:
{
Base64[i] = Base64_Table[(hash[j] & 0xFC) >> 2];
j++;
b64_case = 1;
}
break;
case 1:
{
Base64[i] = Base64_Table[((hash[j-1] & 0x03) << 4) | ((hash[j] & 0xF0) >> 4)];
b64_case = 2;
}
break;
case 2:
{
Base64[i] = Base64_Table[((hash[j] & 0x0F) << 2) | ((hash[j+1] & 0xC0) >> 6)];
j++;
b64_case = 3;
}
break;
case 3:
{
Base64[i] = Base64_Table[(hash[j] & 0x3F)];
j++;
b64_case = 0;
}
break;
default:
break;
}
}
return Base64;
}
int main()
{
char * HMAC_SHA256_result;
char * Base64_Stringify_result;
HMAC_SHA256_result = HMAC_SHA256("test", "secret");
Base64_Stringify_result = Base64_Stringify(HMAC_SHA256_result, 32);
unsigned char arr[32] = { 0 };
memcpy(arr, HMAC_SHA256_result, 32);
for(int i = 0; i < 32; i++) {
printf("%#02x, ", arr[i]);
}
printf("\n\n");
for(int i = 0; i < strlen(Base64_Stringify_result); i++) {
printf("%c", Base64_Stringify_result[i]);
}
printf("\n\n");
return 0;
}
I'm leaving the old main.c for reference. You can also modify the updated main.c functions, e.g. the error codes when calloc fails...
I've created a simple example of how you can create the hmac with the libgcrypt library. You just need to install it in your system and them compile the program with the -lgcrypt flag to link the library.
As you've asked a standalone function, I created a function which you can call with the key and message that returns a string with the base64 encoded result, which is exactly what you asked for in your JSFiddle.
#include <stdio.h>
#include <string.h>
#include <gcrypt.h>
#include <stdint.h>
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
static char *decoding_table = NULL;
static int mod_table[] = {0, 2, 1};
char *base64_encode(const unsigned char *data,
size_t input_length,
size_t *output_length) {
*output_length = 4 * ((input_length + 2) / 3);
char *encoded_data = calloc(1,*output_length+1);
if (encoded_data == NULL) return NULL;
for (int i = 0, j = 0; i < input_length;) {
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
}
for (int i = 0; i < mod_table[input_length % 3]; i++)
encoded_data[*output_length - 1 - i] = '=';
return encoded_data;
}
//don't forget to free the return pointer!
char* hmacSHA256(gcry_mac_hd_t hd, const char* key, size_t key_size, const char* msg, size_t msg_size) {
unsigned char output[32];
size_t outputSize = 32;
gcry_mac_reset(hd);
gcry_mac_setkey(hd,key,strlen(key));
gcry_mac_write(hd,msg,strlen(msg));
gcry_mac_read(hd,output,&outputSize);
return base64_encode(output,outputSize,&outputSize);
}
int main() {
const char* const key = "secret";
const char* const msg = "test";
//hmacsha256 returns 256 bits, meaning 32 bytes
unsigned char output[32];
size_t outputSize = 32;
gcry_mac_hd_t hd;
gcry_mac_open(&hd,GCRY_MAC_HMAC_SHA256,0,NULL);
char* tmp = hmacSHA256(hd,key,strlen(key),msg,strlen(msg));
printf("HMAC-SHA256: '%s'\n",tmp);
free(tmp);
tmp = hmacSHA256(hd,"secrett",7,msg,strlen(msg));
printf("HMAC-SHA256: '%s'\n",tmp);
free(tmp);
gcry_mac_close(hd);
return 0;
}
Important remarks:
-Don't forget to free the return value of the hmacSHA256 function and to call gcry_mac_close when you are done hashing.
-I've included the size of the key and size of the message in the function's arguments because this way you can do the HMAC of binary data as well as ASCII/UTF-8 encoded strings. If you're not going to use binary data, feel free to remove the sizes from the arguments and calculating the size inside of the function with strlen like I did in the main when I called the function.
-I didn't wrap the creation of the gcry_mac_hd_t in the function because it's more efficient to reuse the same handler and just reset it every time you need to reuse it then to create a new one every time you need it. This optimization is even more noticeable if you call this function many times in the same execution!

Send a variable to a function and modify this variable in C

I have the following vars:
char seed[NBITS + 1], x0[NBITS + 1], y0[NBITS + 1], z0[NBITS + 1], dT0[NBITS + 1];
And i want to change it values on this function:
void lfsr(char *bin, char *output)
{
//bits significativos para fazer o xor NBITS -> NBITS,126,101,99;
int bits[4];
int bit;
if(bin[0] == '0')
bits[0] = 0;
else if(bin[0] == '1')
bits[0] = 1;
if(bin[2] == '0')
bits[1] = 0;
else if(bin[2] == '1')
bits[1] = 1;
if(bin[21] == '0')
bits[2] = 0;
else if(bin[21] == '1')
bits[2] = 1;
if(bin[19] == '0')
bits[3] = 0;
else if(bin[19] == '1')
bits[3] = 1;
bit = bits[0] ^ bits[1] ^ bits[2] ^ bits[3] ^ 1;
//reconstruir o vector de char depois do lfsr
for(int i = 127; i >= 1; i--)
{
bin[i] = bin[i - 1];
}
bin[0] = (char)(48 + bit);
output = bin;
}
The way that I put the value in y0 from x is, for example, calling the lfsr functions like this:
lfsr(x0, y0);
What am I doing wrong?
I have to do 3 Fibonacci Linear Feedback Shift Register starting from x0.
x0 = 10101010101010
y0 = lfsr(101010101010)
z0 = lfsr(y0)
dT0 = lfsr(z0);
The results are good, but when I do the above code the value of x0 will be the same as dT0 if i use pointers.
Can anyone help me?
Thanks. Cumps!
Consider the following:
The numbers correspond to the taps. The bits are actually 15..0, left to right. The following is my implementation of the Fibonacci Linear Feedback Shift Register:
#include <stdio.h>
uint16_t fibLfsr(const uint16_t num)
{
uint16_t tempNum;
tempNum = (num) ^ (num >> 2) ^ (num >> 3) ^ (num >> 5);
tempNum = (tempNum & 0x1) << 15;
tempNum = (tempNum | (num >> 1));
return tempNum;
}
int main(void)
{
uint16_t testNum = 0xACE1;
printf("%#X\n", testNum);
testNum = fibLfsr(testNum);
printf("%#X\n", testNum);
return 0;
}
I'm not quite sure why you're using strings and converting them to binary. If this is necessary, you'll need some of the standard library APIs in stdlib and string to convert the string to an uint16_t before calling fibLfsr() and back to a string afterwards.

Resources