0

I've been trying to encrypt and decrypt a file using AES in GCM mode using Crypto++. What this code is supposed to do is, given a password, hash it using PBKDF2< HMAC< SHA256>>, then encrypt and decrypt a file using the password hash as the key. After searching all over on Stack Overflow I've gotten this far:

using namespace Cryptopp;

const std::string password = "password";
const int iterations = 1000000;
const std::string fileName = "test.txt";
SecByteBlock derived(32);
SecByteBlock salt(16);
const int TAG_SIZE = AES::BLOCKSIZE;

AutoSeededRandomPool rng;
rng.GenerateBlock(salt, 16);

// KDF function
PKCS5_PBKDF2_HMAC<SHA256> kdf;
kdf.DeriveKey(
    derived.data(), 
    derived.size(), 
    0, 
    (byte*)password.data(), 
    password.size(), 
    salt.data(), 
    salt.size(), 
    iterations);

// Key the cipher
GCM<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), 16, derived.data() + 16, 16);

FileSource(fileName.c_str(), true,
    new AuthenticatedEncryptionFilter(encryptor, 
    new FileSink(fileName.c_str()), false, TAG_SIZE));

// Key the cipher
GCM<AES>::Decryption decryptor;
decryptor.SetKeyWithIV(derived.data(), 16, derived.data() + 16, 16);

AuthenticatedDecryptionFilter decryptionFilter(decryptor, 
    new FileSink(fileName.c_str()), 16, TAG_SIZE);
FileSource(fileName.c_str(), true, new Redirector(decryptionFilter));

If the use of half of the derived hash from PBKDF2 as the key and half as the IV seems weird, this code is largely copied from How to use a custom key in Crypto++. Is this good practice in cryptography? Or should I generate a separate IV every time I encrypt?

Crypto++ throws a HashVerificationFailed exception, meaning the data was changed since encryption. So obviously I'm doing something wrong. What's wrong with my code?

  • 2
    You should probably checkout [GCM Mode](https://www.cryptopp.com/wiki/GCM_Mode) on the Crypto++ wiki. The wiki provides working examples for download. Plug in your custom keying scheme to a known good implementation and see if it works as expected. – jww Nov 27 '17 at 13:36
  • I did check that out, and eventually solved it. I did not understand the difference between the 'sink' and 'source' objects. – Andrew LeFevre Nov 30 '17 at 19:26
  • 1
    Sources and Sinks are part of the [Pipeline](https://www.cryptopp.com/wiki/Pipelining) model. Its just a high level abstractions. Data flows from sources to sinks. In between, filters are encountered that transform the data. You are certainly free to use the lower level stuff like `Put` and `Get`. The pipelines call them under the covers. – jww Nov 30 '17 at 19:44

0 Answers0