Qt crypto++ aes encrypt/decrypt not decrypting properly - qt

I have the following code:
#define PRIVATE_KEY "729308A8E815F6A46EB3A8AE6D5463CA7B64A0E2E11BC26A68106FC7697E727E37011"
To Encrypt:
QString Encryption::AESEncrypt(const QString &data)
{
string plain = data.toStdString();
string ciphertext;
// Hex decode symmetric key:
HexDecoder decoder;
decoder.Put( (byte *)PRIVATE_KEY, 32*2 );
decoder.MessageEnd();
word64 size = decoder.MaxRetrievable();
char *decodedKey = new char[size];
decoder.Get((byte *)decodedKey, size);
// Generate Cipher, Key, and CBC
byte key[ AES::MAX_KEYLENGTH ];
byte iv[ AES::BLOCKSIZE ];
StringSource( reinterpret_cast<const char *>(decodedKey), true,
new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)) );
memset( iv, 0x00, AES::BLOCKSIZE );
CBC_Mode<AES>::Encryption Encryptor( key, sizeof(key), iv );
StringSource( plain, true, new StreamTransformationFilter( Encryptor,
new HexEncoder(new StringSink( ciphertext ) ) ) );
return QString::fromStdString(ciphertext);
}
To Decrypt:
QString Encryption::AESDecrypt(const QString &data)
{
string plain;
string encrypted = data.toStdString();
// Hex decode symmetric key:
HexDecoder decoder;
decoder.Put( (byte *)PRIVATE_KEY,32*2 );
decoder.MessageEnd();
word64 size = decoder.MaxRetrievable();
char *decodedKey = new char[size];
decoder.Get((byte *)decodedKey, size);
// Generate Cipher, Key, and CBC
byte key[ AES::MAX_KEYLENGTH ];
byte iv[ AES::BLOCKSIZE ];
StringSource( reinterpret_cast<const char *>(decodedKey), true,
new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)) );
memset( iv, 0x00, AES::BLOCKSIZE );
try
{
CBC_Mode<AES>::Decryption Decryptor( key, sizeof(key), iv );
StringSource( encrypted, true,
new HexDecoder(new StreamTransformationFilter( Decryptor,
new StringSink( plain ) ) ) );
}
catch (Exception &e) { // ...
}
catch (...) { // ...
}
return QString::fromStdString(plain);
}
If I run the following:
Encryption encrypt;
QString encdata = encrypt.AESEncrypt("This is my data");
qDebug() << "encrypt: " << encdata;
qDebug() << "decrypt" << encrypt.AESDecrypt(encdata);
I get the following output:
encrypt: "4E712EFDE13DA42FF798C193D17BE5D2"
decrypt ""
So I'm not sure why its not decrypting properly. I took the code from the following conversation. The code is failing on the second StringSource on decrypt and landing on the first Exception. Any ideas on what am I doing wrong?

