Sending file directory from one function to another - c

In this programme I want to ask the user to enter the file path of the image, this takes place in the main function. However the open file takes place in another function.
To get the variable (location) to communicate between both functions, I declared it as a global variable, however, when the programme is executed no file path can be found.
Here is a snippet from the main function:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
char * scale = "8Xoi?;`. ";
int numScale;
char * location;
typedef struct
{
size_t width;
size_t height;
unsigned char * data;
} image;
unsigned char luminanceFromRGB(unsigned char r, unsigned char g, unsigned char b)
{
return (unsigned char) (0.2126 * r + 0.7152 * g + 0.0722 * b);
}
//Loads image and saves it to img as an image pointer.
long loadImage(image ** img, char * location)
{
FILE *f = fopen(location, "rb");
if (f == NULL)
{
puts("Opening failed...");
return 0;
}
unsigned char * result;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
result = (unsigned char *) malloc((size_t) size);
if (size != fread(result, sizeof(unsigned char), (size_t) size, f))
{
free(result);
puts("Reading failed...");
fclose(f);
return 0;
}
fclose (f);
if (size < 54)
{
free(result);
puts("Invalid file...");
return 0;
}
size_t pdOffset = result[10] | result[11] << 8 | result[12] << 16 | result[13] << 24;
unsigned long width = result[18] | result[19] << 8 | result[20] << 16 | result[21] << 24;
unsigned long height = result[22] | result[23] << 8 | result[24] << 16 | result[25] << 24;
unsigned long bpp = result[28] | result[29] << 8;
int noCompression = result[30] == 0 && result[31] == 0 && result[32] == 0 && result[33] == 0;
if (bpp != 24 || !noCompression || width < 1 || height < 1 || width > 64000 || height > 64000)
{
free(result);
puts("Unsupported BMP format, only 24 bits per pixel are supported...");
return 0;
}
int bytesPerPixel = (int) (bpp / 8);
size_t rowBytes = (width * bytesPerPixel + 3) / 4 * 4;
printf("Bytes per row: %zu\n", rowBytes);
size_t usedRowBytes = width * bytesPerPixel;
size_t imageBytes = rowBytes * height;
*img = malloc(sizeof(image));
(*img)->height = height;
(*img)->width = width;
size_t imgSize = width * height;
(*img)->data = (unsigned char *) malloc(imgSize);
printf("Offset: %zu\n", pdOffset);
unsigned char * ptr = (*img)->data;
unsigned char * srcPtr = &result[pdOffset];
for (size_t i = 0; i < imgSize; ++i)
{
unsigned char r = *srcPtr;
unsigned char g = *(srcPtr + 1);
unsigned char b = *(srcPtr + 2);
*ptr = luminanceFromRGB(r, g, b);
ptr++;
srcPtr += bytesPerPixel;
if (i % width == 0)
{
srcPtr += rowBytes - usedRowBytes;
}
}
free(result);
return size;
}
//Assigns a ASCII character (scale) depending on the images brightness
void sprintchar(char *dst, image *img) {
for (size_t y = img->height - 1; y > 0; --y) {
for (size_t x = 0; x < img->width; ++x) {
unsigned char c = *(img->data + x + img->width * y);
int rescaled = c * numScale / 256;
*dst++ = scale[numScale - rescaled];
}
*dst++ = '\n';
}
*dst++ = 0;
}
void release(image * img)
{
if (img)
{
if (img->data)
free(img->data);
free(img);
}
}
int main(int argc, char ** argv)
{
char filepath [99];
printf("Enter file path: \n");
scanf_s("%s", &filepath);
location = filepath;
if (argc != 2)
{
puts("Argument needed: filename.");
return 1;
}
puts(argv[1]);
setbuf(stdout, 0);
numScale = strlen(scale) - 1;
printf("ASCII Brightness Scale: %d\n", numScale);
image *img = NULL;
if (loadImage(&img, argv[1]))
{
printf("Image dimensions: %zux%zu\n", img->width, img->height);
//Prints ASCII characters in terminal
char buf[1000000]; // 1M should be enough
sprintchar(buf, img);
//printf("%s", buf); // or whatever
release(img);
}
return 0;
}

