Segmentation fault within do_crypt() - c

This is my code but when I run it, it gives me a segmentation fault in the function do_crypt(). When I try to print all the keys in the function it will only print out a few and I don't know why because if I print all the keys before calling do_crypt it will print them without any issues.
Any advice in fixing this would be lovely!!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <openssl/evp.h>
#define MAX_LINE_NUM 25143
#define MAX_LINE_LEN 80
#define MAX_WORDS 25143
#define MAX_WORD_LEN 30
char words[MAX_WORDS][MAX_WORD_LEN];
unsigned char output[] = "";
void read_KeyFile(int *line_counter, char *KeyFilename, char arr[MAX_LINE_NUM][MAX_LINE_LEN]){
FILE *fptr;
char read_line[MAX_LINE_LEN];
char buffer[MAX_LINE_NUM];
const char delim[] = " \n";
int buff_line_num = 0;
int word_counter = 0;
char *token;
fptr = fopen(KeyFilename, "r");
while(fgets(read_line, MAX_LINE_LEN, fptr) != NULL){
strncpy(arr[*line_counter], read_line, MAX_LINE_LEN);
*line_counter = *line_counter + 1;
}
fclose(fptr);
for (int i = 0; i<*line_counter; i++){
strncpy(buffer, arr[buff_line_num], MAX_LINE_LEN);
token = strtok(buffer, delim);
while(token != NULL){
strncpy(words[word_counter], token, MAX_WORD_LEN);
word_counter = word_counter + 1;
token = strtok(NULL, delim);
}
buff_line_num++;
}
}
int do_crypt(char plaintext[], char ciphertext[], unsigned char tempKey[], unsigned char output[], int do_encrypt){
unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen;
EVP_CIPHER_CTX ctx;
unsigned char iv[] = "aabbccddeeff00998877665544332211";
unsigned char key[] = "";
strcpy(key, tempKey);
int len = strlen(key);
if (len < 16){
for (int i=0; i<(16-len)+1; i++){
strcat(key, "#");
}
}
FILE *in;
in = fopen("Input.txt", "r");
FILE *out;
out = fopen("output.txt", "w");
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, do_encrypt);
OPENSSL_assert(EVP_CIPHER_CTX_key_length(&ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(&ctx) == 16);
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
for(;;) {
inlen = fread(inbuf, 1, 1024, in);
if(inlen <= 0) break;
if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen)){
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
strcpy(output, outbuf);
}
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)){
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
strcpy(output, outbuf);
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
void toHexConverter(unsigned char output[], int i, unsigned char tempKey[17]){
char hex[100];
for (int j=0, k=0; j<strlen(output); ++j, k +=2){
sprintf(hex + k, "%02x", output[j] & 0xff);
}
strcpy(output, hex);
}
int main(int argc, char *argv[]){
char plaintext[] = "This is a top secret.";
unsigned char ciphertext[] = "764aa26b55a4da654df6b19e4bce00f4ed05e09346fb0e762583cb7da2ac93a2";
char hexCompare[] = "";
int line_counter = 0;
char *KeyFilename = NULL;
char lines[MAX_LINE_NUM][MAX_LINE_LEN];
unsigned char tempKey[] = "";
int do_encrypt = 1;
KeyFilename = argv[1];
read_KeyFile(&line_counter, KeyFilename, lines);
for (int i=0; i<MAX_WORDS; i++){
// printf("%s\n", words[i]);
strcpy(tempKey, words[i]);
do_crypt(plaintext, ciphertext, tempKey, output, do_encrypt);
}
}

Related

Problems working on CSV archive and array of structures on C

I am a complete beginner. I am trying to use strtok in C to read a
CSV file, and store the contents into an array structure for each column, but I have a "segmentation fault" message. I will appreciate any advice. Before this I should make a column for deaths/cases and sorting the lines in ascending order, but first I should fix this code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 200
#define COUNT 2
typedef struct data_s {
char iso[SIZE];
char continent[SIZE];
char location[SIZE];
char date[SIZE];
unsigned int cases;
unsigned int deaths;
} data_t;'
int j = 1;
int main()
{
FILE *myfile;
myfile = fopen("owid-covid-data-small.csv", "r");
if (myfile == NULL)
{
printf("Archivo no encontrado.");
}
rewind(myfile);
char myLine[SIZE];
char *delimiter = ",";
char buffer[SIZE];
memset(buffer, 0, sizeof(buffer));
int i = 0;
for (char c = getc(myfile); c != EOF; c = getc(myfile))
{
if (c == '\n')
{
j++;
}
}
data_t temp_data[j];
memset(&temp_data, 0, j*sizeof(data_t));
rewind(myfile);
while (fgets(myLine, 200, (FILE*)myfile) != NULL && i<j)
{
strcpy(temp_data[i].iso, strtok(myLine, delimiter));
strcpy(temp_data[i].continent, strtok(myLine, delimiter));
strcpy(temp_data[i].location, strtok(myLine, delimiter));
strcpy(temp_data[i].date, strtok(myLine, delimiter));
temp_data[i].cases = atoi(strtok(NULL, delimiter));
strncpy(buffer, strtok(NULL, delimiter), SIZE);
temp_data[i].deaths = atoi(buffer);
memset(buffer, 0, sizeof(buffer));
i++;
for (int i = 0; i < COUNT; i++)
{
printf("Country: %s\n", temp_data[i].location);
printf("Continent: %s\n", temp_data[i].continent);
printf("Date: %s\n", temp_data[i].date);
printf("Total cases: %u\n", temp_data[i].cases);
printf("Total deaths: %u\n", temp_data[i].deaths);
printf("\n");
}
memset(&temp_data, 0, sizeof(data_t));
}
fclose(myfile);
}

Tested File Reads as expected but on Complete Code Not Working

I have tested the following code to read the tester.txt file and it outputted my expectation, however, when I inserted similar code in my complete code, it just stuck at: "Data from the file:" Why it is not outputting my expectation?
#include <stdio.h>
#include <stdlib.h>
char c[1000];
FILE *fptr;
int fileReader(){
if ((fptr = fopen("tester.txt", "r")) == NULL) {
printf("Error! File cannot be opened.");
// Program exits if the file pointer returns NULL.
exit(1);
}
// reads text until newline is encountered
fscanf(fptr, "%[^\n]", c);
fclose(fptr);
}
int main() {
fileReader();
printf("Data from the file:\n%s", c);
char* anotherone = (char*) c;
printf(anotherone);
return 0;
}
Another code to read file:
int fileReader() {
fp = fopen("tester.txt", "r");
fscanf(fp, "%s", c);
fclose(fp);
}
The complete code is:
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int success = 0;
void handleOpenSSLErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}
unsigned char* decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv ){
EVP_CIPHER_CTX *ctx;
unsigned char *plaintexts;
int len;
int plaintext_len;
unsigned char* plaintext = malloc(ciphertext_len);
bzero(plaintext,ciphertext_len);
if(!(ctx = EVP_CIPHER_CTX_new())) handleOpenSSLErrors();
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleOpenSSLErrors();
EVP_CIPHER_CTX_set_key_length(ctx, EVP_MAX_KEY_LENGTH);
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleOpenSSLErrors();
plaintext_len = len;
// return 1 if decryption successful, otherwise 0
if(1 == EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
success = 1;
plaintext_len += len;
/* Add the null terminator */
plaintext[plaintext_len] = 0;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
//delete [] plaintext;
return plaintext;
}
size_t calcDecodeLength(char* b64input) {
size_t len = strlen(b64input), padding = 0;
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
padding = 2;
else if (b64input[len-1] == '=') //last char is =
padding = 1;
return (len*3)/4 - padding;
}
void Base64Decode( char* b64message, unsigned char** buffer, size_t* length) {
BIO *bio, *b64; // A BIO is an I/O strean abstraction
int decodeLen = calcDecodeLength(b64message);
*buffer = (unsigned char*)malloc(decodeLen + 1);
(*buffer)[decodeLen] = '\0';
bio = BIO_new_mem_buf(b64message, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);
//BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
*length = BIO_read(bio, *buffer, strlen(b64message));
BIO_free_all(bio);
}
void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv )
{
//initialisatio of key and iv with 0
bzero(key,sizeof(key));
bzero(iv,sizeof(iv));
EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv);
}
int checkPlaintext(char* plaintext, char* result){
int length = 10; // we just check the first then characters
return strncmp(plaintext, result, length);
}
char *cas[1000];
FILE *fptr;
int fileReader(){
if ((fptr = fopen("tester.txt", "r")) == NULL) {
printf("Error! File cannot be opened.");
// Program exits if the file pointer returns NULL.
exit(1);
}
// reads text until newline is encountered
fscanf(fptr, "%[^\n]", cas);
fclose(fptr);
}
int main (void)
{
fileReader();
printf("Data from the file:\n%s", cas);
char* ciphertext_base64 = (char*) cas;
char* plaintext = "to be or not to be is the question";
char dict[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int decryptedtext_len, ciphertext_len, dict_len;
// cipher (binary) pointer and length
size_t cipher_len; // size_t is sizeof(type)
unsigned char* ciphertext;
unsigned char salt[8];
ERR_load_crypto_strings();
Base64Decode(ciphertext_base64, &ciphertext, &cipher_len);
unsigned char key[16];
unsigned char iv[16];
unsigned char plainpassword[] = "00000";
unsigned char* password = &plainpassword[0];
// retrive the slater from ciphertext (binary)
if (strncmp((const char*)ciphertext,"Salted__",8) == 0) { // find the keyword "Salted__"
memcpy(salt,&ciphertext[8],8);
ciphertext += 16;
cipher_len -= 16;
}
dict_len = strlen(dict);
time_t begin = time(NULL);
for(int i=0; i<dict_len; i++)
for(int j=0; j<dict_len; j++)
for(int k=0; k<dict_len; k++)
for(int l=0; l<dict_len; l++)
for(int m=0; m<dict_len; m++){
*password = dict[i];
*(password+1) = dict[j];
*(password+2) = dict[k];
*(password+3) = dict[l];
*(password+4) = dict[m];
initAES(password, salt, key, iv);
unsigned char* result = decrypt(ciphertext, cipher_len, key, iv);
if (success == 1){
if(checkPlaintext(plaintext, result)==0){
printf("Password is %s\n", password);
time_t end = time(NULL);
printf("Time elpased is %ld seconds", (end - begin));
return 0;
}
}
free(result);
}
// Clean up
EVP_cleanup();
ERR_free_strings();
return 0;
}
char *cas[1000]; should be char cas[1000];, I would say this is the main issue, you are using an array of pointers as if it was a character array, this is very likely what's causing your program to fail.
Fix bzero, pass the size of the array as argument. When you use sizeof(key) in initAES(), what you are actually getting is the size of the pointer, not the size of the container it points to. More oh this in How to find the 'sizeof' (a pointer pointing to an array)?
You can add size of the array as a global constant with a macro:
#define SIZE 16 // size of the arrays
//...
void initAES(const unsigned char *pass, unsigned char* salt, unsigned char* key, unsigned char* iv )
{
//initialisatio of key and iv with 0
bzero(key, SIZE);
bzero(iv, SIZE);
EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, pass, strlen(pass), 1, key, iv);
}
You can use it to define the size in main making your code more consistent.
int main (void)
{
//...
unsigned char key[SIZE];
unsigned char iv[SIZE];
//...
}
For good measure make fileReader have void return type if you don't want it to return an int.
I always advise the use of compiler warnings at full blast and preferably to treat warnings as errors.

