Crypto++ AES encryption with pbkdf2 - c++

I would like to encrypt text using pbkdf2, but each time I execute my code the derivekey output is different. How can I fix the output?
The code is for making key to utf8 bytes, making sha256 hash from the utf8 bytes, and making pbkdf2 key and iv.
My code is following:
#include <stdio.h>
#include <string.h>
#include "modes.h"
#include "aes.h"
#include "filters.h"
#include "sha.h"
#include "base64.h"
#include "pwdbased.h"
#include "misc.h"
using namespace std;
int main()
{
char text[] = "For test";
size_t targetSize = sizeof(text);
char key[] = "asdlkj32"
size_t keySize = sizeof(key);
// convert key to utf8
string baseKey(key);
int size = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, baseKey.c_str(), baseKey.length(), nullptr, 0);
wstring utf16(size, '\0');
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, baseKey.c_str(), baseKey.length(), &utf16[0], size);
int utf8Size = WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), utf16.length(), nullptr, 0, nullptr, nullptr);
string utf8(utf8Size, '\0');
WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), utf16.length(), &utf8[0], utf8Size, nullptr, nullptr);
// Make sha256 hash
unsigned char shaChar[1000];
CryptoPP::SHA256 hash;
auto temp = (unsigned char*)utf8.c_str();
hash.CalculateDigest(shaChar, (unsigned char*)utf8.c_str(), utf8Size);
string sha(reinterpret_cast<const char*>(shaChar));
sha = sha.erase(sha.find_last_not_of(-52) + 1);
CryptoPP::byte* test = (unsigned char*)reinterpret_cast<const unsigned char*>(sha.c_str());
// Make pbkdf2 key and iv
CryptoPP::byte derive[pbkdf2KeySize + ivSize]; /*deriveKey output buffer*/
size_t derivesize = { sizeof(derive) };
const CryptoPP::byte* ppkey = reinterpret_cast<unsigned char*>(key);
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256> pbkdf;
size_t temp1 = pbkdf.DeriveKey(derive, derivesize, 0, ppkey, keySize, test, sha.length(), 1000, 0.0f); /* Each time the output of this function is different */
}

Related

C++ OPENSSL - How to convert OPENSSL output to a readable text and store it to a variable (if possible)

I have the working code below using OPENSSL AES 256 CBC to encrypt/decrypt.
It is working but I am missing something really important that is to CONVERT the Encryption result to readable text and STORE it to a STRING variable if possible (for later use).
For example, I need to see something like this: UkV8ecEWh+b1Dz0ZdwMzFVFieCI5Ps3fxYrfqAoPmOY=
Trying hard to find how to do that and what format OPENSSL is throwing out from Encryption process. (binary format ??) See image attached.
ps. Don't worry about the hashes below. They are not in production.
Thanks in Advance!!
Here is my code so far:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
using namespace std;
// HEX PRINT
static void hex_print(const void* pv, size_t len)
{
const unsigned char* p = (const unsigned char*)pv;
if (NULL == pv)
printf("NULL");
else
{
size_t i = 0;
for (; i < len; ++i)
printf("%02X ", *p++);
}
printf("\n");
}
// Starting MAIN function
int main()
{
int keylength = 256;
unsigned char aes_key[] = "1Tb2lYkqstqbh9lPAbeWpQOs3seHk6cX";
// Message we want to encrypt
unsigned char aes_input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz";
size_t inputslength = sizeof(aes_input)-1; // -1 because we don't want to encrypt the \0 character
// initialization vector IV - same for Encryption and Decryption
unsigned char iv_enc[] = "JxebB512Gl3brfx4" ;
unsigned char iv_dec[] = "JxebB512Gl3brfx4" ;
// buffers for encryption and decryption
const size_t encslength = inputslength ;
unsigned char enc_out[257];
unsigned char dec_out[257];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
//Encryption START
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
//Decryption START
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
// Printing Results
printf("original: \t");
hex_print(aes_input, sizeof(aes_input));
cout << aes_input << endl;
printf("encrypted: \t");
hex_print(enc_out, sizeof(enc_out));
cout << enc_out << endl;
printf("decrypt: \t");
hex_print(dec_out, sizeof(dec_out));
cout << dec_out << endl;
return 0;
}
Image of the Process
All Right. Thanks for the tips #RemyLebeau and #PaulSanders !!
I could resolve the issue using another tip from here -->
Base64 C++
Working REALLY fine now!!
Thanks Much!!
Here is the code for "encode" and "decode" Base64, just in case someone wants to do the same. Very usefull!!
typedef unsigned char uchar;
static const string b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static string base64_encode(const string &in) {
string out;
int val=0, valb=-6;
for (uchar c : in) {
val = (val<<8) + c;
valb += 8;
while (valb>=0) {
out.push_back(b[(val>>valb)&0x3F]);
valb-=6;
}
}
if (valb>-6) out.push_back(b[((val<<8)>>(valb+8))&0x3F]);
while (out.size()%4) out.push_back('=');
return out;
}
static string base64_decode(const string &in) {
string out;
vector<int> T(256,-1);
for (int i=0; i<64; i++) T[b[i]] = i;
int val=0, valb=-8;
for (uchar c : in) {
if (T[c] == -1) break;
val = (val<<6) + T[c];
valb += 6;
if (valb>=0) {
out.push_back(char((val>>valb)&0xFF));
valb-=8;
}
}
return out;
}