Related

Saving the ASCII output to a variable

This C code converts a BMP image to a ASCII art. The output is displayed in the terminal.
However I want to modify the programme and save the outputted characters to a string variable. The problem being that img which outputs the characters is a image pointer.
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
char * scale = "8Xoi?;`. ";
int numScale;
typedef struct
{
size_t width;
size_t height;
unsigned char * data;
} image;
unsigned char luminanceFromRGB(unsigned char r, unsigned char g, unsigned char b)
{
return (unsigned char) (0.2126 * r + 0.7152 * g + 0.0722 * b);
}
//Loads image and saves it to img as an image pointer.
long loadImage(image ** img, char * location)
{
FILE *f = fopen(location, "rb");
if (f == NULL)
{
puts("Opening failed...");
return 0;
}
unsigned char * result;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
result = (unsigned char *) malloc((size_t) size);
if (size != fread(result, sizeof(unsigned char), (size_t) size, f))
{
free(result);
puts("Reading failed...");
fclose(f);
return 0;
}
fclose (f);
if (size < 54)
{
free(result);
puts("Invalid file...");
return 0;
}
size_t pdOffset = result[10] | result[11] << 8 | result[12] << 16 | result[13] << 24;
unsigned long width = result[18] | result[19] << 8 | result[20] << 16 | result[21] << 24;
unsigned long height = result[22] | result[23] << 8 | result[24] << 16 | result[25] << 24;
unsigned long bpp = result[28] | result[29] << 8;
int noCompression = result[30] == 0 && result[31] == 0 && result[32] == 0 && result[33] == 0;
if (bpp != 24 || !noCompression || width < 1 || height < 1 || width > 64000 || height > 64000)
{
free(result);
puts("Unsupported BMP format, only 24 bits per pixel are supported...");
return 0;
}
int bytesPerPixel = (int) (bpp / 8);
size_t rowBytes = (width * bytesPerPixel + 3) / 4 * 4;
printf("Bytes per row: %zu\n", rowBytes);
size_t usedRowBytes = width * bytesPerPixel;
size_t imageBytes = rowBytes * height;
*img = malloc(sizeof(image));
(*img)->height = height;
(*img)->width = width;
size_t imgSize = width * height;
(*img)->data = (unsigned char *) malloc(imgSize);
printf("Offset: %zu\n", pdOffset);
unsigned char * ptr = (*img)->data;
unsigned char * srcPtr = &result[pdOffset];
for (size_t i = 0; i < imgSize; ++i)
{
unsigned char r = *srcPtr;
unsigned char g = *(srcPtr + 1);
unsigned char b = *(srcPtr + 2);
*ptr = luminanceFromRGB(r, g, b);
ptr++;
srcPtr += bytesPerPixel;
if (i % width == 0)
{
srcPtr += rowBytes - usedRowBytes;
}
}
free(result);
return size;
}
//Assigns a ASCII character (scale) depending on the images brightness
void printchar(image * img)
{
for (size_t y = img->height - 1; y > 0; --y)
{
for (size_t x = 0; x < img->width; ++x)
{
unsigned char c = *(img->data + x + img->width * y);
int rescaled = c * numScale / 256;
putchar(scale[numScale - rescaled]);
}
putchar('\n');
}
}
void release(image * img)
{
if (img)
{
if (img->data)
free(img->data);
free(img);
}
}
int main(int argc, char ** argv)
{
if (argc != 2)
{
puts("Argument needed: filename.");
return 1;
}
puts(argv[1]);
setbuf(stdout, 0);
numScale = strlen(scale) - 1;
printf("ASCII Brightness Scale: %d\n", numScale);
image *img = NULL;
if (loadImage(&img, argv[1]))
{
printf("Image dimensions: %zux%zu\n", img->width, img->height);
//Prints ASCII characters in terminal
printchar(img);
release(img);
}
return 0;
}
Change main() to
//printchar(img);
char buf[1000000]; // 1M should be enough
sprintchar(buf, img);
printf("%s", buf); // or whatever
and change/copy printchar() to
void sprintchar(char *dst, image *img) {
for (size_t y = img->height - 1; y > 0; --y) {
for (size_t x = 0; x < img->width; ++x) {
unsigned char c = *(img->data + x + img->width * y);
int rescaled = c * numScale / 256;
*dst++ = scale[numScale - rescaled];
}
*dst++ = '\n';
}
*dst = 0;
}

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!

