processing same stream in parallel

27 views
Skip to first unread message

Maricel Gregoraschko

unread,
Apr 3, 2015, 6:59:19 PM4/3/15
to cryptop...@googlegroups.com


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!


Jeffrey Walton

unread,
Apr 4, 2015, 10:54:42 PM4/4/15
to cryptop...@googlegroups.com, maricelgr...@yahoo.com
> 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; 

Jeffrey Walton

unread,
Apr 4, 2015, 11:13:32 PM4/4/15
to cryptop...@googlegroups.com, maricelgr...@yahoo.com
> 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 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.

Jeffrey Walton

unread,
Apr 5, 2015, 4:23:30 PM4/5/15
to cryptop...@googlegroups.com, maricelgr...@yahoo.com
>> 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.
The wiki documentation was updated for http://www.cryptopp.com/wiki/ChannelSwitch. It adds an SSH-style authenticated encryption example.


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

Maricel Gregoraschko

unread,
Apr 5, 2015, 11:20:16 PM4/5/15
to Jeffrey Walton, cryptop...@googlegroups.com
Jeffrey,
Thank you very much for your insights and details.
I was indeed looking to do HMAC on cipher text, not directly on clear text. I asked the question wrong.
Your code using putMessage=true was what I needed, but it's also good to know that ChannelSwitch is the equivalent of Fork.
I looked at the crash in the sample that you gave, and started by assuming there was something in HashVerificationFilter that made it send the wrong data to CBC_Encryption; I followed the data through all the hoops all the way down to AESNI_AdvancedProcessBlocks(), until I realized it was on its subkeys  parameter that the read violation was occurring. Turns out the key wasn't set:
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); //needs to be decryptor.SetKeyWithIV....

Quite an easy mistake to make with boilerplate code, and it's a bit disconcerting that the decryption class wouldn't at a minimum make a basic check that the key was set by the client, before proceeding to use it. 

>You will *always* have to touch the data twice. 

If I understand you correctly, you are saying each block of data/chunk needs to be read twice (once in memory, from there), once as input to the encryption cipher, and once as input to the hmac? That makes sense. 
I was referring to not reading it off the disk twice, e.g. in the case of doing hmac on plain text from a file, not going twice through the input stream (first to encrypt, then resetting the stream, and reading through it again for the mac). putMessage=true, or Fork/ChannelSwitch help with that.

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.




From: Jeffrey Walton <nolo...@gmail.com>
To: cryptop...@googlegroups.com
Cc: maricelgr...@yahoo.com
Sent: Saturday, April 4, 2015 11:13 PM
Subject: Re: processing same stream in parallel
> 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 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;
 
--
--
You received this message because you are subscribed to the "Crypto++ Users" Google Group.
To unsubscribe, send an email to cryptopp-user...@googlegroups.com.
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 cryptopp-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout


.


Maricel Gregoraschko

unread,
Apr 5, 2015, 11:26:15 PM4/5/15
to Jeffrey Walton, cryptop...@googlegroups.com
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!


From: Maricel Gregoraschko <maricelgr...@yahoo.com>
To: Jeffrey Walton <nolo...@gmail.com>; "cryptop...@googlegroups.com" <cryptop...@googlegroups.com>
Sent: Sunday, April 5, 2015 11:20 PM

Jeffrey Walton

unread,
Apr 5, 2015, 11:53:52 PM4/5/15
to cryptop...@googlegroups.com, nolo...@gmail.com, maricelgr...@yahoo.com
> I looked at the crash in the sample that you gave, and started
> by assuming there was something in HashVerificationFilter that
> made it send the wrong data to CBC_Encryption; I followed the
> data through all the hoops all the way down to
> AESNI_AdvancedProcessBlocks(), until I realized it was on its
> subkeys  parameter that the read violation was occurring. Turns
> out the key wasn't set:
> 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);


Dooh... thank you very much. I'm glad I put "modulo my dumb mistake" in there :) It makes it a little more palatable.

When I looked at it under GDB, I thought I was actually getting what looked like a good subkey address (0x7ffffff...). I thought the culprit was the verification filter smashing some memory due to channel confusion.

Jeff

Jeffrey Walton

unread,
Apr 5, 2015, 11:59:42 PM4/5/15
to cryptop...@googlegroups.com, nolo...@gmail.com, maricelgr...@yahoo.com


On Sunday, April 5, 2015 at 11:26:15 PM UTC-4, Maricel Gregoraschko wrote:
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!
Independent key derivation.

In pseudo code, something like:

    master_key = PBKDF(password, salt, iterations, useage)

Useage is just a label like "Master key derivation for Maricel's Algorithm". It tries to ensure master_key differs under the same parameters.

Then:

    enc_key = KDF(master_key, salt, iteration, "encryption key")
    enc_iv = KDF(master_key, salt, iteration, "encryption iv")
    hamc_key = KDF(master_key, salt, iteration, "hmac key")

