Log in

No account? Create an account

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.

Thu, May. 19th, 2011 09:08 pm (UTC)

You should always do encryption as a layer outside of authentication.

Strongly disagree.

Authenticate-then-encrypt (AtE) is subject to attacks that encrypt-then-authenticate (EtA) is not. How practical those attacks are depend on exactly what you're using for your encryption, but they can occur surprisingly often, and you don't want to have to worry about them.

The most prevalent class of such attack (in my opinion) is when you've got a (possibly public-key) encryption system that isn't reaction resistant. The encryption might be somewhat homomorphic, in that the adversary can modify the ciphertext in such a way as to make it come out to the same plaintext some of the time, and a different plaintext (or \bottom) some of the time. Then the inner authentication will fail, and the adversary will know which happened. Lattice-based crypto often has this problem, as does McElice (see our 1999 paper on this). Other encryption systems may have this or similar problems, as protecting against this isn't generally something that's a design goal of semantically secure encryption. (If your encryption is IND-CCA2, you're safe, but then you've basically got the authentication built in, anyway.)

Authenticating the ciphertext avoids the whole issue.

Of course, it may have its own issues, if you're using signatures (and not MACs) for authentication, and you want, say, to hide the information of who's signing the message. If you have complex requirements like that, though, you might think twice about designing the crypto protocol yourself.

Thu, May. 19th, 2011 09:25 pm (UTC)

RSA in particular has vicious attacks when you do authentication checks the wrong way, but that's really an argument in favor of doing authentication properly rather than changing the order, particularly because checking that high order byte is something a naive implementer might do anyway.

That more complicated stuff you mention really shouldn't be done by people who don't already know these issues well, and my advice is for people who don't really know what they're doing by are trying to do something simple (which still might not be a good idea, but they're better off with good advice than without).