BlowFish Encryption: Cannot decrypt cipher to original plaintext - c

I'm using OpenSSL BlowFish and encountering something very strange. My functions are below:
char* BFEncrypt(char* key, char* text)
{
char ivec[EVP_MAX_IV_LENGTH] = {0};
int len = strlen(text);
char *cipher = (char*)malloc(sizeof(char)*(len+1));
int *num = (int*)malloc(sizeof(int));
*num = 0;
BF_KEY *bfkey = (BF_KEY*)malloc(sizeof(BF_KEY));
BF_set_key(bfkey, strlen(key), key);
BF_cfb64_encrypt(text, cipher, len, bfkey, ivec, num, BF_ENCRYPT);
cipher[len] = '\0';
free(num);
free(bfkey);
return cipher;
}
char* BFDecrypt(char* key, char* cipher)
{
char ivec[EVP_MAX_IV_LENGTH] = {0};
int len = strlen(cipher);
char *text = (char*)malloc(sizeof(char)*(len+1));
int *num = (int*)malloc(sizeof(int));
*num = 0;
BF_KEY *bfkey = (BF_KEY*)malloc(sizeof(BF_KEY));
BF_set_key(bfkey, strlen(key), key);
BF_cfb64_encrypt(cipher, text, len, bfkey, ivec, num, BF_DECRYPT);
text[len] = '\0';
free(num);
free(bfkey);
return text;
}
If I did something as below in a function, I can obtain the right plaintext from decryption:
char *plainText1;
char *key1;
//initialize those pointers
char *cipher1 = BFEncrypt(key1, plainText1);
char *temp = BFDecrypt(key1, cipher1); //here I test that temp is equal to plainText1
However, in a different function, if I only invoke the BFDecrypt, I would not be able to get the same plaintext before:
//somehow I stored the cipher1 above in my disk and read it
char *cipher2; //store cipher1
char *key2;// key2 is equal to key1
char *plaintext2 = BFDecrypct(key2, cipher2); //Here is the problem!!!!! plaintext2 is not equal to plaintext1
The confusing part is, even if key2 and cipher2 is exactly the same as key1 and cipher1 , plaintext2 is completely different with plaintext1. Could anyone give me a hint, I stuck on this for a long time.
Thanks in advance!

Related

BIO_get_mem_ptr is returnig 0 as length and output

Here I am trying to get the size of bio file as ,
long res = BIO_get_mem_ptr(certBio, &bptr);
length = bptr->length; // is the length
I got this sample code from some stackoverflow question. I have tried many time but the BIO_get_mem_ptr is giving a null pointer in bptr with return value 0. I can't find any solutions related to this problem in any reference sites.
Here is the source code,
int pass_cb(char *buf, int size, int rwflag, void *u)
{
int len;
char *tmp;
tmp = "123456";
len = strlen(tmp);
if (len <= 0)
return 0;
if (len > size)
len = size;
memcpy(buf, tmp, len);
return len;
}
int main(void)
{
X509 *x509;
int length = 0;
unsigned char data[1000];
unsigned char *buffer = NULL;
buffer = data;
BIO *certBio = BIO_new(BIO_s_file());
// BIO *certBio = BIO_new(BIO_s_mem()); -> have tried this one too gives the same result
BUF_MEM *bptr = 0;
BIO_read_filename(certBio, "E:\\share\\Folder\\TempCert.pem");
x509 = PEM_read_bio_X509_AUX(certBio, NULL, pass_cb, NULL);
long res = BIO_get_mem_ptr(certBio, &bptr);
length = bptr->length;
memset(&buffer, 0, 1000);
int ret = BIO_read(certBio, &buffer, length);
BIO_free_all(certBio);
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
return 0;
}
What is the problem causing here,
As you can see on The Man bio_get_mem_ptr wants a memory BIO
A memory BIO is a source/sink BIO which uses memory for its I/O. Data written to a memory BIO is stored in a BUF_MEM structure which is extended as appropriate to accommodate the stored data.
You are trying to use a file, so you should use the example code on The Man of bio_s_file