Now you have your independent keys for your block cipher and hamc.


From: Maricel Gregoraschko <maricelgr...@yahoo.com>
To: Jeffrey Walton <nolo...@gmail.com>; "cryptop...@googlegroups.com" <cryptop...@googlegroups.com>
Sent: Sunday, April 5, 2015 11:20 PM
Subject: Re: processing same stream in parallel
Jeffrey,
Thank you very much for your insights and details.
I was indeed looking to do HMAC on cipher text, not directly on clear text. I asked the question wrong.
Your code using putMessage=true was what I needed, but it's also good to know that ChannelSwitch is the equivalent of Fork.
I looked at the crash in the sample that you gave, and started by assuming there was something in HashVerificationFilter that made it send the wrong data to CBC_Encryption; I followed the data through all the hoops all the way down to AESNI_AdvancedProcessBlocks(), until I realized it was on its subkeys  parameter that the read violation was occurring. Turns out the key wasn't set:
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); //needs to be decryptor.SetKeyWithIV....

Quite an easy mistake to make with boilerplate code, and it's a bit disconcerting that the decryption class wouldn't at a minimum make a basic check that the key was set by the client, before proceeding to use it. 

>You will *always* have to touch the data twice. 

If I understand you correctly, you are saying each block of data/chunk needs to be read twice (once in memory, from there), once as input to the encryption cipher, and once as input to the hmac? That makes sense. 
I was referring to not reading it off the disk twice, e.g. in the case of doing hmac on plain text from a file, not going twice through the input stream (first to encrypt, then resetting the stream, and reading through it again for the mac). putMessage=true, or Fork/ChannelSwitch help with that.

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

Jeffrey Walton

unread,
Apr 6, 2015, 12:20:47 AM4/6/15
to cryptop...@googlegroups.com, nolo...@gmail.com, maricelgr...@yahoo.com


On Sunday, April 5, 2015 at 11:20:16 PM UTC-4, Maricel Gregoraschko wrote:
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 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?
Yeah, once you know about the wiki and begin searching it, it gets a lot easier :)

Take consolation in the fact that the wiki has only been around since about 2005 or so. It was quite painful before then :)

The source code is incredibly sparsely documented, is there annotated code elsewhere? Am I looking in the wrong place?
Yes. On the Crypto++ homepage, see the link to "Manual" at the top. That's the Doxygen markup for the annotated sources. But they are brief too.
 
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.
OK, you can use PUT_RESULT here.

Or, you can tell the filter to throw with THROW_EXCEPTION. The example below should probably use THROW_EXCEPTION.

I don't believe you can use both PUT_RESULT and  THROW_EXCEPTION because there's only one sink. You have to sue the sink to recover the message, or use the sink to capture the result (true/false).

I think there's another way to jigger it with a Redirector:

    // Authenticate and decrypt data
    HashVerificationFilter hvf(hmac2,
                       new StreamTransformationFilter(decryptor,
                                                      new StringSink(recover)),
                       HASH_AT_END | PUT_MESSAGE);

    StringSource ss2(cipher, true /*pumpAll*/, new Redirector(hvf));

    if(!hvf.GetLastResult()) {
        cerr << "Failed to verify message" << endl;
        exit(1);
    }

And of course, Redirector is documented at http://www.cryptopp.com/wiki/Redirector.

Jeff

Maricel Gregoraschko

unread,
Apr 6, 2015, 10:14:53 AM4/6/15
to Jeffrey Walton, cryptop...@googlegroups.com
I was doing something like
byte* vector[ AES_CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN ];
PBKDF2( pwd, salt, iterations, out key, out key_len_above ];
Then taking the corresponding bytes from the vector to form the key, iv and mac key respectively. I took this from Botan's cryptobox.

>master_key = PBKDF(password, salt, iterations, useage)
You mean use salt + useage concatenated, as the salt parameter to PBKDF2, right?

Your approach seems to take safety (as far as keys being independent of each other), a little further, I'll go with it. I wonder how big of a difference there is. 


Thanks!


From: Jeffrey Walton <nolo...@gmail.com>
To: cryptop...@googlegroups.com
Cc: nolo...@gmail.com; maricelgr...@yahoo.com; maricelgr...@yahoo.com
Sent: Sunday, April 5, 2015 11:59 PM

Subject: Re: processing same stream in parallel

On Sunday, April 5, 2015 at 11:26:15 PM UTC-4, Maricel Gregoraschko wrote:
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!
Independent key derivation.

In pseudo code, something like:

    master_key = PBKDF(password, salt, iterations, useage)

Useage is just a label like "Master key derivation for Maricel's Algorithm". It tries to ensure master_key differs under the same parameters.

Then:

    enc_key = KDF(master_key, salt, iteration, "encryption key")
    enc_iv = KDF(master_key, salt, iteration, "encryption iv")
    hamc_key = KDF(master_key, salt, iteration, "hmac key")