Can't encrypt long string with XOR C crypter

I wrote a C program to perform an XOR encryption,
my problem is that the program is not able to encrypt files with more than 24 characters.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define BUF_SIZE 2
char* xor(char*, char*);
char* gen_key(size_t);
int main(int argc, char **argv) {
char *buffer = NULL,* encrypted_buffer = NULL;
size_t file_size;
char *key = gen_key(6);
char tmp_buffer[BUF_SIZE];
FILE *finput = NULL, *foutput = NULL;
finput = fopen("file.txt", "rb");
fseek(finput, 0, SEEK_END);
file_size = ftell(finput);
rewind(finput);
printf("File size : %d\n", (int)file_size);
buffer = (char*)malloc((file_size + 1) * sizeof(char));
memset(buffer, 0, sizeof(buffer));
while (!feof(finput)) {
memset(tmp_buffer, 0, sizeof(tmp_buffer));
fgets(tmp_buffer, sizeof(tmp_buffer), finput);
strcat(buffer, tmp_buffer);
}
printf("%s", buffer);
encrypted_buffer = xor(buffer, key);
free(buffer);
buffer = xor(encrypted_buffer, key);
printf("Encrypted : %s\n", encrypted_buffer);
printf("Decrypted : %s\n", buffer);
printf("EOF\n");
free(encrypted_buffer);
fclose(finput);
return 0;
}
char *gen_key(size_t length) {
srand(time(NULL));
const char charset[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345679";
const size_t charset_size = (sizeof(charset) - 1);
unsigned int i;
char *key = NULL;
key = (char*)malloc((length + 1) * sizeof(char));
memset(key, 0, sizeof(key));
for (i = 0; i < length; i++)
key[i] = charset[rand() % charset_size];
return key;
}
char *xor(char *file, char *key) {
unsigned int i;
char *xor = NULL;
xor = (char*)malloc(sizeof(file));
memset(xor, 0, sizeof(xor));
for (i = 0; i < strlen(file); i++)
*(xor + i) = *(file + i) ^ *(key + (i % strlen(key) - 1));
return xor;
}
And the output is :
File size : 55
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklimnopqrstuvwxyz
Encrypted : A2#G8- M >7S$1!
Decrypted : ABCDEFGHIJKLMNOPQRSTUVWX!:!e!
EOF
There are multiple problems in your code:
The buffer size is very small: #define BUF_SIZE 2. You should use a reasonable size for the line buffer, such as 80 or 100.
in memset(buffer, 0, sizeof(buffer));, buffer is a pointer, so sizeof(buffer) is not the size of the array, just the size of the pointer. Use file_size + 1 in this case.
You make the same mistake in other places in your code: pass the size of the buffers instead of relying on the sizeof() operator.
while (!feof(f)) is always wrong: you could jut use fread to read the file in one step or read line by line with:
while (fgets(tmp_buffer, sizeof(tmp_buffer), finput)) {
...
Note that there is a major problem with your approach: the key is composed of letters and digits and the file is assumed to contain text. If the file contains one of the characters in the key at the appropriate position, xoring this character with the key byte will produce a null byte that will stop the output in printf() and that would also stop the decryption if you were to store it in an output file. You rightfully use binary mode ("rb") for the file stream, but you should also make no assumptions on the file contents and handle null bytes transparently.
Here is a modified version of your program:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
unsigned char *xor(unsigned char *file, size_t size, const char *key);
char *gen_key(size_t length);
void print_buffer(const char *msg, unsigned char *buf, size_t size) {
printf("%s: ", msg);
for (size_t i = 0; i < size; i++) {
switch (buf[i]) {
case '\n':
printf("\\n");
break;
case '\\':
printf("\\\\");
break;
default:
if (buf[i] >= ' ' && buf[i] < 127)
putchar(buf[i]);
else
printf("\\%02x", buf[i]);
break;
}
}
printf("\n");
}
int main(int argc, char **argv) {
long file_size, nread, nwritten;
unsigned char *buffer, *encrypted_buffer, *decrypted_buffer;
char *key = gen_key(6);
FILE *finput = fopen("file.txt", "rb");
if (finput == NULL) {
fprintf(stderr, "cannot open file.txt: %s\n", strerror(errno));
return 1;
}
fseek(finput, 0, SEEK_END);
file_size = ftell(finput);
rewind(finput);
printf("File size: %ld\n", file_size);
buffer = calloc(file_size, sizeof(char));
nread = fread(buffer, 1, file_size, finput);
if (nread != file_size) {
fprintf(stderr, "error reading file.txt: read %ld bytes, expected %ld\n",
nread, file_size);
}
fclose(finput);
FILE *foutput = fopen("output.bin", "wb");
if (foutput == NULL) {
fprintf(stderr, "cannot open output.bin: %s\n", strerror(errno));
return 1;
}
encrypted_buffer = xor(buffer, nread, key);
nwritten = fwrite(encrypted_buffer, 1, nread, foutput);
if (nwritten != nread) {
fprintf(stderr, "error writing output.bin: wrote %ld bytes, expected %ld\n",
nwritten, nread);
}
fclose(foutput);
decrypted_buffer = xor(encrypted_buffer, nread, key);
printf("Key : %s\n", key);
print_buffer("Original ", buffer, nread);
print_buffer("Encrypted", encrypted_buffer, nread);
print_buffer("Decrypted", decrypted_buffer, nread);
if (!memcmp(decrypted_buffer, buffer, nread))
printf("OK\n");
free(decrypted_buffer);
free(encrypted_buffer);
free(buffer);
return 0;
}
char *gen_key(size_t length) {
const char charset[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345679";
const size_t charset_size = sizeof(charset) - 1;
char *key = (char*)calloc(length + 1, sizeof(char));
size_t i;
srand(time(NULL));
for (i = 0; i < length; i++)
key[i] = charset[rand() % charset_size];
return key;
}
unsigned char *xor(unsigned char *file, size_t size, const char *key) {
size_t i, keylen = strlen(key);
unsigned char *xor = calloc(size, sizeof(char));
for (i = 0; i < size; i++)
xor[i] = file[i] ^ key[i % keylen];
return xor;
}

Reading from a file into an array of chars

I'm trying to read a list of strings from a file to an array.
in file it looks like this
ItemOne
ItemTwo
ItemThree etc.
I declared an array as:
char** array;
and file as:
FILE *read;
This is what I came up with:
{
i = 0;
printf("Type in the name of the file\n");
scanf("%s", &name);
read = fopen(name, "r");
if (read == NULL)
{
perror("Doesn't work");
return 1;
}
else
{
array = malloc(100 * sizeof(*array));
while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", &array[i]);
i++;
}
}
}
Tt compiles, but when I try to display the array it's empty. Any ideas?
while (!feof(read))
{
array[i] = malloc(32 * sizeof(*array[i]));
fscanf(read, "%s", array[i]); //You should pass a pointer to a pointer to array of chars
i++;
}
I hope it'll work...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long GetFileSize(FILE *fp){
long fsize = 0;
fseek(fp,0,SEEK_END);
fsize = ftell(fp);
fseek(fp,0,SEEK_SET);//reset stream position!!
return fsize;
}
char *ReadToEnd(const char *filepath){
FILE *fp;
long fsize;
char *buff;
if(NULL==(fp=fopen(filepath, "rb"))){
perror("file cannot open at ReadToEnd\n");
return NULL;
}
fsize=GetFileSize(fp);
buff=(char*)malloc(sizeof(char)*fsize+1);
fread(buff, sizeof(char), fsize, fp);
fclose(fp);
buff[fsize]='\0';
return buff;
}
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=strdup(p);
}
*array=NULL;
*len=c;
free(text);
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
while(*sa)
free(*sa++);//for string
free(array); //for array
}
}
int main(){
char *text, **lines;
size_t line_count;
text=ReadToEnd("data.txt");
lines=split(text, "\r\n", &line_count);
free(text);
{ //test print
int i;
for(i=0;i<line_count;++i)
printf("%s\n", lines[i]);
}
free4split(lines);
return 0;
}

OpenSSL libs: 2 on Linux libcrypto and libssl and more than 13 on windows. What shall I link on windows to compile my sample?

So I look at this sample code:
#include <stdio.h>
#include <string.h>
#include "openssl/sha.h"
void sha256(char *string, char outputBuffer[65])
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, string, strlen(string));
SHA256_Final(hash, &sha256);
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}
int sha256_file(char *path, char outputBuffer[65])
{
FILE *file = fopen(path, "rb");
if(!file) return -534;
byte hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
const int bufSize = 32768;
byte *buffer = malloc(bufSize);
int bytesRead = 0;
if(!buffer) return ENOMEM;
while((bytesRead = fread(buffer, 1, bufSize, file)))
{
SHA256_Update(&sha256, buffer, bytesRead);
}
SHA256_Final(hash, &sha256);
sha256_hash_string(hash, outputBuffer);
fclose(file);
free(buffer);
return 0;
}
int main()
{
static unsigned char buffer[65];
sha256("string", buffer);
printf("%s\n", buffer);
}
What libs shall I link to my project to compile this on windows?
I use the pre-compiled DLL flavor of OpenSSL and it works fine for me.

Resources