> I need to encrypt a stream (with a symmetric algorithm)
> and compute its HMAC at the same time.
You have to be careful here. Combining a confidentiality mode with an authenticity mode can cause some trouble if you combine them incorrectly. Its probably best to use a mode that does it for you, like EAX, CCM or GCM mode.
Getting authenticated encryption wrong is easy. SSL/TLS and SSH got them wrong, and they've been dealing with the associated bugs for decades. IPSec got it right with Encrypt-Then-Authenticate.
To have a chance at getting it right, you have to encrypt the data first and then MAC it. That's what IPSec does. See http://www.cryptopp.com/wiki/Authenticated_Encryption - private for more details.
> In Botan you do it with the Fork class.
Crypto++ has a ChannelSwitch which allows you to take data and send it to multiple sinks. But I don't think that's what you want in the is case.
If you were doing authenticated encryption using Encrypt-And-Authenticate (like SSH), then you could use the ChannelSwitch.
> Is there an easy way to do that in crypto++, without going through it twice
Yes, just pipeline the data. Have the output of the encryptor feed the HMAC.
You can read more about pipelining at http://www.cryptopp.com/wiki/Pipeline - private.
> I need to encrypt a stream (with a symmetric algorithm)
> and compute its HMAC at the same time.
You have to be careful here. Combining a confidentiality mode with an authenticity mode can cause some trouble if you combine them incorrectly. Its probably best to use a mode that does it for you, like EAX, CCM or GCM mode.
Getting authenticated encryption wrong is easy. SSL/TLS and SSH got them wrong, and they've been dealing with the associated bugs for decades. IPSec got it right with Encrypt-Then-Authenticate.
To have a chance at getting it right, you have to encrypt the data first and then MAC it. That's what IPSec does. See http://www.cryptopp.com/wiki/Authenticated_Encryption - private for more details.
> In Botan you do it with the Fork class.
Crypto++ has a ChannelSwitch which allows you to take data and send it to multiple sinks. But I don't think that's what you want in the is case.
If you were doing authenticated encryption using Encrypt-And-Authenticate (like SSH), then you could use the ChannelSwitch.
> Is there an easy way to do that in crypto++, without going through it twice
Yes, just pipeline the data. Have the output of the encryptor feed the HMAC.
You can read more about pipelining at http://www.cryptopp.com/wiki/Pipeline - private.
> without going through it twice
You will *always* have to touch the data twice. The only mode that supports touching the data once is CWC mode. Its patented, so everything else touches the data twice.
With that out of the way, below is a program that kind of does what you want. It streams plaintext data through and encryptor and then a HMAC. Unfortunately, it appears to have a bug. The unfortunate thing is the bug appears to be in the Crypto++ library (modulo me doing something dumb).
...
> I need to encrypt a stream (with a symmetric algorithm)
> and compute its HMAC at the same time.
You have to be careful here. Combining a confidentiality mode with an authenticity mode can cause some trouble if you combine them incorrectly. Its probably best to use a mode that does it for you, like EAX, CCM or GCM mode.
Getting authenticated encryption wrong is easy. SSL/TLS and SSH got them wrong, and they've been dealing with the associated bugs for decades. IPSec got it right with Encrypt-Then-Authenticate.
To have a chance at getting it right, you have to encrypt the data first and then MAC it. That's what IPSec does. See http://www.cryptopp.com/wiki/ Authenticated_Encryption - private for more details.
> In Botan you do it with the Fork class.
Crypto++ has a ChannelSwitch which allows you to take data and send it to multiple sinks. But I don't think that's what you want in the is case.
If you were doing authenticated encryption using Encrypt-And-Authenticate (like SSH), then you could use the ChannelSwitch.
> Is there an easy way to do that in crypto++, without going through it twice
Yes, just pipeline the data. Have the output of the encryptor feed the HMAC.
You can read more about pipelining at http://www.cryptopp.com/wiki/ Pipeline - private.
> without going through it twice
You will *always* have to touch the data twice. The only mode that supports touching the data once is CWC mode. Its patented, so everything else touches the data twice.
With that out of the way, below is a program that kind of does what you want. It streams plaintext data through and encryptor and then a HMAC. Unfortunately, it appears to have a bug. The unfortunate thing is the bug appears to be in the Crypto++ library (modulo me doing something dumb).
I have not analyzed the stack trace, yet. I'm tossing it out there in case someone else has time to look at it and develop a patch.
********
static const int DIGEST_SIZE = HMAC<SHA256>::DIGESTSIZE;
SecByteBlock keys(16 /*AES key*/ + 16 /*AES IV*/ + 16 /*HMAC key*/);
OS_GenerateRandomBlock(false, keys, keys.size());
CBC_Mode<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(keys. data() + 0 /*key*/, 16, keys.data() + 16 /*iv*/, 16);
CBC_Mode<AES>::Decryption decryptor;
encryptor.SetKeyWithIV(keys. data() + 0 /*key*/, 16, keys.data() + 16 /*iv*/, 16);
encoder.Put((byte*)cipher. data(), cipher.size());
encoder.MessageEnd(); cout << endl;
// Decrypt with HMAC verification
StringSource ss2(cipher, true /*pumpAll*/,
new HashVerificationFilter(hmac2,
new StreamTransformationFilter( decryptor,
new StringSink(recover)),
HASH_AT_END | PUT_MESSAGE,
DIGEST_SIZE));
cout << recover << endl;
Also, in order to get the authentication right (not using an authenticated mode like GCM/EAX), is there anything else obvious that I should be aware of other than making sure I calculate the HMAC(SHA256/512) on the cipher text, not plain, and use a different MAC key than the cipher key, and if deriving it from a passphrase, generate it with a computationally heavy KDF? Thank you!
By the way, you are linking to wiki pages (Authenticated_Encryption, ChannelSwitch), that I see no way to get to from cryptopp main wiki page
I had no clue they existed, and it seems there are many more. I see no table of contents, no index and no search, how does one get to the documentation without knowing exact URL's of specific pages?
The source code is incredibly sparsely documented, is there annotated code elsewhere? Am I looking in the wrong place?
How is one supposed to know what putMessage=true means in HashFilter()?
Or the fact that HashVerificationFilter() takes in the message + hash at the end if you use HashVerificationFilter::HASH_AT_END and it outputs just the message with the hash stripped if you use HashVerificationFilter::PUT_MESSAGE?
Or the fact that ChannelSwitch exists and what it's used for? People just browse through source code, look at classes and go "there it is! that's what I'm looking for!"? :)
One more question, how does HashVerificationFilter check the hash, does it set a status somewhere? Because it doesn't throw an exception or anything for the wrong hash.Thank you very much for your time. It's truly appreciated.
Also, in order to get the authentication right (not using an authenticated mode like GCM/EAX), is there anything else obvious that I should be aware of other than making sure I calculate the HMAC(SHA256/512) on the cipher text, not plain, and use a different MAC key than the cipher key, and if deriving it from a passphrase, generate it with a computationally heavy KDF? Thank you!
By the way, you are linking to wiki pages (Authenticated_Encryption, ChannelSwitch), that I see no way to get to from cryptopp main wiki page
> Well, we (the community) run the Wiki. What do you suggest? We can make the changes if they seem like they would be helpful.I would say that first of all the new visitor needs to be made aware that these pages exist. Because browsing through the wiki site you only see "Denis Bider's Crypto++ User Guide" which is very short and dated.A hierarchical table of contents, or at least a categorized list of pages would be very good.
That could be some work, but how about just flatly listing all the wiki pages in an html that's linked to from the web page. Just the directory listing, and perhaps other pages too if they are not all in the same directory. That should be straightforward to do.
You can also post a text on the main wiki page that says "if you search a class name in the search box below, you will get additional documentation", or "you can form URLs by adding a class name to...
> Take consolation in the fact that the wiki has only been around since about 2005 or so. It was quite painful before then :)I felt that pain full force, as I had no idea anything else existed other than what's linked to from the crypto++ home page and wiki page. And any newcomer is bound to experience the same, guaranteed.