How to solve this 'EVP_DecryptFinal_ex:wrong final block length' error?

I would like to encrypt the architecture of a neural network, so I could protect the knowledge property of my research.
An example of one of these files, have similar structure as this example.
The code compiles, but I get a runtime error that I don't know how to solve. The error message is digital envelope routines:EVP_DecryptFinal_ex:wrong final block length.
Im using OpenSSL version 1.1.1a 20 Nov 2018
Most relevant includes
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/err.h>
Most relevant code for ENCRYPTION
Open and read file to encrypt
std::ifstream in_file(file_name, std::ios::binary);
in_file.seekg(0, in_file.end);
long size = in_file.tellg();
in_file.seekg(0, in_file.beg);
std::vector<unsigned char> binarydata(size);
in_file.read((char*)binarydata.data(), size);
in_file.close();
Encrypt
EVP_CIPHER_CTX *en;
en = EVP_CIPHER_CTX_new();
unsigned char *salt = (unsigned char *)"12345678";
unsigned char *key_data = (unsigned char *)"super_secret_key_with_32_charact";
int k_len = strlen((const char*)key_data);
int nrounds = 5;
unsigned char key[32], iv[32];
EVP_BytesToKey(
EVP_aes_256_cbc(), EVP_sha1(),
salt,
key_data, k_len, nrounds,
key, iv);
EVP_CIPHER_CTX_init(en);
// I don't know why, but all examples that I have founded,
// calls this function twice, so I am doing it too.
EVP_EncryptInit_ex(en, EVP_aes_256_cbc(), NULL, key, iv);
EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL);
int c_len = size + AES_BLOCK_SIZE, f_len = 0;
std::vector<unsigned char> ciphertext(c_len);
EVP_EncryptUpdate(en, ciphertext.data(), &c_len, binarydata.data(), size);
EVP_EncryptFinal_ex(en, ciphertext.data()+c_len, &f_len);
EVP_CIPHER_CTX_free(en)
Write ciphertext to a new file
std::ofstream out_file(output_file, std::ios::binary);
out_file.write((char*)ciphertext.data(), ciphertext.size() *
sizeof(char));
out_file.close();
Most relevant code for DECRYPTION
Open and read encrypted file
std::ifstream in_file(file_name, std::ios::binary);
in_file.seekg(0, in_file.end);
int size = in_file.tellg();
in_file.seekg(0, in_file.beg);
std::vector<unsigned char> ciphertext(size);
in_file.read((char*)ciphertext.data(), size);
in_file.close();
Decrypt
EVP_CIPHER_CTX *de;
de = EVP_CIPHER_CTX_new();
unsigned char *salt = (unsigned char *)"12345";
unsigned char *key_data = (unsigned char *)"super_secret_key_with_32_charact";
int k_len = strlen((const char*)key_data);
int nrounds = 5;
unsigned char key[32], iv[32];
EVP_BytesToKey(
EVP_aes_256_cbc(), EVP_sha1(),
salt,
key_data, k_len, nrounds,
key, iv)
EVP_CIPHER_CTX_init(de);
// I don't know why, but all examples that I have founded,
// calls this function twice, so I am doing it too.
EVP_DecryptInit_ex(de, EVP_aes_256_cbc(), NULL, key, iv);
EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL);
int p_len = size, f_len = 0;
std::vector<unsigned char> plaintext(p_len);
EVP_DecryptUpdate(de, plaintext.data(), &p_len, ciphertext.data(), size);
EVP_DecryptFinal_ex(de, plaintext.data()+p_len, &f_len);
EVP_CIPHER_CTX_free(de);
return plaintext;
I would like to have some help on how to solve this problem.
I don't know if this is still an issue.
I had the exact same issue and I solved the problem with adapting the length of the ciphertext after encryption:
EVP_EncryptFinal_ex(en, ciphertext.data()+c_len, &f_len);
ciphertext.erase(ciphertext.begin() + c_len + f_len, ciphertext.end());
With this, the length of ciphertext should be n * AES_BLOCK_SIZE.

