2

I am trying to encrypt a byte array using AES. I have been able to encrypt strings and files no problem, however byte arrays seem to not be working for me. I pass in a byte array to be encrypted, for ease of testing I just pass in a generated AES key by crypto++ (bArrayToEncrypt). The encryption appears to be working but then the decryption does work at all. I also found it strange that the encryption has a large amount of duplicate characters. What I am doing wrong here??

I saw a similar question Here, but it was pertaining to RSA as well as the example provided encrypts strings which I already have up a running.

How functions are called:

   size_t ksize = CryptoPP::AES::MAX_KEYLENGTH;
   size_t vsize = CryptoPP::AES::BLOCKSIZE;

   byte key[ksize];
   byte testArray[ksize];
   byte encryptedksize];
   byte decrypted[ksize];
   byte iv[vsize];

   //generate key & iv, then generate a random byte array to encrypt/decrypt
   CryptoPP::AutoSeededRandomPool prng;
   prng.GenerateBlock(key, ksize);
   prng.GenerateBlock(iv, vsize);
   prng.GenerateBlock(testArray, ksize);


   encrypt_barray(key, ksize, iv, vsize, testArray, ksize, encrypted);

   //printed results here

   decrypt_barray(key, ksize, iv, vsize, encrypted, ksize, decrypted);

   //printed results here

Encrypt_barray

void encrypt_barray(byte* key, 
                    size_t kSize,
                    byte* iv, 
                    size_t ivSize, 
                    byte* bArrayToEncrypt,
                    size_t bArraySize,
                    byte* encrypted) {

   CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption e;
   e.SetKeyWithIV(key, kSize, iv, ivSize);

   CryptoPP::ArraySource(key, true,
      new CryptoPP::StreamTransformationFilter(e, new CryptoPP::ArraySink(encrypted, bArraySize)));
}

Decrypt_barray

void decrypt_barray(byte* key,
                    size_t kSize,
                    byte* iv,
                    size_t ivSize,
                    byte* bArrayToDecrypt,
                    size_t bArraySize,
                    byte* decrypted) {

   CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption d;
   d.SetKeyWithIV(keyFromHash, kfhSize, iv1, iv1Size);

   CryptoPP::ArraySource(keyToDecrypt, true,
      new CryptoPP::StreamTransformationFilter(d, new CryptoPP::ArraySink(decrypted, bArraySize)));
}

Output:

 Encrypted: ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠E1A2AFC5D820ADF7
7DB656DEF3245570╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╨Ñ♫

Decrypted: ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠E
1A2AFC5D820ADF77DB656DEF3245570╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╨Ñ♫
Press any key to continue . . .
Community
  • 1
  • 1
  • `ArraySink` is the wrong tool for the job. You cannot get the actual size of the ciphertext from the encryption operation. Then, during decryption, you are flying blind because you don't know what size to use with the `ArraySource`. Consider switching to a `std::string` or a `ByteQueue`. Also see [SecByteBlockSink](https://www.cryptopp.com/wiki/SecByteBlockSink) on the Crypto++ wiki. – jww Mar 15 '17 at 18:43
  • Also, `E1A2AFC5D820ADF77DB656DEF3245570` and `E1A2AFC5D820ADF77DB656DEF3245570` almost look like a concatenation memory locations (i.e., pointers) to me. You should probably show the way you are calling `encrypt_barray` and `decrypt_barray`. – jww Mar 15 '17 at 18:46
  • @jww I went ahead and added how I am calling those 2 functions. Thanks! –  Mar 15 '17 at 19:00
  • How would I go about incorporating a ByteQueue into these functions? –  Mar 15 '17 at 19:09
  • The ciphertext will be larger than `testArray[ksize]` due to the mode of operation and PKCS padding. `ArraySink` will store up to `ksize` bytes, and then stop writing to the array. – jww Mar 15 '17 at 19:12
  • @jww That would make sense. So then you mentioned i should change it to use a ByteQueue. How would I go about incorporating a ByteQueue into these functions? Thanks again! –  Mar 15 '17 at 19:18