Now you have your independent keys for your block cipher and hamc.


From: Maricel Gregoraschko <maricelgr...@yahoo.com >
To: Jeffrey Walton <nolo...@gmail.com>; "cryptop...@googlegroups. com" <cryptop...@googlegroups. com>
Sent: Sunday, April 5, 2015 11:20 PM
Subject: Re: processing same stream in parallel
Jeffrey,
Thank you very much for your insights and details.
I was indeed looking to do HMAC on cipher text, not directly on clear text. I asked the question wrong.
Your code using putMessage=true was what I needed, but it's also good to know that ChannelSwitch is the equivalent of Fork.
I looked at the crash in the sample that you gave, and started by assuming there was something in HashVerificationFilter that made it send the wrong data to CBC_Encryption; I followed the data through all the hoops all the way down to AESNI_ AdvancedProcessBlocks(), until I realized it was on its subkeys  parameter that the read violation was occurring. Turns out the key wasn't set:
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); //needs to be decryptor.SetKeyWithIV....

Quite an easy mistake to make with boilerplate code, and it's a bit disconcerting that the decryption class wouldn't at a minimum make a basic check that the key was set by the client, before proceeding to use it. 

>You will *always* have to touch the data twice. 

If I understand you correctly, you are saying each block of data/chunk needs to be read twice (once in memory, from there), once as input to the encryption cipher, and once as input to the hmac? That makes sense. 
I was referring to not reading it off the disk twice, e.g. in the case of doing hmac on plain text from a file, not going twice through the input stream (first to encrypt, then resetting the stream, and reading through it again for the mac). putMessage=true, or Fork/ChannelSwitch help with that.

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

Maricel Gregoraschko

unread,
Apr 6, 2015, 10:45:13 AM4/6/15
to Jeffrey Walton, cryptop...@googlegroups.com
> 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 "http://www.cryptopp.com/wiki/"".
That still won't reveal pages such as 
but a full flat list will do.


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

> Yes. On the Crypto++ homepage, see the link to "Manual" at the top. That's the Doxygen markup for the annotated sources. But they are brief too.

Looking at them they seem to be generated directly from what comments exist in the source, via a doxygen-type documentation system. There are some class diagrams that could be useful, though they're not more than what a tool like Visual Studio can generate, which is not much, given the extensive use of the "inherit from template parameter (BASE)" scheme (this is the first time I see this kind of template usage, I assume this choice of design, taking generalization to this level, is needed/useful).

Thank you!

Sent: Monday, April 6, 2015 12:20 AM

Subject: Re: processing same stream in parallel

On Sunday, April 5, 2015 at 11:20:16 PM UTC-4, Maricel Gregoraschko wrote:
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

Jeffrey Walton

unread,
Apr 6, 2015, 12:15:54 PM4/6/15
to cryptop...@googlegroups.com, nolo...@gmail.com, maricelgr...@yahoo.com


On Monday, April 6, 2015 at 10:45:13 AM UTC-4, Maricel Gregoraschko wrote:
> 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.
OK, the real estate on the home page is kind of limited, so we can't place everything on it.

Mediawiki has a couple of special pages (see the toolbox on the right) that lists all pages (http://www.cryptopp.com/wiki/Special:AllPages) and provide a random page from the wiki (http://www.cryptopp.com/wiki/Special:Random).

We also have this: http://www.cryptopp.com/wiki/Go_versus_Search, but I never thought to highlight it. Maybe the graphic should be moved to the homepage with a note about searching.
 
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.
It seems like Mediawiki's http://www.cryptopp.com/wiki/Special:AllPages is the tool for the job here.

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...
OK, I think the solution here is to put the graphic on the main page to draw attention to it with some text that highlights search.
 
>   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.
Yeah, that's a problem.

That's why I try to answer in terms of the wiki (even when a simple code snippet would do). It raises awareness for the wiki so you know where to find things.

Jeff

Maricel Gregoraschko

unread,
Apr 7, 2015, 11:31:22 AM4/7/15
to Jeffrey Walton, cryptop...@googlegroups.com
Great, it looks like what I'm asking for is already there, including a list by categories. The only thing is I never thought about clicking on "Special pages", in the main page. I'm not familiar with mediawiki and I don't know how many people are. Even those who are, would think that if there was anything of interest there, it would have been linked to from the main page.
I understand you can't have the list right on the main page, but how about an explicit link to it, other than through the generic "Special pages". E.g.: "Here is the REAL documentation: <link_to_http://www.cryptopp.com/wiki/Special:AllPages>
", also sorted by categories: <link_to_http://www.cryptopp.com/wiki/Special:Categories>



Sent: Monday, April 6, 2015 12:15 PM

Subject: Re: processing same stream in parallel
Reply all
Reply to author
Forward
0 new messages