string function: insert - self implemented via a copy function

i got a new task from my teach to implement some basic string operations like append, remove, substr and insert.
while i was thinking at how should i approach this problem i thought i could just write a function which does the copying and ...
int copy(char* buffer,char * string,int begin,int end)
{
if(end == 0)
end = length(string);
//Copy from begin to end and save result into buffer
for(int i = 0; i < end;i++)
buffer[i] = *(string+begin+i);
return end;
}
with that implementation, so my idea i could just implement all the other functions asked by my teacher like this :
void insert(char* buffer,char * string, char * toInsert, int begin,int end)
{
//Copy till the position of the original string
begin = copy(buffer,
string,0,begin);
//Insert
//copy from the last change of the original string
begin = copy(buffer+begin,
toInsert,0,end);
//Copy whats left
copy(buffer+begin,
string);
}
So if i now try to insert something with this function i get some weird output:
int main() {
char * Hallo = "Hello World how are things?";
char * appendix = "Halt die schnauze!";
char buffer[128];
for (int i = 0; i < 128;i++)
buffer[i] = -0;
insert(buffer,Hallo,appendix,5,0);
printf("%s\n",buffer);
return 0;
}
output: HelloHalt die schnHello World how are things?
I simply cannot get my head around why the output does look like this. Do i have a logical mistake there?
fix like this:
#include <stdio.h>
size_t length(const char *s){
size_t len = 0;
while(*s++){
++len;
}
return len;
}
int copy(char *buffer, const char *string, int begin, int end){
int len = 0;//copy length
if(end == 0)
end = length(string);
for(int i = begin; i < end; i++)//End position is not included
buffer[len++] = string[i];
return len;
}
void insert(char *buffer, const char *string, const char *toInsert, int begin, int end){
int len;
len = copy(buffer, string, 0, begin);
len += copy(buffer + len, toInsert, 0, end);
len += copy(buffer + len, string, begin, end);
buffer[len] = 0;
}
int main(void) {
char * Hallo = "Hello World how are things?";
char * appendix = "Halt die schnauze!";
char buffer[128] = {0};
insert(buffer, Hallo, appendix, 5, 0);
printf("%s\n",buffer);
return 0;
}

Creating Variable Sized char Array in C

I am trying to take in a char array that is oversized in order to place delimiters in it based on the variable maxSize
For example if the string "This is a message" is passed to the function along with a maxSize of 4 then the output should be "This, is ,a me,ssag,e"
char *placeDelimiter(char message[], int maxSize) {
int msgSize = strlen(message);
int delSize = (msgSize/maxSize);
int remSize = msgSize%maxSize;
int newSize = msgSize+delSize;
if (remSize==0) delSize--; //removes delimiter if on end of char array
char temp[newSize];
int delPos = 0;
for (int x=0;x<msgSize;x++) {
if ((x+1)%maxSize == 0) temp[x] = ',';
temp[x+delPos] = message[x];
delPos = (x+1)/maxSize;
}
return (char *)temp;
}
int main()
{
char msg[] = "This is a message";
char *p;
p = placeDelimiter(msg, 4);
printf("%s", p);
return 0;
}
My problem is that I am getting the output "This i," from the input "This is a message" (From an online compiler). Can anyone explain to me what I am doing wrong and how to fix it?
char temp[newSize]; is a local variable to the function placeDelimiter(). Accessing it after the function has returned is Undefined behavior.
You should use dynamic memory allocation.
char* temp = malloc(newSize);

Encrypting and decrypting a message with Blowfish

