openssl aes decryption in c - c

I am trying to create an openssl aes encryption/decryption using php and c. I am able to encrypt text using php and openssl and this will output the encrypted string in a base64 string. I am trying to pass this base64 encoded string to a c program to decode it using openssl in c.
int decrypt(unsigned char *ciphertext,
int ciphertext_len,
unsigned char *key,
unsigned char *iv,
unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors();
plaintext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
Is there any method to decrypt the base64 string using openssl in c ? i am able to decrypt it using the command line something like
openssl enc -aes-256-cbc -d -in file.encrypted -nosalt -nopad -K 31323334353637383132333435363738 -iv 31323334353637383132333435363738
Thanks in advance

You are directly working on base64 encoded data.
First you need to base64 decode the data to get the actual encrypted data. Then you will apply AES decryption to get the decrypted data
BIO *b64, *bmem;
buffer = (char *)malloc(datalength);
b64 = BIO_new(BIO_f_base64());
if(b64 == NULL)
{
return NULL;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf(input, length);
if(bmem == NULL)
{
return NULL;
}
bmem = BIO_push(b64, bmem);
if(bmem == NULL)
{
return NULL;
}
ret = BIO_read(bmem, buffer, length);
if(ret == 0)
{
return NULL;
}
BIO_free_all(bmem);
return buffer;

Related

C, OpenSSL and AES 256 CTR, then mkfs

I am encrypting XFS filesystem using OpenSSL 1.0.2 (cannot update) and AES-256 in ctr mode (using sector number as a IV). I am encrypting only blocks of 512B at one time.
At first I started with EVP_aes_256_ecb() ECB mode for testing and en/decrypt is working fine.
With same code I am also going for CTR (EVP_aes_256_ctr()):
encrypt(...) {
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (EVP_EncryptInit_ex(ctx, evp_cipher, NULL, key, iv) != 1)
handleErrors();
if (EVP_CIPHER_CTX_set_padding(ctx, 0) != 1)
handleErrors();
if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len) != 1)
handleErrors();
ciphertext_len = len;
if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1)
handleErrors();
ciphertext_len += len;
if (tag && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1)
handleErrors();
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int decrypt(...) {
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (EVP_DecryptInit_ex(ctx, evp_cipher, NULL, key, iv) != 1)
handleErrors();
if (EVP_CIPHER_CTX_set_padding(ctx, 0) != 1)
handleErrors();
if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len) != 1)
handleErrors();
plaintext_len = len;
if (tag && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
handleErrors();
if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) {
if (tag) {
printf("Tag verify failed.\n");
return 0;
}
handleErrors();
}
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
Only in this case after mkfs.xfs I am getting:
specified blocksize 4096 is less than device physical sector size 4194304
switching to logical sector size 512
meta-data=/dev/sdb isize=512 agcount=4, agsize=2097152 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=8388608, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=4096, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
bad magic number
bad magic number
Metadata corruption detected at xfs_sb block 0x0/0x200
libxfs_writebufr: write verifer failed on xfs_sb bno 0x0/0x200
releasing dirty buffer (bulk) to free list!
This isn't very nice. Is there any problem with my approach?
Although I haven't found a reason, I inspired my code by this: https://raw.githubusercontent.com/saju/misc/master/misc/openssl_aes.c and it is working now. Code in this link seems to be compatible with OpenSSL 1.0.2.

Openssl EVP API fails to decrypt ciphertext when it is read from file (AES 128 ecb)

