Crypto++ 5.0 update

42 views
Skip to first unread message

Wei Dai

unread,
Aug 2, 2002, 2:06:06 PM8/2/02
to crypto...@eskimo.com
The final drop of Crypto++ 5.0 to the FIPS 140 testing lab is scheduled
for Sept 2. So if you have any tests you want to do, or suggestions or bug
reports please make them with that date in mind. So far I have received
two bug reports for the beta, one in the benchmarks code, another in the
FIPS required power-on self test.

Also, I've personally rewritten IDEA and HAVAL to remove the copyrighted
code, so Crypto++ 5.0 should not have any kind of copyright problems.

Anyone have comments on the new interfaces? Do you like them, dislike
them, not care?

Chris Newcombe

unread,
Aug 2, 2002, 5:41:44 PM8/2/02
to Wei Dai, crypto...@eskimo.com

>> Anyone have comments on the new interfaces? Do you like them, dislike
them, not care?

Absolutely we care! I'd like to say many thanks again for the huge amount
of work and continuing support and improvements on your library - it's an
achievement that most commercial vendors can't emulate (sadly).


IMO, SimpleKeyingInterface looks great (it will let me remove my own
per-encryptor SetIV() hacks from 4.2), but I haven't had time to upgrade my
apps to try 5.0 yet.

I do have an efficiency concern for my server apps; the "take ownership of
attached sink" aspect of the filter interface (e.g. StringSource) means that
decrypting a message requires 2 calls to global operator new to construct a
throwaway source object, which is a huge per-message overhead on high-load
servers. i.e. decryption code looks like this (even using a cached keyed
decryption object)...

StringSource aesDecryptionSource
(
pEncryptedMsgBody,
u32SizeOfEncryptedMsgBody,
true, // pump all data immediately
new CBCPaddedDecryptor
(
m_AES128Decryption,
pBuffered_aesIV,
new ArraySink
(
pDestBuffer,
uSizeOfDestBuffer
)
)
);

To avoid the overhead I would like to be able to set this up just once
(actually as part of a struct in thread local storage; one instance for each
thread in my server's worker-thread pool).

But to do that I need to be able to...

1. Reset the StringSource to new source pData,Size, and so be able to call
PumpAll() to decrypt the new message.
2. Reset the pDestination,Size of the ArraySink.
3. Reset the IV of the CSCPaddedDecryptor (in my case the the Decryption
object (key) stays the same, but other users may want to change that too).

Sounds like v5.0 makes 3 possible, but not 1 or 2 (?)

It's easier to avoid the overhead for encryption because it's not wrapped in
a Source filter. I wrote my own SimpleBuffer class to use with
StringSinkTemplate so I can redirect its output. (This means I don't really
need point 2 above, but it would be nice if other users didn't have to
reimplement this). So the 'encryption' part of my thread-local-storage
struct comnstructor looks something like:

/*AESEncryption*/ m_AES128Encryption( pKey, uSizeOfKey ),
/*aes128IV_t*/ m_aesIV,
/*CSimpleBuffer*/ m_SimpleEncryptionBuffer,
/*CBCPaddedEncryptor*/ m_Encryptor
(
& m_AES128Encryption,
m_aesIV,
new StringSinkTemplate< CSimpleBuffer >
(
m_SimpleEncryptionBuffer
)
)

And I can redirect the output with:

pWorkerThreadCtxt->m_SimpleEncryptionBuffer.Set( pBuffer, pBuffEnd );

.. and then simply start Put()'ing data into m_Encryptor.

(As I said I hacked a SetIV() method into CBCPaddedEncryptor too.)

So I guess really I am asking for the ability to reset existing StringSource
objects. I was planning on adding that myself, but I thought I'd mention
this at 'interface-change' time as other users (writing servers) may need
the same thing. In which case the ability to reset ArraySink would be good
too (I don't want to use StringSink because I need to avoid the subsequent
copying of the processed data.)

I know it's kind of a trivial request -- just shows how well designed the
rest of the library is :)

Many thanks,

Chris

Rickey Braddam

unread,
Aug 2, 2002, 4:31:15 PM8/2/02
to crypto...@eskimo.com
Hello again, Dr. Wei Dai. Hope this finds you well. I have a question or two
regarding Blowfish... relatively unimportant, though.

Neither your implementation nor Eric Young's (SSLEAY/OpenSSL) check or
ensure that the key used is less than or equal to 56 bytes (448 bits) as
required in the specification. Doesn't this make it non-compliant with the
specification? It wouldn't affect anything until keys longer than 56 bytes
differing after the 56th byte were used, though.... Personally, I like the
idea of longer (72 byte) keys being available, and have actually used
Blowfish with 20 rounds and full length keys (88 bytes).

Have you considered trying to use Eric's Blowfish code? His implementation
using macros seems to be substantially faster than your c/c++ code.... and
has some assembly language code, although I'm not sure the asm adds that
much. His code appears (to me) to be freely useable as long as credit is
given him for his work.

Would you consider adding benchmarks using byte arrays, secure byte blocks,
strings, etc, with multiple block data lengths? Your benchmarks and
validation code are my primary source of examples of the use of CryptoPP.
I'd think additional benchmarks might also be more realistic, including
blocking, deblocking, and padding issues.

Sorry I don't have anything to contribute about the new interface, I'm
working on a large (for me) project and don't want to take the time to
figure out what to change in the project.

Please don't think of this as complaining, I'm deeply grateful for the
effort you've made and your generosity.