I was getting a PKCS#7 padding error with the provided code. The code I used was modified to remove the Qt stuff and remove the function calls, so I'm not sure if I accidentally added/removed an error.
I was able to fix the padding issue by modifying the encoding/decoding of the key. I think the problem was here:
StringSource( reinterpret_cast<const char *>(decodedKey), true,
new HashFilter(*(new SHA256), new ArraySink(key, AES::MAX_KEYLENGTH)) );
In the code above, there was no guarantee decodedKey was NULL terminated. The fix was easy - store it in a string and then use length().
The key you listed is 35 bytes in length (after decoding).
#define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
#define PRIVATE_KEY "729308A8E815F6A46EB3A8AE6D5463CA7B64A0E2E11BC26A68106FC7697E727E37011"
string plain1 = "Now is the time for all good men...";
string decoded1, cipher1;
// Hex decode symmetric key:
StringSource ss1((const byte*)PRIVATE_KEY, COUNTOF(PRIVATE_KEY), true,
new HexDecoder(new StringSink(decoded1)));
// Generate Cipher, Key, and CBC
byte key1[ AES::MAX_KEYLENGTH ];
byte iv1[ AES::BLOCKSIZE ];
SHA256 sha1;
StringSource ss2( decoded1, true,
new HashFilter(sha1, new ArraySink(key1, sizeof(key1))) );
memset( iv1, 0x00, AES::BLOCKSIZE );
CBC_Mode<AES>::Encryption encryptor( key1, sizeof(key1), iv1 );
StringSource ss3( plain1, true, new StreamTransformationFilter( encryptor,
new HexEncoder(new StringSink( cipher1 ) ) ) );
string plain2, decoded2;
string cipher2 = cipher1;
// Hex decode symmetric key:
StringSource ss4((const byte*)PRIVATE_KEY, COUNTOF(PRIVATE_KEY), true,
new HexDecoder(new StringSink(decoded2)));
// Generate Cipher, Key, and CBC
byte key2[ AES::MAX_KEYLENGTH ];
byte iv2[ AES::BLOCKSIZE ];
SHA256 sha2;
StringSource ss5( decoded2, true,
new HashFilter(sha2, new ArraySink(key2, sizeof(key2))) );
memset( iv2, 0x00, AES::BLOCKSIZE );
CBC_Mode<AES>::Decryption decryptor( key2, sizeof(key2), iv2 );
StringSource ss6( cipher2, true,
new HexDecoder(new StreamTransformationFilter( decryptor,
new StringSink( plain2 ) ) ) );
cout << "Plain 1: " << plain1 << endl;
cout << "Cipher: " << cipher1 << endl;
cout << "Plain 2: " << plain2 << endl;
Output from those three cout's is:
Plain 1: Now is the time for all good men...
Cipher: 3073448F4A71BC26CF81441F1DEE69C5DE700DF86294181B5E72E19D260DDF1E725DB3EFC74415982FFF45F9F7E290AE
Plain 2: Now is the time for all good men...

Related

OpenSSL: decryption with private key _sometimes_ throws "error:02000079:rsa routines::oaep decoding error"

We are trying to use openSSL to encrypt a string with a public key, and then decrypt it with the private key.
Curiously, the workflow sometimes works, and sometimes it does not work (for the same keys and texts) and throws an error.
First, the private and public key are generated by:
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
openssl rsa -in key.pem -outform PEM -pubout -out public.pem
After that, the code below is executed.
#include <iostream>
using namespace std;
#include <cstring>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
const int PADDING = RSA_PKCS1_OAEP_PADDING;
RSA *createRSAWithFilename(const char *filename, int pub)
{
FILE *fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("Unable to open file %s \n", filename);
return NULL;
}
RSA *rsa = RSA_new();
if (pub)
{
rsa = PEM_read_RSA_PUBKEY(fp, &rsa, NULL, NULL);
}
else
{
rsa = PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);
}
return rsa;
}
int public_encrypt(unsigned char *data, int data_len, RSA *rsa, unsigned char *encrypted)
{
int result = RSA_public_encrypt(data_len, data, encrypted, rsa, PADDING);
return result;
}
int private_decrypt(unsigned char *enc_data, int data_len, RSA *rsa, unsigned char *decrypted)
{
int result = RSA_private_decrypt(data_len, enc_data, decrypted, rsa, PADDING);
return result;
}
int main()
{
std::string textToBeEncoded="hi";
unsigned char plaintext[1024] = {0};
unsigned char encrypted[4098]= {0};
unsigned char decrypted[4098]={0};
strcpy((char *)plaintext,textToBeEncoded.c_str());
RSA *rsaPublic=createRSAWithFilename("public.pem", 1);
memset(encrypted,0,4098);
int en_result=public_encrypt(plaintext, strlen((char *)plaintext), rsaPublic, encrypted);
//fprintf(stderr, "Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
RSA *rsaPrivate=createRSAWithFilename("key.pem", 0);
memset(decrypted,0,4098);
int de_result=private_decrypt(encrypted, strlen((char *)encrypted), rsaPrivate, decrypted);
//fprintf(stderr, "Error: %s\n", ERR_error_string(ERR_get_error(), NULL));
std::cout << "Result EN: " + std::to_string(en_result) << std::endl;
std::cout << "Result DE: " + std::to_string(de_result) << std::endl;
std::string decryptedString = std::string((const char *)decrypted);
std::cout << "DECRYPTED: " + decryptedString << " END."<< std::endl;
return 0;
}
Output:
At one time, the output looks okay and 0 (No error) is the only error code:
Error: error:00000000:lib(0)::reason(0) // error code=0 after encryption
Error: error:00000000:lib(0)::reason(0) // error code=0 after decryption
Result EN: 256
Result DE: 2
DECRYPTED: hi END.
At another time, the output is this:
Error: error:00000000:lib(0)::reason(0) // error code=0 after encryption
Error: error:02000079:rsa routines::oaep decoding error // ERROR after decryption
Result EN: 256
Result DE: -1
DECRYPTED: END.
Can someone help?
Best regards!