i am trying to create a simple application that encrypts and decrypts a small file, < 10 bytes. I am using OpenSSL API of C (AES-128 ecb encryption) and i am encountering a strange "bug" when i encrypt a string and save it to a file.
unsigned char buffer[256];
unsigned char rcv[256];
char my_string[]={"123456"};
int bil = aes_encrypt(my_string, strlen(my_string), "1", NULL, buffer);
FILE* fp =fopen("encrypted_file","w");
write(fileno(fp),buffer,bil);
fclose(fp);
aes_decrypt(buffer, bil, "1", NULL, rec);
printf("%s\n",rec); /* Correct: Prints 123456 */
The problem here is that if i read the ciphertext from the file, although it is exactly the one i had previously saved, it does not seem to be decrypted correctly.
FILE* fp =fopen("encrypted_file","r");
int bil = read(fileno(fp),buffer,256); /* The buffer contains the exact cipher that was created by the aes_encrypt in the first place */
fclose(fp);
int y = aes_decrypt(buffer, bil, "1", NULL, rec);
printf("%s\n",rec); /* Emptry string */
The encryption and decryption functions are shown bellow:
Encryption:
int
aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext){
EVP_CIPHER_CTX* ctx;
int len;
int ciphertext_len;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv);
EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len);
ciphertext_len = len;
EVP_EncryptFinal_ex(ctx, ciphertext + len, &len);
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}`
Decryption:
int
aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
unsigned char *iv, unsigned char *plaintext){
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, iv);
EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
plaintext_len = len;
EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
plaintext[plaintext_len] = '\0';
return plaintext_len;
}

How to use bcrypt in OpenSSL?

I want to use bcrypt encryption for storing passwords and I know OpenSSL implements Blowfish Cipher (which I'm assuming is the same thing).
I made some adaptations from the code shown in this page https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption
and came up with this:
int OpenSSLEncrypt(
unsigned char* plaintext,
int plaintext_len,
unsigned char* key,
unsigned char* iv,
unsigned char* ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
if (!(ctx = EVP_CIPHER_CTX_new())) OpenSSLHandleErrors();
if (1 != EVP_EncryptInit_ex(ctx, EVP_bf_cbc(), 0, key, 0))
OpenSSLHandleErrors();
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
OpenSSLHandleErrors();
ciphertext_len = len;
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
OpenSSLHandleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int OpenSSLDecrypt(
unsigned char* ciphertext,
int ciphertext_len,
unsigned char* key,
unsigned char* iv,
unsigned char* plaintext)
{
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if (!(ctx = EVP_CIPHER_CTX_new())) OpenSSLHandleErrors();
if (1 != EVP_DecryptInit_ex(ctx, EVP_bf_cbc(), NULL, key, 0))
OpenSSLHandleErrors();
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
OpenSSLHandleErrors();
plaintext_len = len;
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
OpenSSLHandleErrors();
plaintext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
But the length of the cipher that I get from OpenSSLEncrypt(...) depends on the length of the plaintext input parameter, which is not what I was expecting. I was expecting the output to be 64 bytes long no matter the length of the password.
Also, I don't know if EVP_EncryptInit_ex needs an iv (initialization vector) or not for EVP_bf_cbc, and I found no documentation that could help me with this.
As it was pointed out in the comments, I was wrong in assuming Blowfish and BCrypt are the same thing, just because I read somewhere B stands for Blowfish.
I ended up following the suggestion from Cinder Biscuits of using the OpenBSD implementation of bcrypt, avaiable at
https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/crypt/bcrypt.c

Encrypt using OpenSSL API in C [duplicate]

This question already has answers here:
Simple AES encryption decryption with openssl library in C
(4 answers)
Closed 7 years ago.
Its not duplicate since I was not asking how to encrypt, but I was asking whats wrong in my encryption. Dont like this Question you are free to delete it. I dont care.
I am trying to encrypt one simple hello text file.
Here is my code to encrypt the data.
int encrypt(EVP_CIPHER_CTX *ctx, FILE *ifp,FILE *ofp)
{
int bytes_read, bytes_written, enc_bytes,tlen;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char encdata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
while (1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp);
if (EVP_EncryptUpdate (ctx, encdata, &enc_bytes, indata, bytes_read) != 1)
{
printf ("error in encrypt update\n");
return -1;
}
printf ("INPUT\n");
print_memory(indata, bytes_read);
if (EVP_EncryptFinal (ctx, encdata + enc_bytes, &tlen) != 1)
{
printf ("error in encrypt final\n");
return -1;
}
printf ("OUTPUT\n");
print_memory(encdata,enc_bytes+tlen);
bytes_written = fwrite(encdata, 1,enc_bytes + tlen, ofp);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
Here is key and ivec, I have used for initialization
unsigned char ckey[] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF};
unsigned char ivec[] = {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF};
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init (&ctx);
EVP_EncryptInit (&ctx, EVP_bf_cbc (), ckey, ivec);
Here is the output encrypted data in hex 24 47 50 58 93 0B 04 9C D5 54 65 93 D1 6B AD 5A
but when i try to decode the data using openSSL cmd
I get following error
anshul:~/> openssl aes-128-cbc -d -in otext -K 000102030405060708090A0B0C0D0E0F -iv 000102030405060708090A0B0C0D0E0F -nosalt
bad decrypt
3075450556:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
This is the same error I get if I use wrong ivec or key.
So I do have wild guess that there is something different in c program key or ivec and openssl cmd key or ivek
I am trying to encrypt one simple hello text file...
I took code from http://openssl.org/docs/crypto/EVP_EncryptInit.html#EXAMPLES...
Here's the example from the OpenSSL wiki on EVP Authenticated Encryption and Decryption. It uses GCM mode because you often want/need confidentiality and authenticity assurances, and not just confidentiality.
OpenSSL routines work on byte strings in memory. So you will have to read the file and present a byte string to the OpenSSL functions.
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
int aad_len, unsigned char *key, unsigned char *iv,
unsigned char *ciphertext, unsigned char *tag)
{
EVP_CIPHER_CTX *ctx;
int len, ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the encryption operation. */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
handleErrors();
/* Set IV length if default 12 bytes (96 bits) is not appropriate */
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
handleErrors();
/* Initialise key and IV */
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
/* Provide any AAD data. This can be called zero or more times as
* required
*/
if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
handleErrors();
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Normally ciphertext bytes may be written at
* this stage, but this does not occur in GCM mode
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
/* Get the tag */
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
handleErrors();
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
And the decryption routine:
int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
unsigned char *plaintext)
{
EVP_CIPHER_CTX *ctx;
int len, plaintext_len, ret;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the decryption operation. */
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
handleErrors();
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
handleErrors();
/* Initialise key and IV */
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
/* Provide any AAD data. This can be called zero or more times as
* required
*/
if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
handleErrors();
/* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary
*/
if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
/* Set expected tag value. Works in OpenSSL 1.0.1d and later */
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
handleErrors();
/* Finalise the decryption. A positive return value indicates success,
* anything else is a failure - the plaintext is not trustworthy.
*/
ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
if(ret > 0)
{
/* Success */
plaintext_len += len;
return plaintext_len;
}
else
{
/* Verify failed */
return -1;
}
}
anshul:~/> openssl aes-128-cbc -d -in ...
For GCM mode, this won't work. GCM has not been cut-in for the OpenSSL encrypt and decrypt subcommands. See AES-GCM failing from Command Line Interface on the OpenSSL mailing list.
And in case you are wondering, that's not a valid reason to use a different mode, like CBC or OFB. Use GCM mode.

Segmentation fault in EVP_CIPHER_CTX_new() when using OpenSSL in C

I am a total beginner with the OpenSSL Library in C but was working on a code to encrypt using the libraries while taking a pass phrase as input and generating the salt,IV and key from the pass phrase. This is what I have tried till now:
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *ciphertext)
{
char *passphrase;
printf("\nEnter a Pass Phrase:");
scanf("%s",passphrase);
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
const EVP_MD *dgst = NULL;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
const char *salt;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) //This line causes the error
handleErrors();
cipher = EVP_get_cipherbyname("aes-256-cbc");
if(!cipher) { fprintf(stderr, "no such cipher\n"); return -1; }
dgst=EVP_get_digestbyname("md5");
if(!dgst) { fprintf(stderr, "no such digest\n"); return -1; }
if(!EVP_BytesToKey(cipher, dgst, salt, (unsigned char *) passphrase, strlen(passphrase), 1, key, iv))
{
fprintf(stderr, "EVP_BytesToKey failed\n");
return -1;
}
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
EVP_cleanup();
ERR_free_strings();
return ciphertext_len;
}
I tried this out but kept getting a segmentation fault. I tried to debug and found out that the EVP_CIPHER_CTX_new() was the one cussing it. I am at my wits end right now trying to debug it and could really appreciate some help.
Thanks in advance.
This is incorrect:
char *passphrase;
printf("\nEnter a Pass Phrase:");
scanf("%s",passphrase);
char *pasphrase is just a pointer point to unknown location.
Change this to:
char passphrase[2048];
printf("\nEnter a Pass Phrase:");
scanf("%s", passphrase);

Resources