Rick


Wei Dai

unread,
Aug 2, 2002, 6:10:23 PM8/2/02
to Chris Newcombe, crypto...@eskimo.com
On Fri, Aug 02, 2002 at 02:44:49PM -0700, Chris Newcombe wrote:
> 1. Reset the StringSource to new source pData,Size, and so be able to call
> PumpAll() to decrypt the new message.
> 2. Reset the pDestination,Size of the ArraySink.
> 3. Reset the IV of the CSCPaddedDecryptor (in my case the the Decryption
> object (key) stays the same, but other users may want to change that too).
>
> Sounds like v5.0 makes 3 possible, but not 1 or 2 (?)

Thanks for your feedback. 1 is not necessary, because you can avoid
using StringSource and just call Put() on the CBCPaddedDecryptor
directly (or in 5.0 the StreamTransformationFilter). 2 is possible in 5.0.
Call Initialize() on ArraySink with a value named "OutputBuffer" of
type ByteArrayParameter, like this:

pSink->Initialize(MakeParameters("OutputBuffer", ByteArrayParameter(buffer, length)))

Chris Newcombe

unread,
Aug 2, 2002, 6:21:06 PM8/2/02
to Wei Dai, Chris Newcombe, 'cryptopp-list@eskimo.com '

>> you can avoid using StringSource and just call Put() on the
CBCPaddedDecryptor directly (or in 5.0 the StreamTransformationFilter).

Duh - thanks :) All the examples I've seen use StringSource, so I just went
blindly ahead...


>> Call Initialize() on ArraySink with a value named "OutputBuffer" of
type ByteArrayParameter, like this:
pSink->Initialize(MakeParameters("OutputBuffer", ByteArrayParameter(buffer,
length)))

I like the new variable keyword parameters stuff -- but could you tell me
what the overhead is? If it's a std::map (or indeed anything that does
dynamic allocation) then it's not really a viable alternative in my server
situation. (Fortunately my SimpleBuffer class took about 30 seconds to
write, so it's not a problem really).

But thanks for pointing it out (and sorry I didn't spot it myself).

Chris


-----Original Message-----
From: Wei Dai

Wei Dai

unread,
Aug 2, 2002, 6:35:43 PM8/2/02
to crypto...@eskimo.com
On Fri, Aug 02, 2002 at 03:31:02PM -0500, Rickey Braddam wrote:
> Neither your implementation nor Eric Young's (SSLEAY/OpenSSL) check or
> ensure that the key used is less than or equal to 56 bytes (448 bits) as
> required in the specification. Doesn't this make it non-compliant with the
> specification? It wouldn't affect anything until keys longer than 56 bytes
> differing after the 56th byte were used, though.... Personally, I like the
> idea of longer (72 byte) keys being available, and have actually used
> Blowfish with 20 rounds and full length keys (88 bytes).

The Blowfish key setup routine is able to make use of keys up to 72 bytes
(for 16 round Blowfish) so that's why I set 72 as the max key length. But
you're right, the Blowfish paper does say 448 bits is the max, so I'll go
ahead and change the it. Thanks.

BTW, if you haven't noticed, the min and max keylengths of each cipher are
set in .h files, like this:

struct Blowfish_Info : public FixedBlockSize<8>, public
VariableKeyLength<16, 1, 56>, public FixedRounds<16>
{
static const char *StaticAlgorithmName() {return "Blowfish";}
};

So for Blowfish, VariableKeyLength<16, 1, 56> means default key length is
16, min is 1, and max is 56. The min and max values are used to check each
input key at runtime.

> Have you considered trying to use Eric's Blowfish code? His implementation
> using macros seems to be substantially faster than your c/c++ code.... and
> has some assembly language code, although I'm not sure the asm adds that
> much. His code appears (to me) to be freely useable as long as credit is
> given him for his work.

How much faster is it? Make sure you're comparing with the same compilers
and options. However at this point I don't think it makes sense to try to
optimize Blowfish much more since AES is the new standard and it and many
of the other AES candidates in Crypto++ are faster and more secure than
Blowfish.

> Would you consider adding benchmarks using byte arrays, secure byte blocks,
> strings, etc, with multiple block data lengths? Your benchmarks and
> validation code are my primary source of examples of the use of CryptoPP.
> I'd think additional benchmarks might also be more realistic, including
> blocking, deblocking, and padding issues.

I'll put that on my todo list. Thanks.

Wei Dai

unread,
Aug 2, 2002, 6:51:01 PM8/2/02
to Chris Newcombe, 'cryptopp-list@eskimo.com '
On Fri, Aug 02, 2002 at 03:24:10PM -0700, Chris Newcombe wrote:
> I like the new variable keyword parameters stuff -- but could you tell me
> what the overhead is? If it's a std::map (or indeed anything that does
> dynamic allocation) then it's not really a viable alternative in my server
> situation. (Fortunately my SimpleBuffer class took about 30 seconds to
> write, so it's not a problem really).

MakeParameters() doesn't use any dynamic allocation unless you pass
objects that use dynamic allocation (like an Integer). The parameter names
are passed as const char *. The main overhead is the linear search through
the parameter names using string comparisons. So if you pass 100
parameters it would cause 100*100 = 10000 string comparisons to occur. If
you need to pass that many parameters regularly you may want to do a new
implementation of the NameValuePairs interface using std::map.

Reply all
Reply to author
Forward
0 new messages