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;
}
Related
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 */
}
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;
}
This is a follow up question from this one:
OpenSSL EVP_DecryptFinal_ex returns "wrong final block length" error when decrypting a file
I am trying to decrypt a file. At first I was reading it as ASCII file instead of binary. Having this fixed (I hope) and reading it as a binary I always get the an "bad decrypt" error:
15208:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:crypto\evp\evp_enc.c:570:
Here is a sample for how I am encrypting and decrypting:
Encryption:
Cipher cipher;
ifstream f("d:/test.YML");
ofstream out("d:/temp.YML");
byte key[KEY_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2};
byte iv[BLOCK_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
secure_string line;
secure_string temp;
while (getline(f, line)) {
cipher.Encrypt(key, iv, line, temp);
out << temp << endl;
}
Decryption:
Cipher cipher;
ifstream f("d:/temp.YML", ifstream::binary);
ofstream out("d:/tempDecrypt.YML");
byte key[KEY_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2};
byte iv[BLOCK_SIZE] = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
secure_string temp;
vector<char> buffer(1024, 0);
while (!f.eof()) {
f.read(buffer.data(), buffer.size());
streamsize dataSize = f.gcount();
secure_string chunk = { buffer.begin(), buffer.begin() + dataSize };
cipher.Decrypt(key, iv, chunk, temp);
}
Now I am not sure where start with this investigation:
Is there an encryption problem ? The encrypted file is generated, I am not seeing anything wrong with it.
Is there a problem with how I am reading chunks of file and decrypt them ? Again I don't see the issue here.(the error is on EVP_DecryptFinal_ex)
I also heard there could be a problem with padding. I am not doing anything related to padding, so I am not sure if this is an issue.
I am using same version of OpenSsl, on Windows, I have 2 Visual Studio projects, so there shouldn,t be an issue with imcompatible OpenSsl libraries.
If someone has any pointers pleaase let me know. I never worked with encryption before so some things are hard to understand.
PS: I haven't included the Encrypt and Decrypt methods, they are the same as on the Openssl Wiki website, let me know if I should.
There are a number of issues in your code... to name a few:
ofstream out("d:/temp.YML"); should be opened in binary mode.
out << temp << endl; will damage binary (encrypted) data by adding newlines unnecessarily.
Output buffer should contain enough space to fit (input buffer + block_size).
Encryption/decryption in chunks must follow the update/final pattern. You can't encrypt/decrypt chunks independently.
The IV should be random and should be stored with the ciphertext.
Have a look at the following sample application, which works:
#include <cstdint>
#include <fstream>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <string.h>
#include <stdio.h>
static const size_t KEY_SIZE = 256 / 8, BLOCK_SIZE = 128 / 8;
class AESBase {
protected:
const uint8_t *key, *iv;
EVP_CIPHER_CTX *ctx;
AESBase(const uint8_t *key, const uint8_t *iv) : key(key), iv(iv) {
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
}
~AESBase() {
EVP_CIPHER_CTX_free(ctx);
}
static void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
};
class Encrypt : AESBase {
public:
Encrypt(const uint8_t *key, const uint8_t *iv) : AESBase(key, iv) {
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
int update(const char *plaintext, int plaintext_len, char *ciphertext) {
int len;
if (1 != EVP_EncryptUpdate(ctx, (uint8_t*)ciphertext, &len, (const uint8_t*)plaintext, plaintext_len))
handleErrors();
return len;
}
int final(char *ciphertext) {
int len;
if (1 != EVP_EncryptFinal_ex(ctx, (uint8_t*)ciphertext, &len))
handleErrors();
return len;
}
};
class Decrypt : AESBase {
public:
Decrypt(const uint8_t *key, const uint8_t *iv) : AESBase(key, iv) {
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv))
handleErrors();
}
int update(const char *ciphertext, int ciphertext_len, char *plaintext) {
int len;
if (1 != EVP_DecryptUpdate(ctx, (uint8_t*)plaintext, &len, (const uint8_t*)ciphertext, ciphertext_len))
handleErrors();
return len;
}
int final(char *plaintext) {
int len;
if (1 != EVP_DecryptFinal_ex(ctx, (uint8_t*)plaintext, &len))
handleErrors();
return len;
}
};
void test_encrypt(const uint8_t *key, const char* in, const char* out) {
std::ifstream fin(in, std::ios_base::binary);
std::ofstream fout(out, std::ios_base::binary);
uint8_t iv[BLOCK_SIZE];
RAND_bytes(iv, sizeof(iv));
char buf[1024], temp[sizeof(buf) + BLOCK_SIZE];
Encrypt aes(key, iv);
fout.write((char*)iv, sizeof(iv));
while (fin) {
fin.read(buf, sizeof(buf));
int len = (int)fin.gcount();
if (len <= 0)
break;
len = aes.update(buf, len, temp);
fout.write(temp, len);
}
int len = aes.final(temp);
fout.write(temp, len);
}
void test_decrypt(const uint8_t *key, const char* in, const char* out) {
std::ifstream fin(in, std::ios_base::binary);
std::ofstream fout(out, std::ios_base::binary);
uint8_t iv[BLOCK_SIZE];
fin.read((char*)iv, sizeof(iv));
char buf[1024], temp[sizeof(buf) + BLOCK_SIZE];
Decrypt aes(key, iv);
while (fin) {
fin.read(buf, sizeof(buf));
int len = (int)fin.gcount();
if (len <= 0)
break;
len = aes.update(buf, len, temp);
fout.write(temp, len);
}
int len = aes.final(temp);
fout.write(temp, len);
}
int main()
{
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
uint8_t key[KEY_SIZE] = { 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2 };
test_encrypt(key, "main.cpp", "main.cpp.enc");
test_decrypt(key, "main.cpp.enc", "main.cpp.txt");
}
I am new with Crypto++. I want to using Crypto++ library to encrypt/decrypt a large byte array in C++. The data can be anything, so asume its binary format.
First, I tried with "byte array" (char * or char[]).
byte PlainText[] = {
'H','e','l','l','o',' ',
'W','o','r','l','d',
0x0,0x0,0x0,0x0,0x0
};
byte key[ AES::DEFAULT_KEYLENGTH ];
::memset( key, 0x01, AES::DEFAULT_KEYLENGTH );
// Encrypt
ECB_Mode< AES >::Encryption Encryptor( key, sizeof(key) );
byte cbCipherText[AES::BLOCKSIZE];
Encryptor.ProcessData( cbCipherText, PlainText, sizeof(PlainText) );
We use ProcessData() to encrypt the plain text, since it allows us to receive the result in a single line of code. Next, we enter a DMZ, and then decrypt the cipher text.
// Decrypt
ECB_Mode< AES >::Decryption Decryptor( key, sizeof(key) );
byte cbRecoveredText[AES::BLOCKSIZE];
Decryptor.ProcessData( cbRecoveredText, cbCipherText, sizeof(cbCipherText) );
The code above work perfect with small data (16KB). But it doesn't work with large data because "is not multiple of block size". Then, I think about using StreamTransformationFilter, which can automatic do the padding job for me. So I tried to encrypt and decrypt a std::string with encryptString() and decryptString() like below:
string encryptString(string plain, byte key[], int sizeKey, byte iv[], int sizeIV){
string cipher;
try{
CBC_Mode< AES >::Encryption e;
e.SetKeyWithIV(key, sizeKey, iv, sizeIV);
// The StreamTransformationFilter removes
// padding as required.
StringSource s(plain, true,
new StreamTransformationFilter(e,
new StringSink(cipher)
) // StreamTransformationFilter
); // StringSource
#if 0
StreamTransformationFilter filter(e);
filter.Put((const byte*)plain.data(), plain.size());
filter.MessageEnd();
const size_t ret = filter.MaxRetrievable();
cipher.resize(ret);
filter.Get((byte*)cipher.data(), cipher.size());
#endif
return cipher;
}
catch (const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
return NULL;
}
}
string decryptString(string cipher, byte key[], int sizeKey, byte iv[], int sizeIV){
string reco;
try{
CBC_Mode< AES >::Decryption d;
d.SetKeyWithIV(key, sizeKey, iv, sizeIV);
StringSource s(cipher, true,
new StreamTransformationFilter(d,
new StringSink(reco)
) // StreamTransformationFilter
); // StringSource
#if 0
StreamTransformationFilter filter(e);
filter.Put((const byte*)plain.data(), plain.size());
filter.MessageEnd();
const size_t ret = filter.MaxRetrievable();
cipher.resize(ret);
filter.Get((byte*)cipher.data(), cipher.size());
#endif
return reco;
}
catch (const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
return reco;
}
}
They are worked for large text file too. But, wait, my goal is encrypt/decrypt ANY byte array. And sometime they aren't string.
So I think about wrap the above two function to work with char *.
//wrap encryptString()
char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV){
string cipher = encryptString(plainText, key, sizeKey, iv, sizeIV);
FileUtil::writeFile("ss1.txt", cipher, cipher.length());
long len = cipher.size() + 1;
char * writable = new char[len];
std::copy(cipher.begin(), cipher.end(), writable);
writable[len] = '\0';
// don't forget to free the string after finished using it
//delete[] writable;
return writable;
}
//wrap decryptString()
char* decrypt(char * cipher, byte key[], int sizeKey, byte iv[], int sizeIV){
long len = strlen(cipher);
string recovered = decryptString(cipher, key, sizeKey, iv, sizeIV);
char * writable = new char[recovered.size() + 1];
std::copy(recovered.begin(), recovered.end(), writable);
writable[recovered.size()] = '\0'; // don't forget the terminating 0
// don't forget to free the string after finished using it
//delete[] writable;
return writable;
}
The result is:
When I read 1MB of text to encrypt() function, write the encrypted string "cipher" to "ss1.txt", its 1MB too. But to "writable", its only a part of "cipher" (about 1KB), and decrypted result is a part of original text too. Seem like '\0' was met somewhere and its terminated my char array?
I feel like going around now. Is there a way to using Crypto++ with (any) large byte (binary) array?
Additionally, I want to avoid using FileSource (Crypto++), because it doesn't allow me to save the encrypted value to variable.
I've tried to make a program which will be encrypt strings by AES encryption. After looking at stackoverflow and many other forums I end up with this. But there are some problems with the code:
1.Sometimes encryption works sometimes not(for 20 tries, 2 failed). How to fix it? It's related to ivec or maybe textLength?
2.After encryption and decryption I have only 16 first characters of my primary
string.After this I have some random characters. It is possible to decrypt all my string or I have to cut to 16 characters pieces?
3.I need to fuse some chars so I made this:
char ivec[16];
for(int i=0;i<16;i++)
{
ivec[i]=iveccreate[i];
}
But after all char ivec[16] have 55 characters. Any idea why?
4.After function AES_cbc_encrypt my ivec changed to some totally diffrent char. Is there any way to stop this(I want to reduce size of the code)?
I will be very greatful for the answers to the 1-4 questions.
MKAROL
PS:I come from Poland so my English is not so good. Sorry.
Valiable code:
#include <string.h>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <openssl/aes.h>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
using namespace std;
string AESencode(string Text,string Key);
void AESdecode(string in,string Key);
char *encode(unsigned char *input, int length);
char *decode(unsigned char *input,int lenght);
void main
{
string out=AESencode("String,which I want to encrypt.\0","encryptionkey");
AESdecode(out,"encryptionkey");
return 0;
}
string AESencode(string Text,string Key)
{
//Creating 16 random ive
srand((unsigned int) time(NULL));
unsigned char ive[16];
for(int i=0; i<16; i++){
ive[i] = (unsigned char) rand();
}
//I'm losing null by encode ive
char *iveccreate=encode(ive,16);
//Copying 16 first chars from iveccreate(16 random letters,numbers)
char ivec[16];
for(int i=0;i<16;i++)
{
ivec[i]=iveccreate[i];
}
//Saving ivec,because I need to fuse ivec with output later
//and after encode I lose orginal ivec
char* ivec1=decode((unsigned char*)iveccreate,strlen((const char*)iveccreate));
// Round up to AES_BLOCK_SIZE
size_t textLength = ((Text.length() / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;
//If necessary adding null to the Key(full 32 bytes)
if(Klucz.length() < 32){
Key.append(32 - Key.length(), '\0');
}
//Creating space for the output
unsigned char *aesoutput = new unsigned char[textLength];
//Create and set AESkey
AES_KEY *aesKey = new AES_KEY;
AES_set_encrypt_key((unsigned char*)Key.c_str(), 256, aesKey);
//Encrypting
AES_cbc_encrypt((unsigned char*)Text.c_str(), aesoutput, Text.length()+ 1, aesKey, (unsigned char*)ivec, AES_ENCRYPT);
//Fusing ivec with aesoutput
char wyjsciowy[strlen((const char*)Wyjscie)+16];
for(int i=0;i<16;i++){
fuse[i]=ivec1[i];
}
for(int i=0;i<strlen((const char*)Wyjscie);i++) {
fuse[i+16]=aesouput[i];
}
//Encode the fuse
char* out=encode((unsigned char*)wyjsciowy,strlen(wyjsciowy));
//Saving chars to string
string mychar((char*)out);
//Creating normal string from the base64 encode output
//String is 65 chars, new line, 65 chars
//so I'm looking for the number of not 65, ending chars of the string
int res=mychar.length()%65;
string allstr;
//Fuse strings without new line charater
for(int i=0;i<(mychar.length()-res);i+=65)
{
allstr+=mychar.substr(i,64);
}
//Fuse string with the ending string.If res==0 it will add nothing.
allstr+=mychar.substr((mychar.length()-res),res);
//Returnig string
return allstr;
}
//Base64 encode function
char *encode(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+1);
memcpy(buff, bptr->data, bptr->length);
buff[bptr->length] = 0;
BIO_free_all(b64);
return buff;
}
//Base64 decode function
char *decode(unsigned char *input, int length)
{
BIO *b64, *bmem;
char *buffer = (char *)malloc(length);
memset(buffer, 0, length);
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf(input, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
}
void AESdecode(string in,string Key)
{
//Decode the input string with Base64
char* dec=decode((unsigned char*)in.c_str(),in.length());
//Getting ivec
unsigned char ivec[16];
{
//Getting first 16 bytes from dec
unsigned char preivec[16];
for(int i=0;i<16; i++){
preivec[i] = dec[i];
}
//Encode these 16 bytes
char *ppiv=encode(preivec,16);
//Now we have 25 chars text
//And ivec is only fist 16
for(int i=0;i<25; i++){
ivec[i] = ppiv[i];
}
}
//Getting aesouput bytes
char data[strlen(dec)-16];
for(int i=16;i<(strlen(dec));i++){
data[i-16]=dec[i];
}
//If necessary adding null to the Key(full 32 bytes)
if(Key.length()< 32){
Key.append(32-Key.length(),'\0');
}
//Creating space for the output
unsigned char *output = new unsigned char[strlen(data)];
//Create and set new AESkey
AES_KEY *aesKey = new AES_KEY;
AES_set_decrypt_key((unsigned char*)Key.c_str(), 256, aesKey);
// key length is in bits, so 32 * 8 = 256
//Deccrypting
AES_cbc_encrypt((unsigned char*)data, output, strlen(data), aesKey,ivec, AES_DECRYPT);
//And there should be full primary string
cout<<"OUTPUT: "<<output<<endl;
}
AES keys are fixed length byte arrays, not variable length strings. When you call AES_set_decrypt_key(), you give it a 13 character long string, with an added null byte, so 14 bytes that we know of. Then the function will use the (32-14) -> 18 remaining bytes for its key. What is the content of these 18 bytes is mostly the result of luck
I suspect that this is your problem.