I am getting "unknown: this object doesn't support multiple channels" exception during file encryption. I am able to generate session key but it can not be used to encrypt file.
The following is my code snippet for file encryption:
void enc_file_EAX(PAES_KEY_WITH_IV key, const char *in_file, const char *out_file)
{
try {
CryptoPP::EAX<CryptoPP::AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key->key, key->key.size(), key->iv);
CryptoPP::FileSource f(in_file, true,
new CryptoPP::AuthenticatedEncryptionFilter(encryptor,
new CryptoPP::FileSink(
std::string(in_file).c_str()),
CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION |
CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END ));
std::fstream file(out_file, std::ios::binary | std::ios::ate);
size_t remaining = file.tellg();
file.close();
size_t BLOCK_SIZE = 16384;
while (remaining && !f.SourceExhausted()) {
const unsigned int req = std::min(remaining, BLOCK_SIZE);
f.Pump(req);
f.Flush(false);
remaining -= req;
}
} catch (const CryptoPP::Exception& e) {
std::cout << e.GetWhat() << std::endl;
return;
}
}
Can someone help me on this ? What is going wrong here ?
Thanks in advance.
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key->key, key->key.size(), key->iv);
FileSource f(in_file, true,
new AuthenticatedEncryptionFilter(encryptor,
new FileSink(
std::string(in_file).c_str()),
AuthenticatedDecryptionFilter::THROW_EXCEPTION |
AuthenticatedDecryptionFilter::MAC_AT_END ));
You are mixing and matching encryption and decryption gear in the same object pipeline. You should probably fix that first.
Looking at AuthenticatedEncryptionFilter, the THROW_EXCEPTION | MAC_AT_END
flags are probably being coerced into the putAAD
flag:
AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c,
BufferedTransformation *attachment = NULL, bool putAAD=false,
int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL,
BlockPaddingScheme padding=DEFAULT_PADDING);
I seem to recall you need to avoid the Pipelines if you want to add AAD. The pipe only allows inputting data on DEFAULT_CHANNEL
, which provides AE (but no AAD). Also see EAX Mode | AEAD example on the Crypto++ wiki.
Your use of FileSink
and FileSource
does not quite look right. I'm not sure how this is going to behave:
FileSource f(in_file, true, ...
new FileSink(std::string(in_file).c_str()), ...);
You should probably use in_file.c_str()
for the file name:
FileSource f(in_file.c_str(), ...);
You should also probably use a different file for the sink:
FileSource f(out_file.c_str(), ...);
EDIT (from the comments):
No , we don't want to add pipeline, we just want to use DEFAULT_CHANNEL for inputting data. And given example is for text input. I want to use same function for file inputting. Can you elaborate more on this?
In this case, try:
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(key->key, key->key.size(), key->iv);
FileSource f(in_file.c_str(), true,
new AuthenticatedEncryptionFilter(encryptor,
new FileSink(out_file.c_str()));
That should input text for confidentiality and integrity (AE). It will avoid text with confidentiality only (AEAD).
Also see EAX Mode on the Crypto++ wiki. It has three or four examples with both AE and AEAD.