1 Answers1

4

Here's the way to do things using ArraySource and ArraySink. The Redirector ensures the ArraySink survives so you can call TotalPutLength.

#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"
using namespace CryptoPP;

int main(int argc, char* argv[])
{
  byte key[AES::MAX_KEYLENGTH];
  byte iv[AES::BLOCKSIZE];
  vector<byte> plain, cipher, recover;
  HexEncoder encoder(new FileSink(cout));

  memset(key, 0x00, sizeof(key));
  memset(iv, 0x00, sizeof(iv));

  string str("Attack at dawn!");
  std::copy(str.begin(), str.end(), std::back_inserter(plain));

  cout << "Plain text: ";
  encoder.Put(plain.data(), plain.size());
  encoder.MessageEnd();
  cout << endl;

  /////////////////////////////////////////////////////////////

  CBC_Mode<AES>::Encryption enc;
  enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

  // 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());

  cout << "Cipher text: ";
  encoder.Put(cipher.data(), cipher.size());
  encoder.MessageEnd();
  cout << endl;

  /////////////////////////////////////////////////////////////

  CBC_Mode<AES>::Decryption dec;
  dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

  // Recovered text will be less than cipher text
  recover.resize(cipher.size());
  ArraySink rs(&recover[0], recover.size());

  ArraySource(cipher.data(), cipher.size(), true,
    new StreamTransformationFilter(dec, new Redirector(rs)));

  // Set recovered text length now that its known
  recover.resize(rs.TotalPutLength());

  cout << "Recovered text: ";
  encoder.Put(recover.data(), recover.size());
  encoder.MessageEnd();
  cout << endl;

  return 0;
}

Running the program results in:

$ ./test.exe
Plain text: 41747461636B206174206461776E21
Cipher text: 85928E5511BFE9E6EE235BCACC4894D4
Recovered text: 41747461636B206174206461776E21

Here's the example using ByteQueue. The Redirector helps chain the pipeline together because a ByteQueue is a BufferedTransformation.

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

#include "cryptlib.h"
#include "filters.h"
#include "files.h"
#include "modes.h"
#include "queue.h"
#include "hex.h"
#include "aes.h"
using namespace CryptoPP;

int main(int argc, char* argv[])
{
  byte key[AES::MAX_KEYLENGTH];
  byte iv[AES::BLOCKSIZE];
  HexEncoder encoder(new FileSink(cout));

  memset(key, 0x00, sizeof(key));
  memset(iv, 0x00, sizeof(iv));

  ByteQueue plain, cipher, recover;
  string str("Attack at dawn!");
  plain.Put(reinterpret_cast<const byte*>(str.data()), str.size());

  cout << "Plain text: ";
  plain.CopyTo(encoder);
  encoder.MessageEnd();
  cout << endl;

  /////////////////////////////////////////////////////////////

  CBC_Mode<AES>::Encryption enc;
  enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

  StreamTransformationFilter f1(enc, new Redirector(cipher));
  plain.CopyTo(f1);
  f1.MessageEnd();

  cout << "Cipher text: ";
  cipher.CopyTo(encoder);
  encoder.MessageEnd();
  cout << endl;

  /////////////////////////////////////////////////////////////

  CBC_Mode<AES>::Decryption dec;
  dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

  StreamTransformationFilter f2(dec, new Redirector(recover));
  cipher.CopyTo(f2);
  f2.MessageEnd();

  cout << "Recovered text: ";
  recover.CopyTo(encoder);
  encoder.MessageEnd();
  cout << endl;

  return 0;
}

It also results in:

skylake:cryptopp$ ./test.exe
Plain text: 41747461636B206174206461776E21
Cipher text: 85928E5511BFE9E6EE235BCACC4894D4
Recovered text: 41747461636B206174206461776E21
jww
  • 97,681
  • 90
  • 411
  • 885
  • What an awesome answer! Really appreciate this cause now I also get to learn why it's the correct way. Thanks again! –  Mar 15 '17 at 21:33