file size exceeds buffer size

I want to compare 2 files for identical lines: mytab2411.txt(15,017,210 bytes in size) and shadow.txt (569 bytes in size) but when I compiled this code and ran the program, I get a segmentation fault. I know that it's because the "mytab2411.txt" file exceeds the size of "char buf" but how do I go about solving this problem without overflowing the buffer?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
int cmp(const void * s1, const void * s2)
{
return strcasecmp(*(char **)s1, *(char **)s2);
}
int cmp_half(const char * s1, const char * s2)
{
int i;
for (i = 0; i < 3; i++)
{
int res = strncasecmp((char *)s1+i*3, (char *)s2+i*3, 2);
if (res != 0) return res;
}
return 0;
}
char * line[1024];
int n = 0;
int search(const char * s)
{
int first, last, middle;
first = 0;
last = n - 1;
middle = (first+last)/2;
while( first <= last )
{
int res = cmp_half(s, line[middle]);
if (res == 0) return middle;
if (res > 0)
first = middle + 1;
else
last = middle - 1;
middle = (first + last)/2;
}
return -1;
}
int main()
{
FILE * f1, * f2;
char * s;
char buf[1024*1024], text[1024];
f1 = fopen("shadow.txt", "rt");
f2 = fopen("mytab2411.txt", "rt");
s = buf;
while (fgets(s, 1024, f2) != NULL)
{
line[n] = s;
s = s+strlen(s)+1;
n++;
}
qsort(line, n, sizeof(char *), cmp);
while (fgets(text, 1024, f1) != NULL)
{
text[strlen(text)-1] = 0;
int idx = search(text);
if (idx >= 0)
{
printf("%s matched %s\n", text, line[idx]);
}
else
{
printf("%s not matched\n", text);
}
}
return 0;
}
Your method assumes that each line in the file is 1024 bytes long. In practice the lines can be up to 1024 bytes, but most lines are much shorter. Use strdup or malloc to allocate memory for each line based on line's length.
Store the lines in dynamically allocated arrays. This is about 15 MB of data and it should not be a problem unless there are resource limitations.
int main(void)
{
char buf[1024];
char **arr1 = NULL;
char **arr2 = NULL;
int size1 = 0;
int size2 = 0;
FILE * f1, *f2;
f1 = fopen("shadow.txt", "r");
f2 = fopen("mytab2411.txt", "r");
while(fgets(buf, 1024, f1))
{
size1++;
arr1 = realloc(arr1, sizeof(char*) * size1);
arr1[size1 - 1] = strdup(buf);
}
while(fgets(buf, 1024, f2))
{
size2++;
arr2 = realloc(arr2, sizeof(char*) * size2);
arr2[size2 - 1] = strdup(buf);
}
for(int i = 0; i < size1; i++)
for(int j = 0; j < size2; j++)
{
if(strcmp(arr1[i], arr2[j]) == 0)
printf("match %s\n", arr1[i]);
}
return 0;
}

Why does Horspool not work on binaries?

