when i Run the following program, i get the error message : terminate called after throwing an instance of ‘CryptoPP::InvalidKeyLength’
what(): AES: 12 is not a valid key length
Aborted (core dumped).
#include "cryptopp/cryptlib.h"
#include "cryptopp/files.h"
#include "cryptopp/hex.h"
#include "cryptopp/osrng.h"
#include "cryptopp/modes.h"
#include "cryptopp/aes.h"
#include "cryptopp/gcm.h"
#include "cryptopp/secblock.h"
#include "cryptopp/pwdbased.h"
#include <iostream>
#include <fstream>
#include <math.h>
#include <string>
using namespace CryptoPP;
void printHex(const byte* data, size_t size, const std::string &label); //for debuggin to print hex values
void deriveKeyAndIV(const std::string& password, byte* key, size_t keySize, byte* iv, size_t ivSize);
//for deriving key and iv using hkdf
void encryptFile(const std::string &password, const std::string &inputFile, const std::string &outputFile);
// Function prototype for encryptFile
void decryptFile(const std::string &password, const std::string &inputFile, const std::string &outputFile);
// Funciton prototype for decryptFile
//void generateAndStoreMasterKey(const std::string &masterKeyFile);
// Function prototype for generateAndStoreMasterKey
void printHex(const byte* data, size_t size, const std::string &label) {
CryptoPP::HexEncoder encoder(new CryptoPP::FileSink(std::cout));
std::cout << label << ": ";
encoder.Put(data, size);
std::cout << std::endl;
//all of print hex for debuggin purposes
}
void deriveKeyAndIV(const std::string& password, byte* key, size_t keySize, byte* iv, size_t ivSize) {
CryptoPP::SecByteBlock derived(keySize + ivSize);
//the keysize & ivSize is not defined.
CryptoPP::SecByteBlock salt(16);
CryptoPP::AutoSeededRandomPool prng;
prng.GenerateBlock(salt, 16);
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256> kdf;
kdf.DeriveKey(derived.data(), derived.size(), 0, (const byte*)password.data(), password.size(), salt.data(), salt.size(), 1000000);
std::memcpy(key, derived.data(), keySize);
std::memcpy(iv, derived.data() + keySize, ivSize);
std::cout << "Derived key size: " << keySize << std::endl;
std::cout << "Derived iv size: " << ivSize << std::endl;
}
void encryptFile(const std::string &password, const std::string &inputFile, const std::string &outputFile) {
//Encrypt file using AES-256-GCM mode
const size_t keySize = 32;
const size_t ivSize = 12;
const size_t TAG_SIZE = 16;
byte key[32], iv[12];
deriveKeyAndIV(password, key, keySize, iv, ivSize);
printHex(key, sizeof(key), "Encryption Key");
printHex(iv, sizeof(iv), "IV");
//debugging
CryptoPP::GCM< CryptoPP::AES >::Encryption encryption;
encryption.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
CryptoPP::AuthenticatedEncryptionFilter aef(encryption, new CryptoPP::FileSink(inputFile.c_str()), //Write the encrypted data and mac to the outputfile
false, TAG_SIZE);
FileSink ivSink(outputFile.c_str(), true);
ivSink.Put(iv, sizeof(iv));
ivSink.MessageEnd();
aef.ChannelPut(CryptoPP::AAD_CHANNEL, iv, sizeof(iv));
//Adding the IV to the AAD channel (MAC calculation)
FileSource fs(inputFile.c_str(), false);
byte buffer[4096];
while(true) {
size_t bytesRead = fs.Get(buffer, sizeof(buffer));
if (bytesRead == 0) break;
aef.ChannelPut(DEFAULT_CHANNEL, buffer, bytesRead);
}
aef.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL);
aef.ChannelMessageEnd(CryptoPP::AAD_CHANNEL);
//End the AAD channel
aef.MessageEnd();
std::cout << "IV after encryption: ";
printHex(iv, sizeof(iv), "IV after encryption");
std::cout << "MAC after encryption: ";
//nothing yet -_-
}
void decryptFile(const std::string &password, const std::string &inputFile, const std::string &outputFile) {
//Decrypt file using AES-256-GCM mode
const size_t keySize = 32;
const size_t ivSize = 12;
byte key[32], iv[12];
if (sizeof(key) != 32) {
throw std::invalid_argument("Invalid key size. Must be 32 bytes for AES-256.");
}
const size_t TAG_SIZE = 16;
FileSource fs(inputFile.c_str(), false);
fs.Pump(12);
fs.Get(iv, 12);
//read the iv from the beggining of the file
std::string cipherText;
FileSource(inputFile.c_str(), true, new StringSink(cipherText));
std::string enc = cipherText.substr(12, cipherText.length() - 12 -TAG_SIZE);
std::string mac = cipherText.substr(cipherText.length() - TAG_SIZE);
//Extracting the cipherText and the MAC from the cipherText
CryptoPP::GCM<CryptoPP::AES>::Decryption decryption;
decryption.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
CryptoPP::AuthenticatedDecryptionFilter adf(decryption, new CryptoPP::FileSink(outputFile.c_str()), CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_BEGIN | CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION, TAG_SIZE); //Decrypting the cipher text
adf.ChannelPut(CryptoPP::DEFAULT_CHANNEL, (const byte*)(mac.data()), mac.size());
//Adding the MAC to the channel
adf.ChannelPut(CryptoPP::AAD_CHANNEL, iv, sizeof(iv));
//Adding the IV to the AAD channel (MAC calculation)
adf.ChannelPut(CryptoPP::DEFAULT_CHANNEL, (const byte*)(enc.data()), enc.size());
//Adding the cipher text to the channel
adf.ChannelMessageEnd(CryptoPP::AAD_CHANNEL);
adf.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL);
//End the AAD channel and the channel
bool result = adf.GetLastResult();
if (!result) {
throw CryptoPP::Exception(CryptoPP::Exception::OTHER_ERROR, "MAC check failed");
}
try {
std::string retrieved;
size_t n = (size_t)-1;
//remove data from channel
adf.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL);
n = (size_t)adf.MaxRetrievable();
retrieved.resize(n);
//resize the retrieved string to the maximum size possible
if (n > 0) {
adf.Get((byte*)retrieved.data(), n);
}
//get the data from the channel
FileSink output(outputFile.c_str());
output.Put((const byte*)retrieved.data(), retrieved.size());
//write the retrieved data to the output file
} catch (const CryptoPP::InvalidCiphertext &e) {
std::cerr << "Decryption error: " << e.what() << std::endl;
}
}
int main() {
std::cout << "Starting program...." << std::endl;
std::string password;
std::cout << "Enter password: ";
std::cin >> password;
std::string inputFile;
std::string outputFile;
//try{
char choice;
std::cout << "Do you want to encrypt or decrypt? (e/d): ";
std::cin >> choice;
if (choice == 'e') {
std::cout << "Enter the input file name for encryption: ";
std::cin >> inputFile;
outputFile = inputFile + ".enc";
encryptFile(password, inputFile, outputFile);
std::cout << inputFile << " was encrypted sucessfully." << std::endl;
} else if (choice == 'd') {
std::cout << "Enter the input file name for decryption: ";
std::cin >> inputFile;
outputFile = inputFile + ".dec";
decryptFile(password, inputFile, outputFile);
std::cout << inputFile << " was decrypted sucessfully." << std::endl;
} else {
std::cout << "Invalid choice. Please enter 'e' for encryption or 'd' for decryption." << std::endl;
}
/*} catch (const std::exception &e) {
std::cerr << "An Error occured: " << e.what() << std::endl;
} */
std::cout << "Program ended" << std::endl;
return 0;
}
Ive tried adding debugging, locating where the issue is occurring and changing the key and IV sizes, im not sure what to do now
New contributor
Ethan is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.