Invalid PKCS #7 block padding when using Crypto++

We are using cryptopp library. We are using the below coding. Encryption is working file without any issue and we are able to get the cipher text. But getting an error while decrypting as "Block padding found". What could be the issue...?
#include <iostream>
#include <string>
using namespace std;
#include "cryptlib.h"
#include "filters.h"
#include "files.h"
#include "modes.h"
#include "hex.h"
#include "aes.h"
#include "osrng.h"
using namespace CryptoPP;
using CryptoPP::AutoSeededRandomPool;
class cspl_crypto{
public:
cspl_crypto();
byte* generate_block(int size);
char* encrypt_rijndael(byte[], byte[], int, char*, int);
char* decrypt_rijndael(byte[], byte[], int, char*, int);
string readFile();
void writeFile(string);
};
cspl_crypto::cspl_crypto()
{
}
int main(int argc, char* argv[])
{
vector<byte> plain;
cspl_crypto ccrypto;
AutoSeededRandomPool prng;
byte key[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));
byte iv[AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
Converting string to char *
string str("testing"); //ccrypto.readFile()
char plainArray[str.size()];
strcpy(plainArray, str.c_str());
char* cipher = ccrypto.encrypt_rijndael(key, iv, sizeof(key), plainArray,
sizeof(plainArray));
//char cipherCharArray[cipherText.size()];
// strcpy(cipherCharArray, cipherText.c_str());
char* recover = ccrypto.decrypt_rijndael(key, iv, sizeof(key), cipher,
sizeof(cipher));
// cout << "Recovered text: " << recoverText << endl;
return 0;
}
Encryption Block:
char* cspl_crypto::encrypt_rijndael(byte key[], byte iv[], int keysize, char
plainText[], int plainTextSize){
vector<byte> cipher;
std::vector<byte> plain(plainText, plainText + plainTextSize);
CBC_Mode<AES>::Encryption enc;
enc.SetKeyWithIV(key, keysize, iv, keysize);
// Make room for padding
cipher.resize(plain.size()+AES::BLOCKSIZE);
ArraySink cs(&cipher[0], cipher.size());
ArraySource(plain.data(), plain.size(), true,
new StreamTransformationFilter(enc, new Redirector(cs)));
// Set cipher text length now that its known
cipher.resize(cs.TotalPutLength());
char returnValue[cipher.size()];
copy(cipher.begin(), cipher.end(), returnValue);
return returnValue;
}
Decyption Block:
char* cspl_crypto::decrypt_rijndael(byte key[], byte iv[], int keysize, char
cipher[], int size ){
std::vector<byte> v(cipher, cipher + size);
vector<byte> recover;
CBC_Mode<AES>::Decryption dec;
dec.SetKeyWithIV(key, keysize, iv, keysize);
// Recovered text will be less than cipher text
recover.resize(v.size());
ArraySink rs(&recover[0], recover.size());
ArraySource(v.data(), v.size(), true,
new StreamTransformationFilter(dec, new Redirector(rs)));
// Set recovered text length now that its known
recover.resize(rs.TotalPutLength());
char returnValue[recover.size()];
copy(recover.begin(), recover.end(), returnValue);
return returnValue;
}
Library:
string cspl_crypto::readFile(){
string line;
string returnValue = "";
ifstream myfile ("N07.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
returnValue += line + '\n';
}
myfile.close();
}
else returnValue = "Unable to open file";
return returnValue;
}

