Ben
Ben

Reputation: 199

Crypto++ exception calling messageEnd

I use following code to decrypt a file:

FileSource fe(fileUrl.c_str(), false,
                  new AuthenticatedDecryptionFilter(decryptor, new FileSink(
                          std::string(fileUrl).c_str()), CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION |  CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END ));

        size_t BLOCK_SIZE = 16384;
    while (remaining && !fe.SourceExhausted()) {
        const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
        fe.Pump(req);
        fe.Flush(false);

        remaining -= req;
    }
    fe.MessageEnd();

If i try to do this without the fe.MessageEnd(), my decrypted File is 16 bytes short. So i thought i need to call MessageEnd() to fix this problem. But if i call MessageEnd() i get Follwing Exception: BufferedTransformation: this object doesn't allow input

Upvotes: 1

Views: 579

Answers (1)

jww
jww

Reputation: 102376

if i call MessageEnd() I get Follwing Exception: BufferedTransformation: this object doesn't allow input...

Correct. The FileSource is a source, and the message must exist. You can't call Put or Put2 on the source to add additional data to the message.


I think you have two options to take more control over the signals.

First

Call Flush on the Source.

const int opts = AuthenticatedDecryptionFilter::THROW_EXCEPTION |
    AuthenticatedDecryptionFilter::MAC_AT_END;

FileSource fe(fileUrl.c_str(), false,
    new AuthenticatedDecryptionFilter(decryptor, new FileSink(
        std::string(fileUrl).c_str()), opts));

fe.Flush(true);

Also see the comments for Flush at Filter::Flush in the manual.

Second

Stash a pointer to the filter and call MessageEnd on it.

const int opts = AuthenticatedDecryptionFilter::THROW_EXCEPTION |
     AuthenticatedDecryptionFilter::MAC_AT_END;
AuthenticatedDecryptionFilter* adf = NULL;

FileSource fe(fileUrl.c_str(), false,
    adf = new AuthenticatedDecryptionFilter(decryptor, new FileSink(
        std::string(fileUrl).c_str()), opts));
adf.MessageEnd();

This is kind of unusual, so I'm not sure what side effects you will encounter.

Don't delete the pointer. The FileSource will delete it when it goes out of scope at the closing brace.


... my decrypted file is 16 bytes short...

In my opinion, this is the problem you should pursue if calling Flush on the Source does not work for you.

Also keep in mind... The output of AuthenticatedEncryptionFilter is the 2-tuple {ciphertext,mac}, so you get ciphertext expansion of 16-bytes because of the MAC. Later, when you use AuthenticatedDecryptionFilter, the mac is removed after verifying it. So the recovered text should be the same size as the plain text, both of which should be 16-bytes less than the cipher text.

The thing I am not clear about is, are things working as expected but you don't realize that's how its supposed to work. Or are you really loosing 16-bytes of recovered text somewhere.

Upvotes: 1

Related Questions