> 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 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. > 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); HMAC<SHA256> hmac1; hmac1.SetKey(keys.data() + 32, 16); HMAC<SHA256> hmac2; hmac2.SetKey(keys.data() + 32, 16); HexEncoder encoder(new FileSink(cout)); cout << "AES key: "; encoder.Put(keys.data() + 0, 16); encoder.MessageEnd(); cout << endl; cout << "AES IV: "; encoder.Put(keys.data() + 16, 16); encoder.MessageEnd(); cout << endl; cout << "HMAC key: "; encoder.Put(keys.data() + 32, 16); encoder.MessageEnd(); cout << endl; string plain = "Now is the time for all good men to come to the aide of their country"; string cipher, recover; cout << plain << endl; // Encrypt with HMAC StringSource ss1(plain, true /*pumpAll*/, new StreamTransformationFilter(encryptor, new HashFilter(hmac1, new StringSink(cipher), true /*putMessage*/, DIGEST_SIZE))); cout << "Ciphertext+MAC: "; 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; On Friday, April 3, 2015 at 6:59:19 PM UTC-4, Maricel Gregoraschko wrote: > > > > Hi, > I need to encrypt a stream (with a symmetric algorithm) and compute its > HMAC at the same time. Is there an easy way to do that in crypto++, without > going through it twice, short of reading and feeding the file manually into > the two filters? In Botan you do it with the Fork class. Thanks! > > -- -- You received this message because you are subscribed to the "Crypto++ Users" Google Group. To unsubscribe, send an email to [email protected]. More information about Crypto++ and this group is available at http://www.cryptopp.com. --- You received this message because you are subscribed to the Google Groups "Crypto++ Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