I'm trying to make a quick and simple signature detection program in C. It should read a binary file (.exe, ELF, a library, etc...) and search for binary data (sometimes strings, sometimes bytes);
I have a simple test program in C:
#include <stdio.h>
#include <unistd.h>
const char *str = "TestingOneTwoThree";
int main()
{
while(1)
{
fprintf(stdout, "%s %ld\n", str, (long)getpid());
sleep(1);
}
}
Here is the horspool algorithm I'm using. I adapted it directly from the wikipedia pseudocode found here: https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HORSPOOL_COUNT 256
#define BLOCK_SIZE 1024
#define MAX(a, b) a > b ? a : b
ssize_t horspool_find(const char *buf, size_t buflen, const char *egg, size_t egglen)
{
int table[HORSPOOL_COUNT];
ssize_t shift = 0, i, tmp;
for(i = 0; i < HORSPOOL_COUNT; ++i)
{
table[i] = (int)egglen;
}
for(i = 0; i < egglen - 1; ++i)
{
table[(int)egg[i]] = egglen - i - 1;
}
while(shift <= buflen - egglen)
{
i = egglen - 1;
while(buf[shift + i] == egg[i])
{
if(i == 0)
{
return shift;
}
i--;
}
shift += MAX(1, table[(int)buf[shift + egglen - 1]]);
}
return -1;
}
char *readfile(const char *filename, size_t *size)
{
int ch;
size_t used = 0, allocated = 0;
char *buf = NULL, *tmp = NULL;
FILE *f;
if((f = fopen(filename, "rb")) == NULL)
{
if(size) *size = 0;
return perror("fopen"), NULL;
}
while((ch=fgetc(f)) != EOF)
{
if(used >= allocated)
{
allocated += BLOCK_SIZE;
tmp = realloc(buf, allocated);
if(tmp == NULL)
{
free(buf);
if(size) *size = 0;
fclose(f);
return perror("realloc"), NULL;
}
buf = tmp;
}
buf[used++] = (char)ch;
}
fclose(f);
if(size) *size = used;
return realloc(buf, used);
}
ssize_t naivealg_find(const char *buf, size_t buflen, const char *find, size_t findlen)
{
size_t i, j, diff = buflen - findlen;
for(i = 0; i < diff; ++i)
{
for(j = 0; j < findlen; ++j)
{
if(buf[i+j] != find[j])
{
break;
}
}
if(j == findlen)
{
return (ssize_t)i;
}
}
return -1;
}
int main()
{
size_t size;
char *buf = readfile("./a.out", &size);
char *pat = "TestingOneTwoThree";
ssize_t pos1 = horspool_find(buf, size, pat, strlen(pat));
ssize_t pos2 = naivealg_find(buf, size, pat, strlen(pat));
fprintf(stdout, "Offsets: %zd ~ %zd\n", pos1, pos2);
return 0;
}
Output is something along the lines of:
Offsets: -1 ~ 2052
Notes:
The same buffer and "egg" work with the naive search implementation.
The horspool implementation seems to work correctly with normal strings as the buf and egg parameters.
Code was using a signed char and with binary data, from time to time, would index incorrectly with a negative index.
// table[(int)buf[shift + egglen - 1]]
table[(unsigned char )buf[shift + egglen - 1]]
This problem also exists in the the egg pattern.
// table[(int) egg[i]] = egglen - i - 1;
table[(unsigned char) egg[i]] = egglen - i - 1;
Other sign issues occur when buflen < egglen
// while (shift <= buflen - egglen)
// change to avoid underflow
while (shift + egglen <= buflen)
Also consider opening the file in binary and:
ssize_t shift,i; --> size_t shift,i;
int table[HORSPOOL_COUNT]; -- > size_t table[HORSPOOL_COUNT];
Add ()s to #define MAX(a, b) (((a) > (b)) ? (a) : (b))

How to convert LSB extracted data to text or binary to text