AES128 in libgcrypt not encrypting

I've been trying to the libgcrypt for a small cryptography project of mine, but I can't seem to be able to implement the en/decryption correctly. The following the class and the usage of it.
#include <iostream>
#include <string>
#include <cstdlib>
#include <gcrypt.h>
#include "aes.h"
#define GCRY_CIPHER GCRY_CIPHER_AES128
#define GCRY_MODE GCRY_CIPHER_MODE_ECB
using namespace std;
aes::aes(string a) {
key = a;
keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
gcry_cipher_open(&handle, GCRY_CIPHER, GCRY_MODE, 0);
gcry_cipher_setkey(handle, key.c_str(), keyLength);
}
string aes::encrypt(string text) {
size_t textLength = text.size() + 1;
char * encBuffer = (char *)malloc(textLength);
gcry_cipher_encrypt(handle, encBuffer, textLength, text.c_str(), textLength);
string ret (encBuffer);
return ret;
}
string aes::decrypt(string text) {
size_t textLength = text.size() + 1;
char * decBuffer = (char * )malloc(textLength);
gcry_cipher_decrypt(handle, decBuffer, textLength, text.c_str(), textLength);
string ret (decBuffer);
return ret;
}
And I use it in a main function like so:
...
aes bb = aes("one test AES key");
string test = "Some Message";
string enc = bb.encrypt(test);
string dec = bb.decrypt(enc);
for (size_t index = 0; index<enc.size(); index++)
printf("%c", enc[index]);
printf("\n");
cout << dec << endl;
...
And the output is
BBBBBBBBBBBBB
�n�S[
The odd thing is, I made a test program with almost the exact same statements that works perfectly. It started falling apart when I tried to package it into a class. The following is the code for this program, if anyone wants to see it.
#include <cstdlib>
#include <iostream>
#include <string>
#include <gcrypt.h>
using namespace std;
#define GCRY_CIPHER GCRY_CIPHER_AES128 // Pick the cipher here
#define GCRY_MODE GCRY_CIPHER_MODE_ECB // Pick the cipher mode here
void aesTest(void)
{
gcry_cipher_hd_t handle;
size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
string txtBuffer ("123456789 abcdefghijklmnopqrstuvwzyz ABCDEFGHIJKLMNOPQRSTUVWZYZ");
size_t txtLength = txtBuffer.size() +1; // string plus termination
char * encBuffer = (char *)malloc(txtLength);
char * outBuffer = (char *)malloc(txtLength);
char * key = "one test AES key"; // 16 bytes
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
gcry_cipher_open(&handle, GCRY_CIPHER, GCRY_MODE, 0);
gcry_cipher_setkey(handle, key, keyLength);
gcry_cipher_encrypt(handle, encBuffer, txtLength, txtBuffer.c_str(), txtLength);
gcry_cipher_decrypt(handle, outBuffer, txtLength, encBuffer, txtLength);
size_t index;
printf("encBuffer = ");
for (index = 0; index<txtLength; index++)
printf("%c", encBuffer[index]);
printf("\n");
printf("outBuffer = %s\n", outBuffer);
gcry_cipher_close(handle);
free(encBuffer);
free(outBuffer);
}
int main() {
aesTest();
return 0;
}
When you use a std::string to capture the encrypted data, you are possibly losing some data due to the presence of '\0' in the encrypted string.
Try using std::vector<char> instead.
void aes::encrypt(string text, std::vector<char>& ret) {
size_t textLength = text.size() + 1;
ret.resize(textLength);
gcry_cipher_encrypt(handle, ret.data(), textLength, text.c_str(), textLength);
}
string aes::decrypt(std::vector<char> const& text) {
size_t textLength = text.size() + 1;
// Since you are in C++ land, use new and delete
// instead of malloc and free.
char * decBuffer = new char[textLength];
gcry_cipher_decrypt(handle, decBuffer, textLength, text.data(), textLength);
string ret (decBuffer);
delete [] decBuffer;
return ret;
}

c++ mcrypt error at mcrypt_generic

I have the following code:
[test.cpp]
#include <mcrypt.h>
#include <string>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
int main()
{
char algo[] = "rijndael-256";
char mode[] = "cbc";
char *block_buffer=(char*)"HELLO!! MY NAME IS: ";
cout<<"here"<<endl;
string s;
char key="1234-5678-9654-7512-7895-2543-12";
char iv[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};;
MCRYPT td = mcrypt_module_open(algo, NULL, mode, NULL);
if (td == MCRYPT_FAILED) { cout<<"error"<<endl;}
int keysize=32;
int r = mcrypt_generic_init(td, key, keysize, iv);
if (r<0)
{
cout<<"error2"<<endl;
mcrypt_perror(r);
return 1;
}
//while ( fread (&block_buffer, 1, 1, stdin) == 1 ) {
int j= mcrypt_generic (td, &block_buffer, sizeof(block_buffer));
if (j!=0){std::cout<<"error encrypting"<<std::endl;} // I HAVE ERROR HERE J==0
//how to print the encrypted string??
cout<<"buffer "<<block_buffer<<endl; //this is not the encriperd string. why?
mcrypt_generic_deinit(td);
mcrypt_module_close(td);
}
I am testing the code:
$: g++ test.cpp -o tst -lmcrypt
$: ./tst
WHERE SHOULT I ADD THE PKCS 7?
I have the following method:
std::string add_pkcs7_padding(std::string s, std::size_t n)
{
const std::size_t fill = n - (s.length() % n);
s.append(fill, static_cast<char>(fill));
return s;
}
std::string strip_pkcs7_padding(std::string s, std::size_t n)
{
const std::size_t pad = static_cast<unsigned char>(*s.rbegin());
return s.substr(0, s.length() - pad);
}
I din't know when should i run it and where in my code.
NEED SOME HELP. APPRECIATE A LOT!!
EDIT:
I have error at: mcrypt_generic (td, &block_buffer, sizeof(block_buffer)); The compiler prints
that the value j=0;
You should invoke mcrypt_generic() with a char*, not a char** as you do:
mcrypt_generic(td, block_buffer, sizeof(block_buffer));
^^^ ^^^^^^^^^^^^^^^^^^^^
ouch!
Also, the length is wrong, as sizeof(block_buffer) is just be the size of the pointer, not the string; if anything you need strlen(block_buffer).
But this is still going to be wrong in general because you need your message to be a multiple of the block size. Use the padding function:
std::string s = add_pkcs7_padding(block_buffer, mcrypt_enc_get_block_size(td));
std::vector<char> v(s.begin(), s.end()); // this will hold the encrypted data
mcrypt_generic(td, v.data(), v.size());
By the way, your plaintext should be declared like this:
const char * block_buffer = "HELLO!! MY NAME IS: ";
^^^^^ ^^^^
constness! no explicit cast!
But why so clumsy, it's better to just use a string:
std::string plaintext = "HELLO!! MY NAME IS: ";
I think you might benefit from picking up a good C++ book and familiarizing yourself with the basics of the language a bit - it's good to have a project to work on, but most of your problems aren't really related to encryption or mcrypt, but just general C++ programming.