How to decrypt a file in virtual memory in C

I'm trying to decrypt a file in memory and this file was encrypted with openssl.
For doing that, i use mmap for loading my encrypted file in memory like that:
void* src = mmap(0, statbuf.st_size,PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
and duplicate it because i don't want to modify my original file
void* dst = mmap(0, statbuf.st_size,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memcpy (dst, src, statbuf.st_size);
At this step all is ok but i don't know what to do next.
Initialy for testing purpose, i encrypt my file with the openssl command :
system("openssl enc -aes-256-cbc -salt -in my_encryptedfile -out my_encryptedfile.enc -pass")
and decrypt it with this command:
system("openssl enc -d -aes-256-cbc -in my_encryptedfile.enc -out my_encryptedfile -pass pass:")
But i can't use dst in this case, so i search and discovered EVP Symmetric Encryption and Decryption.
link here
Then i encrypted and decrypted my file with that code github code
I try using Key and IV and the decryption in memory and it seem working but i have a problem that i don't understand. When i dump the buffer of my decripted file, i saw "SPACES/NULS" at the end of the file and i don't figure out why it display that. When i try to execute my binany in memory by calling this function :
func()
i got a segmentation fault
Any clues?
typedef void (*JittedFunc)(void);
void* alloc_writable_memory(void *ptr, size_t size) {
ptr = mmap(0, size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == (void*)-1) {
perror("mmap");
return NULL;
}
return ptr;
}
int make_memory_executable(void* m, size_t size) {
if (mprotect(m, size, PROT_READ |PROT_WRITE | PROT_EXEC) == -1) {
perror("mprotect");
return -1;
}
return 0;
}
int do_crypt(char *in, char *out, int do_encrypt, int inlen)
{
/* Allow enough space in output buffer for additional block */
unsigned char outbuf[inlen + EVP_MAX_BLOCK_LENGTH];
int outlen;
EVP_CIPHER_CTX *ctx;
/* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "1234567887654321";
//int n;
printf("step1\n");
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
printf("step2\n");
EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,do_encrypt);
printf("step3\n");
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);
/* Now we can set key and IV */
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);
printf("step4\n");
if(!EVP_CipherUpdate(ctx, outbuf,&outlen, in, inlen))
{
printf("test 2.1: %d %d\n", inlen, outlen);
printf("step8\n");
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//BIO_dump_fp (stdout, (const char *)outbuf, outlen);
printf(" test 2: %d %d\n", inlen, outlen);
if(!EVP_CipherFinal_ex(ctx, outbuf, &outlen))
{
printf("step11\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//copy the decryted buffer in another memory space
memcpy(out, outbuf, outlen);
printf(" test 3: %d %d\n", inlen, outlen);
//BIO_dump_fp (stdout, (const char *)outbuf, outlen);
printf("step12\n");
//fwrite(outbuf, 1, outlen, out);
printf("step13\n");
EVP_CIPHER_CTX_free(ctx);
return 1;
}
int main()
{
FILE *src, *dst;
char *src_mem, *dst_mem, *dst2_mem = NULL;
struct stat statbuf;
int fd;
src = fopen("hello_encrypted", "rb");
if (!src) {
/* Unable to open file for reading */
fprintf(stderr, "ERROR: fopen error: %s\n", strerror(errno));
return errno;
}
/*get the file des from a file*/
fd = fileno(src);
/* find size of input file */
if (fstat (fd,&statbuf) < 0)
{printf ("fstat error");
return 0;
}
/* go to the location corresponding to the last byte */
if (lseek (fd, statbuf.st_size - 1, SEEK_SET) == -1)
{printf ("lseek error");
return 0;
}
if ((src_mem = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t) -1)
{
printf ("mmap error for input");
return 0;
}
if ((dst_mem = mmap (0, statbuf.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS , -1, 0)) == (caddr_t) -1)
{
printf ("mmap error for output");
return 0;
}
if ((dst2_mem = mmap (0, statbuf.st_size , PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS , -1, 0)) == (caddr_t) -1)
{
printf ("mmap error for output");
return 0;
}
memcpy(dst_mem, src_mem, statbuf.st_size);
int n;
/* 0 for decrypting or 1 for encrypting*/
n = do_crypt(dst_mem,dst2_mem, 0, statbuf.st_size);
printf("%d\n", n);
make_memory_executable(dst2_mem, statbuf.st_size);
//dump of the decrypt binary
BIO_dump_fp (stdout, (const char *)dst2_mem, statbuf.st_size);
//try to launch the decrypted binary ==> segmentation fault
JittedFunc func = dst2_mem;
func();
fclose(src);
return 0;
}
I would remove from the first mmap the flag PROT_WRITE, because you dont want to modify the original file, I think you can also use PROT_PRIV, but have a look to what says the man of mmap.
On the other hand for decrypt your buffer you can use many libraries (a lot of them based on openssl), I specially like CryptoPP but there are many others. Here is an example of how your code will look like on CryptoPP
try {
// CryptoPP::ECB_Mode< CryptoPP::AES >::Decryption d;
// CrypoPP::CBC_Mode< CryptoPP::AES >::Decryption d;
CrypoPP::CBC_CTS_Mode< CryptoPP::AES >::Decryption d;
// What ever mode is best for you
d.SetKey(key.data(), key.size());
// The StreamTransformationFilter removes
// padding as required.
CryptoPP::StringSource s((const uint8_t*)dst, length_dst, true,
new CryptoPP::StreamTransformationFilter(d,
new CryptoPP::StringSink(recovered)
) // StreamTransformationFilter
); // StringSource
} catch(const CryptoPP::Exception& e) {
std::cout << "ERROR decrypting:" << e.what() << std::endl;
return;
}

Array access is invalid in MQL5 error

I am trying to access the arrays, delivered via a call-signature into the system invoked OnCalculation() event-handler.
This the way it is written:
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[]
)
{
/* The rest code is written here
...
*/
}
I am trying to merge the code with the OpenCL functions so that the program uses GPU for the tremendous calculations. But the issue is when I am trying to pass the values from OnCalculation() to the kernel for execution, I am getting error. See the following code is written inside OnCalculation()
CLSetKernelArg( cl_krn, 0, start );
CLSetKernelArg( cl_krn, 1, rates_total );
CLSetKernelArg( cl_krn, 2, time );
CLSetKernelArg( cl_krn, 3, high );
CLSetKernelArg( cl_krn, 4, low );
Getting the following error:
'time' - invalid array access ADX.mq5 285 31
'high' - invalid array access ADX.mq5 286 31
'low' - invalid array access ADX.mq5 287 31
I don't know why is this problem happening. I am not able to pass the arrays from the OnCalculation().
Kindly, help me what I can do?
It is impossible to just reference an MQL5 array[] object here
OpenCL starts a completely new code-execution eco-system, and MQL5-side data has to get "transferred" correctly there and back...
Using a mock-up trivial GPU-kernel that doubles an array received:
const string // by default some GPU doesn't support doubles
cl_SOURCE = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable \r\n" // cl_khr_fp64 directive is used to enable work with doubles
" \r\n"
"__kernel void Test_GPU( __global double *data, \r\n" // [0]____GPU-kernel-side_CALL-SIGNATURE
" const int N, \r\n" // [1]____GPU-kernel-side_CALL-SIGNATURE
" const int N_arrays \r\n" // [2]____GPU-kernel-side_CALL-SIGNATURE
" ) \r\n"
"{ \r\n"
" uint kernel_index = get_global_id( 0 ); \r\n"
" if ( kernel_index > N_arrays ) return; \r\n"
" \r\n"
" uint local_start_offset = kernel_index * N; \r\n"
" for ( int i = 0; i < N; i++ ) \r\n"
" data[i+local_start_offset] *= 2.0; \r\n"
"} \r\n";
// AFTER FIRST TESTING THE OpenCL DEVICES & THEIR CAPABILITIES ... ( see prev. posts )
#define ARRAY_SIZE 100 // size of the array
#define TOTAL_ARRAYS 5 // total arrays
// ONE CAN:
//--- SET OpenCL-specific handles' holders
int cl_CONTEXT, // an OpenCL-Context handle
cl_PROGRAM, // an OpenCL-Program handle
cl_KERNEL, // an OpenCL Device-Kernel handle
cl_BUFFER; // an OpenCL-buffer handle
uint cl_offset[] = { 0 }; //--- prepare CLExecute() params
uint cl_work[] = { TOTAL_ARRAYS }; //--- global work size
double DataArray2[]; //--- global mapping-object for data aimed to reach the GPU
ArrayResize( DataArray2, //--- size it to fit data in
ARRAY_SIZE * TOTAL_ARRAYS
);
for ( int j = 0; j < TOTAL_ARRAYS; j++ ) //--- fill mapped-arrays with data
{ uint local_offset = j * ARRAY_SIZE; //--- set local start offset for j-th array
for ( int i = 0; i < ARRAY_SIZE; i++ ) //--- for j-th array
DataArray2[i+local_offset] = MathCos(i+j); //--- fill array with some data
}
The principal structure of MQL5 / OpenCL setup is similar to this:
//--- INIT OpenCL
if ( INVALID_HANDLE == ( cl_CONTEXT = CLContextCreate() ) )
{ Print( "EXC: CLContextCreate() error = ", GetLastError() );
return( 1 ); // ---------------^ EXC/RET
}
//--- NEXT create OpenCL program
if ( INVALID_HANDLE == ( cl_PROGRAM = CLProgramCreate( cl_CONTEXT,
cl_SOURCE
)
)
)
{ Print( "EXC: CLProgrameCreate() error = ", GetLastError() );
CLContextFree( cl_CONTEXT );
return( 1 ); // ----------------^ EXC/RET
}
//--- NEXT create OpenCL kernel
if ( INVALID_HANDLE == ( cl_KERNEL = CLKernelCreate( cl_PROGRAM,
"Test_GPU"
)
)
)
{ Print( "EXC: CLKernelCreate() error = ", GetLastError() );
CLProgramFree( cl_PROGRAM );
CLContextFree( cl_CONTEXT );
return( 1 ); // --------------^ EXC/RET
}
//--- TRY: create an OpenCL cl_BUFFER object mapping
if ( INVALID_HANDLE == ( cl_BUFFER = CLBufferCreate( cl_CONTEXT,
(uint) ( ARRAY_SIZE * TOTAL_ARRAYS * sizeof( double ),
CL_MEM_READ_WRITE
)
)
)
{ Print( "EXC: CLBufferCreate() error == ", GetLastError() );
CLKernelFree( cl_KERNEL );
CLProgramFree( cl_PROGRAM );
CLContextFree( cl_CONTEXT );
return(1); // ----------------^ EXC/RET
}
//--- NEXT: set OpenCL cl_KERNEL GPU-side-kernel call-parameters
CLSetKernelArgMem( cl_KERNEL, 0, cl_BUFFER ); // [0]____GPU-kernel-side_CALL-SIGNATURE
CLSetKernelArg( cl_KERNEL, 1, ARRAY_SIZE ); // [1]____GPU-kernel-side_CALL-SIGNATURE
CLSetKernelArg( cl_KERNEL, 2, TOTAL_ARRAYS ); // [2]____GPU-kernel-side_CALL-SIGNATURE
//--- NEXT: write data into to OpenCL cl_BUFFER mapping-object
CLBufferWrite( cl_BUFFER,
DataArray2
);
//--- MAY execute OpenCL kernel
CLExecute( cl_KERNEL, 1, cl_offset, cl_work );
//--- MAY read data back, from OpenCL cl_BUFFER mapping-object
CLBufferRead( cl_BUFFER, DataArray2 );
CLBufferFree( cl_BUFFER ); //--- FINALLY free OpenCL buffer cl_BUFFER mapping-object
CLKernelFree( cl_KERNEL ); //--- FINALLY free OpenCL kernel object
CLProgramFree( cl_PROGRAM ); //--- FINALLY free OpenCL programme object / handle
CLContextFree( cl_CONTEXT ); //--- FINALLY free OpenCL cl_CONTEXT object / handle

How to encrypt text using ElGamal encryption

I just want to know how to encrypt text documents using ElGamal algorithm? I got encryption of integers using this algorithm. Please help with example
Here's an example using Crypto++. The answer was provided for ElGamal encryption example?.
Do you know what language or library you plan on using?
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
#include <cryptopp/osrng.h>
using CryptoPP::AutoSeededRandomPool;
#include <cryptopp/secblock.h>
using CryptoPP::SecByteBlock;
#include <cryptopp/elgamal.h>
using CryptoPP::ElGamal;
using CryptoPP::ElGamalKeys;
#include <cryptopp/cryptlib.h>
using CryptoPP::DecodingResult;
int main(int argc, char* argv[])
{
////////////////////////////////////////////////
// Generate keys
AutoSeededRandomPool rng;
cout << "Generating private key. This may take some time..." << endl;
ElGamal::Decryptor decryptor;
decryptor.AccessKey().GenerateRandomWithKeySize(rng, 512);
const ElGamalKeys::PrivateKey& privateKey = decryptor.AccessKey();
ElGamal::Encryptor encryptor(decryptor);
const PublicKey& publicKey = encryptor.AccessKey();
////////////////////////////////////////////////
// Secret to protect
static const int SECRET_SIZE = 16;
SecByteBlock plaintext( SECRET_SIZE );
memset( plaintext, 'A', SECRET_SIZE );
////////////////////////////////////////////////
// Encrypt
// Now that there is a concrete object, we can validate
assert( 0 != encryptor.FixedMaxPlaintextLength() );
assert( plaintext.size() <= encryptor.FixedMaxPlaintextLength() );
// Create cipher text space
size_t ecl = encryptor.CiphertextLength( plaintext.size() );
assert( 0 != ecl );
SecByteBlock ciphertext( ecl );
encryptor.Encrypt( rng, plaintext, plaintext.size(), ciphertext );
////////////////////////////////////////////////
// Decrypt
// Now that there is a concrete object, we can check sizes
assert( 0 != decryptor.FixedCiphertextLength() );
assert( ciphertext.size() <= decryptor.FixedCiphertextLength() );
// Create recovered text space
size_t dpl = decryptor.MaxPlaintextLength( ciphertext.size() );
assert( 0 != dpl );
SecByteBlock recovered( dpl );
DecodingResult result = decryptor.Decrypt( rng, ciphertext, ciphertext.size(), recovered );
// More sanity checks
assert( result.isValidCoding );
assert( result.messageLength <= decryptor.MaxPlaintextLength( ciphertext.size() ) );
// At this point, we can set the size of the recovered
// data. Until decryption occurs (successfully), we
// only know its maximum size
recovered.resize( result.messageLength );
// SecByteBlock is overloaded for proper results below
assert( plaintext == recovered );
// If the assert fires, we won't get this far.
if(plaintext == recovered)
cout << "Recovered plain text" << endl;
else
cout << "Failed to recover plain text" << endl;
return !(plaintext == recovered);
}

QCA blowfish decryption fails

I'm trying to use QCA to encrypt/decrypt files.
When i use this code to encrypt, everything works fine (or seems to, at least).
But when i try to decrypt, the process() method returns an empty SecureArray.
Does anyone have an idea why and/or how to fix it?
void FileCrypto::crypt(QByteArray key, bool crypt){
QCA::Initializer init;
open();
Cipher cipher = initializeCipher(key, crypt);
QTextStream in(source); //lecture ligne par ligne
while (!in.atEnd()) {
QString line = in.readLine();
SecureArray secureData = line.toAscii().data(); //securise les donnees
if(!crypt)
QString temp = QString::fromAscii(secureData.toByteArray().toHex());
qDebug() << "Données lues : " << secureData.data();
SecureArray cryptedData = cipher.process(secureData); //(de)crypte les donnees
qDebug() << "Données cryptées :" << cryptedData.data();
destination->write(cryptedData.data()); //ecris dans le nouveau fichier
}
close();
}
void FileCrypto::open() throw (QString){
if(!source->open(QIODevice::ReadOnly | QIODevice::Text)
|| !destination->open(QIODevice::WriteOnly | QIODevice::Text)){
throw QString("Impossible d'ouvrir les fichiers cibles.");
}
}
void FileCrypto::close(){
source->close();
destination->close();
}
Cipher FileCrypto::initializeCipher(QByteArray akey, bool crypt){
QCA::InitializationVector iv;
Direction direction;
SymmetricKey key = SymmetricKey(akey);
iv = InitializationVector(akey);
if(crypt){
direction = Encode;
}else{
direction = Decode;
}
return Cipher(QString("blowfish"),Cipher::CBC,
Cipher::DefaultPadding, direction, key, iv);
}

Resources