Here is a basic code of encryping and decrypting a message:
#include <stdio.h>
#include <openssl/blowfish.h>
#include <string.h>
//gcc cryptage.c -o cryptage -lcrypto
int main(){
BF_KEY *key = malloc(sizeof(BF_KEY));
unsigned char *crypt_key = "Key of encryption";
const unsigned char *in = "Message to encrypt";
int len = strlen(crypt_key);
unsigned char *out = malloc(sizeof(char)*len);
unsigned char *result = malloc(sizeof(char)*len);
//Defining encryption key
BF_set_key(key, len, crypt_key);
//Encryption
BF_ecb_encrypt(in, out, key, BF_ENCRYPT);
//Décryption
BF_ecb_encrypt(out, result, key, BF_DECRYPT);
fprintf(stdout,"Result: %s\n",result);
return 0;
}
My problem is the result i get. It's always a String of 8 caracters, no more.
Can you please help me encrypt and decrypt the full message?
Thank you!
As #WhozCraig says, do things 8 bytes at a time.
The data to encrypt should be viewed as a byte array and not a C string.
So consider the string to encrypt with the \0 and padded with random data to form a byte array that is a multiple of 8.
Call encrypt multiple times, encrypting 8 bytes per iteration.
To decrypt, call decryption the same number of iterations. Note that the result buffer may need to be sized up to a multiple of 8.
const unsigned char *in = "Message to encrypt";
size_t InSize = strlen(in) + 1;
int KeyLen = strlen(crypt_key);
size_t OutSize = (InSize + 7) & (~7);
unsigned char *out = malloc(Outsize);
unsigned char *outnext = out;
//Defining encryption key
BF_set_key(key, KeyLen, crypt_key);
//Encryption
while (InSize >= 8) {
BF_ecb_encrypt(in, outnext, key, BF_ENCRYPT);
in += 8;
outnext += 8;
InSize -= 8;
}
if (Insize > 0) { // Cope with non-octal length
unsigned char buf8[8];
memcpy(buf8, in, InSize);
for (i=InSize; i<8; i++) {
buf8[i] = rand();
}
BF_ecb_encrypt(buf8, outnext, key, BF_ENCRYPT);
}
//Décryption
unsigned char *result = malloc(OutSize);
unsigned char *resultNext = result;
while (OutSize) {
BF_ecb_encrypt(out, resultNext, key, BF_DECRYPT);
out += 8;
resultNext += 8;
OutSize -= 8;
}
fprintf(stdout,"Result: %s\n",result);
// No need to print the random bytes that were generated.
return 0;
}
Not quite comfortable have a known byte (\0) encoded in the last block. A different length indication may be prudent.

C base64 encode string

Folks,
Trying to troubleshoot an issue with the base64 function below. About 2-3% of the requests that pass through this process return an incorrect (too short) base64output.
static const char *header_request_gce(request_rec *r, char *a)
{
char *tim = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
apr_rfc822_date(tim, r->request_time);
char *uri = apr_psprintf(r->pool, "%s", r->uri);
char encode[32768];
//encode = malloc(strlen(tim)+strlen(uri)); /* make space for the new string (should check the return value ...) */
strcpy(encode, "GET\n\n\n");
strcat(encode, tim);
strcat(encode, "\n");
strcat(encode, uri);
unsigned int encode_length = strlen(encode);
unsigned char* result;
unsigned char* key = (unsigned char*) "2kcXHh+K+XLtI61/KIV3d1tVzOooTdeOqFii9osz";
static char res_hexstring[8192];
result = HMAC(EVP_sha1(), key, 40, encode, encode_length, NULL, NULL);
char *base64(const unsigned char *input, int length);
char *base64output = base64(result, strlen(result));
return base64output;
}
char *base64(const unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
char *buff = (char *)malloc(bptr->length);
memcpy(buff, bptr->data, bptr->length-1);
buff[bptr->length-1] = 0;
BIO_free_all(b64);
return buff;
}
The key above has been modified ofcourse, but kept in the correct character format
This line is incorrect:
char *base64output = base64(result, strlen(result));
The data (output from sha1) that you are encoding can contain the NUL byte which means strlen returns a number that is too small (with a probability of 1 - (255/256)^20 which is approximately 7.5%). Rather than call strlen you should just pass in the size as a constant. I believe that if you are just encoding a sha1 hash, the length will always be 20:
char *base64output = base64(result, 20);
There is probably a better way to get that length from an HMAC function or something (so that it updates automatically if you change the hashing algorithm), but I am, admittedly, not very familiar with the hashing functions you're using.

Resources