UPDATE***********************
For reference I included the program I made for opening a PPM image - embedding a message into the image and then saving out a new image with the embedded text. With the function below I'm hoping to extra that message, (hidden in the LSB) and then converting it to text to display it. Thanks for the replies so far - I'm going to start testing them out and see if anything works.
I'm trying to write a function that extracts the LSB of an unsigned char value - puts them bits together to form an extracted message. I have the length of how many LSBs I need to extract from the file, but I'm having trouble with how to convert this into a message.
At first I extracted the first 8 bits into an int array - giving me something such as 00110000. Now I have an INT array with that value, and I need to convert it to a single char for the letter representation. However, I think I should be taking in all of the LSBs into an array that is messageLength * 7 and somehow converting that int array into the text. It would be giving me the binary represenation of the text before converting. Maybe theirs a way to convert a long string of 1's and 0's to text?
unsigned char * extBits(PPMImage *img, int messageLen, unsigned char * decMsg)
{
//int count = 2;
int embCount = 0;
int deM = messageLen * 7;
int count = 0;
unsigned char byte;
// int mask;
// unsigned char update;
// unsigned char flipOne = 0x01; //0x01
// unsigned char flipZero = 0xFE; //0x00
unsigned char dMsg[deM];
int byteArray[7];
int takeByte = 0;
unsigned char *extMsg;
char c;
for(int j = 0; j < 7; j++)
{
if(takeByte == 8)
{
//first letter extracted
takeByte = 0;
}
//byte = msgOne[j];
// byte = img->pixel[j];
//encMsg[j] = byte;
byte = img->pixel[j];
//printf("byte: %c\n", byte);
// printf("byte: %x\n", byte);
byte &= 1;
//printf("byte after: %x\n", byte);
dMsg[j] = byte;
byteArray[j] = byte;
data[j] = byteArray[j];
printf("dMsg:%x ", dMsg[j]);
// printf("pixel:%c \n", img->pixel[j]);
embCount++;
takeByte++;
}
/*
for(int r=0;r<7;r++)
{
printf("\n%d\n", byteArray[r]);
}
printf("count: %d", embCount);
printf("%s ", dMsg);
*/
return decMsg = dMsg;
}
embedding program*******
//////////////////////////////////////////////////////////////
/*
execute as ./emb -i <img2embed> -i <text file> -o <embedIMG>
*/
//////////////////////////////////////////////////////////////
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct {
int x, y;
unsigned char *pixel;
} PPMImage;
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
FILE * fp;
PPMImage *img;
int rgb_comp_color;
int size = 0;
fp = fopen(filename, "a+");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char *buff;
unsigned char stuff[16];
int c;
int x,y;
buff = (unsigned char*) malloc(sizeof(unsigned char)*size +1);
memset(buff, '\0', sizeof(unsigned char)*size+1);
fgets(stuff, sizeof(stuff), fp);
if (stuff[0] != 'P' || stuff[1] != '3') {
fprintf(stderr, "Invalid image format (must be 'P3')\n");
exit(1);
}
//alloc memory form image
img = (PPMImage*)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}
ungetc(c, fp);
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);
}
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n",filename);
exit(1);
}
//printf("x: %d y: %d\n", img->x, img->y);
unsigned char buffer[1024];
memset(buffer,0,1024);
fgets(buffer,1024,fp);
fread(buff, 1, size, fp);
img->pixel = buff;
/*
for(int h = 0; h < 20; h++)
{
printf("%c", buff2[h]);
}
printf("%s", buff2);
*/
fclose(fp);
return img;
}
void writePPM(const char *filename, unsigned char * img, int x, int y)
{
FILE *fp;
//open file for output
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//write the header file
//image format
fprintf(fp, "P3\n");
//comments
// fprintf(fp, "# Created by %s\n",CREATOR);
//image size
fprintf(fp, "%d %d\n",x,y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel pixel
fwrite(img,1, strlen(img), fp);
fclose(fp);
}
//unsigned char * embBits(PPMImage *img, int messageLen, unsigned char*msgOne, unsigned char *encMsg)
int embBits(PPMImage *img, int messageLen, unsigned char*msgOne, int embLen)
{
//int count = 2;
int embCount = 0;
int count = 0;
unsigned char *eMsg;
unsigned char byte;
int mask;
unsigned char update;
unsigned char flipOne = 0x01; //0x01
unsigned char flipZero = 0xFE; //0x00
for(int j = 0; j < messageLen; j++)
{
byte = msgOne[j];
//encMsg[j] = byte;
for(int k=7; 0 < k; k--)
{
update = byte;
update = update & (1<<k);
//printf("pixel:%c\n", img->pixel[count]);
//printf("pixel+1:%c\n", img->pixel[count+1]);
// printf("pixel+2:%c\n", img->pixel[count+2]);
if(update == 0)
{
// if i see 1 |=
// if i see a 0 &=
//img->pixel[count] = img->pixel[count] &= flipZero;
img->pixel[count+2] &= flipZero;
}
else
{
//flip bit
//red
//check LSB and FLIP
// img->pixel[count] = img->pixel[count] |= flipOne;
img->pixel[count+2] |= flipOne;
}
//mask--;
//eMsg[count] = img->pixel[count];
//printf("count: %d\n", count);
count = count + 3;
}
// eMsg[j] = byte;
}
//return encMsg = eMsg;
//unsigned char *yes = "sucess";
/*
for(int a = 0; a < messageLen; a++)
{
printf("pixel: %c", img->pixel[a]);
printf("msg: %c\n", eMsg[a]);
// eMsg[a] = img->pixel[a];
}
*/
embCount = count;
return embLen = embCount;
}
int main(int argc, char **argv){
int messageLen;
int i = 0;
PPMImage *img;
int size = 0;
FILE * fp;
int testSize;
fp = fopen(argv[4], "a+");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char *buff;
buff = (unsigned char*) malloc(sizeof(unsigned char)*size +1);
memset(buff, '\0', sizeof(unsigned char)*size+1);
fread(buff, 1, size, fp);
fclose(fp);
// printf("text encryption: %s\n", buff);
testSize = strlen(buff);
// printf("Size of text %d\n", testSize);
messageLen = strlen(buff);
img = readPPM(argv[2]);
/*
int testing = strlen(img->pixel);
for (int f=0;f<6;f++)
{
//f2 = 1
//f3 = 6
printf("%c", img->pixel[f]);
}
*/
// printf("%c \n", img->pixel[2]);
// printf("%c \n", img->pixel[5]);
printf("\n");
// unsigned char * encMsg;
int encMsg = 0;
encMsg = embBits(img, messageLen, buff, encMsg);
// printf("cipher msg:%s\n", img->pixel);
printf("message length: %d\n", messageLen);
// printf("cipher msg length: %d\n", encMsg);
writePPM(argv[6], img->pixel, img->x, img->y);
printf("Please press enter to complete\n");
getchar();
}
I don't know what you are doing specifically with your file and assigning each bit to a position in an array but you can print binary sequences stored in a unsigned int. Try using something like this...
#include <stdio.h>
int main() {
unsigned int arr[] = {00110110, 00111100, 10111011};
int i = sizeof(arr)/sizeof(arr[0]);
while(i-->0) {
printf("%c, ", arr[i]);
}
printf("\n");
}
You can use bit operations to gather these bits into a byte.
#include <stdio.h>
#define BYTE_LENGTH 8
#if 1
/* MSB is in data[0], LSB is in data[BYTE_LENGTH - 1] */
int arrayToChar(const int data[]) {
int c = 0;
int i;
for (i = 0; i < BYTE_LENGTH; i++) {
if (data[i]) c |= (1 << (BYTE_LENGTH - 1 - i));
}
return c;
}
#else
/* LSB is in data[0], MSB is in data[BYTE_LENGTH - 1] */
int arrayToChar(const int data[]) {
int c = 0;
int i;
for (i = 0; i < BYTE_LENGTH; i++) {
if (data[i]) c |= (1 << i);
}
return c;
}
#endif
int main(void) {
int data[8] = {0, 0, 1, 1, 0, 0, 0, 0};
int c = arrayToChar(data);
printf("%d %c\n", c, c);
return 0;
}
If you want to produce one byte from 7 bits, change BYTE_LENGTH to 7.
If you want to deal with long sequence of bits, apply arrayToChar repeatedly with changing the (address of) first element to be passed.

Resources