Search code examples
encryptionpipelineencryption-symmetriccrypto++

"unknown: this object doesn't support multiple channels" during encryption


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.


Solution

  • 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.