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

Forgot to mention... The issue appears to lie somewhere in the 
HashVerificationFilter.

On Saturday, April 4, 2015 at 10:54:42 PM UTC-4, Jeffrey Walton wrote:
>
> > 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 
> <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 - private 
> <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;
>
 

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

Reply via email to