Thu, May. 19th, 2011, 09:16 am
Practical Cryptography Corrected
The book 'Practical Cryptography' is perfectly good for giving an overview of basic concepts in cryptography, but its immediate practical advice to implementers is not terribly to the point or accurate. Here is much more to the point and accurate advice.
- For a block cipher you should use AES-128. If you don't understand your protocol well enough to know whether there are birthday attacks on your keys, you have bigger issues. (Shame on Schneier for still trying to revisit the AES design competition by yammering on about Twofish.)
- For an encryption mode, you should always use CTR, and always use a nonce of zero, and never reuse keys.
- For a hash function, you should use sha-256 until the winner of the sha-3 design competition is announced, and then you should use sha-3.
- You should always do encryption as a layer outside of authentication.
- For entropy, you should always do whatever the Python os.urandom() call does on the local platform.
- For a data format, you should use JSON. (Not XML!)
- For an RSA exponent, you should always use 2. Technically that's Rabin-Williams, and requires slightly different implementation, but that actually works in its favor. Rabin-Williams has a reduction to factoring, RSA does not.
- You should never use the same key for both encryption and authentication. If you need both encryption and authentication, you should use two keys. One for encryption, and one for authentication.
- If you're going to be using RSA, you should learn about encoding for it! This is by far the most historically error-prone part of crypto protocols, and Practical Cryptography bizarrely doesn't even mention it as an issue.
- You should not parameterize your protocols! That just creates compatibility problems. If necessary you can parameterize it by having two values, one good for the next twenty years, and one good until the end of time, but key sizes have gotten big enough that skipping that first one should be the default.
Maybe someday Schneier will write a book which I can recommend to people who are getting started in cryptography, but I'm not holding my breath.
Are you a good programmer? Try this coding challenge
I certainly agree that Practical Cryptography feels outdated, and readers should be warned about the problematic parts. Here are a few thoughts and questions from a theoretical crypto POV:
For an encryption mode, you should always use CTR, and always use a nonce of zero, and never reuse keys.
I'm interested to hear more about why this is true. Certainly there are times when you want to reuse keys and use modes that provide more security than that :-).
You should always do encryption as a layer outside of authentication.
It sounds like you are suggesting the opposite of what you should do, which is encrypt first, and then authenticate the ciphertext. Authenticating the plaintext before encrypting is not safe.
For an RSA exponent, you should always use 2. Technically that's Rabin-Williams, and requires slightly different implementation, but that actually works in its favor. Rabin-Williams has a reduction to factoring, RSA does not.
I think suggesting that practitioners dig into implementations of the number-theoretic algorithms (as would be necessary here) is likely to lead to exploitable bugs. Moreover, even a proper implementation of Rabin-Williams would not increase security in practice, unless the sky falls and we find algorithms for inverting the RSA trapdoor function that do something other than factoring. And what's worse is that in practice you'll be using a padding scheme like PKCS#1v1.5, which means the reduction no longer applies. Even if you used OAEP instead, the reduction would be in the random oracle model, further clouding the significance of a reduction to factoring vs RSA inversion.
This is all ignoring the fact that low-exponent (e=3) RSA has lead to vulnerabilities in the past...
You should never use the same key for both encryption and authentication. If you need both encryption and authentication, you should use two keys. One for encryption, and one for authentication.
This is good advice, unless you're using an authenticated encryption mode like GCM. It would be good to be more complete on when it applies.
Thu, May. 19th, 2011 11:36 pm (UTC)
CTR is the simplest, easiest to analyze and least error-prone mode there is, and doesn't require padding and allows for random access. The added security of other modes is mostly fallacious, and ones where it isn't are way too complicated for me to feel comfortable using them.
I don't know what your issue is with encrypting outside of authenticating is. If nothing else, it leaks authentication information which one may want to keep secret, and this is one case where I'm agreeing with Practical Cryptography, just making the recommendation more straightforwardly. My simplest explanation for this is that doing encryption on the outside allows for clean layering of the software implementation, where the other way does not.
RSA exponents more than 2 are at least twice as slow, which should not be simply ignored for speculative reasons. Encoding issues should be dealt with by using a good encoding, which is a dangerous issue in any case, as I explained.
I might start recommending GCM in the future, after more chips support in and I've spent some time analyzing its implications. For the time being simply using a secure hash and CTR is the reasonable conservative approach.