NaCl is a new crypto library, courtesy of Dan Bernstein of qmail fame and Tanja Lange. After my series of posts on why crypto libraries have seriously hurt web security by offering an API that is too low-level, I was pleased to find NaCl’s main interface is high-level. In addition to the kind of fanatical attention to security you can expect from DJB, it also has his unique (some would say quirky) viewpoint.
On a related note, I’m sorry to say I have to withdraw my recommendation of Google Keyczar. It has had another vulnerability announced, this time in the random source for the python library. This is exactly the same attack against DSA I described previously. I may reconsider this decision as it matures.
There’s a lot Keyczar gets right. Its high-level API and key management make a lot of sense. Up until recently, there haven’t been many high-level libraries I could recommend. Gutmann’s cryptlib is probably the best one. It has been around a while and is implemented in C with multiple language bindings. It is covered by the Sleepycat license, so it works like the GPL or you can pay for closed-source use. GPGME provides well-reviewed crypto with the simple PGP usage model. However, it only offers a C API. It also works by forking the command-line gpg underneath, something that may bother some developers. It is covered by the LGPL license.
While cryptlib and GPGME have been around a while, I have not personally reviewed either of them and can’t vouch for their implementation security. When I found the timing attack in Keyczar’s HMAC verification, I took a brief look around. It seemed ok overall, but I did not do a thorough review. I was so glad to see another high-level library that I included Keyczar along with cryptlib and GPGME as a good alternative to implementing your own crypto in a recent talk. I should have emphasized that while these libraries are taking the right approach, we need much more thorough reviews by cryptographers before standardizing on them. Keyczar, as the newest library of those three, deserved a note that it especially needed review.
NaCl is the latest entry on the scene and it shows a lot of promise. Take a moment to read its design features. The code is public domain. It offers a set of high-level functions such as:
- Public-key authenticated encryption: establish a shared key with an authenticated partner, encrypt, and integrity-protect each message.
Analogy: the SSL protocol - Secret-key authenticated encryption: encryption and integrity protection for messages, using a pre-selected secret key.
Analogy: IPSEC with encryption and authentication using a pre-shared key - Secret-key authentication: integrity protection for a message using a pre-selected secret key
Analogy: HMAC-protected cookies - Other low-level primitives such as a stream cipher and hash.
There are some good things to be excited about here. The design is extremely high-speed, although that isn’t my personal priority. The high-level APIs are good but not perfect. For example, the caller is expected to specify a nonce and set certain bytes to zero for crypto_box. This is a little too much control for a high-level API. It might be better if NaCl created its own nonce using its PRNG (/dev/urandom, actually), and then focused on making sure it was seeded well.
The design and implementation security, as expected for DJB, is excellent. (Note that I have not done a thorough review and thus cannot yet recommend it.) For example, he focuses on side channel resistance, creating a non-branching scalar multiplication routine and an API for comparing secrets that resists timing attacks. Also, his design choice of using ECDH, a stream cipher, and a MAC algorithm to implement crypto_box fit together well.
However, that’s where the quirkiness comes in. As with qmail, DJB has a really unique way of doing things. The default ECDH implementation uses Curve25519, the stream cipher is Salsa20, and the authenticator is Poly1305. All of these are primitives designed by DJB in the past four years. If it wasn’t DJB, you’d think I was crazy to even consider a library that implements all new ciphers and constructions. Even though I respect him and these may turn out to be good choices, four years is not enough time to review all of these to be certain they are sound. This will limit NaCl’s appeal until more standard ciphers are available.
While NaCl is a good start, here’s what is missing before it can be more widely adopted:
- Language bindings: NaCl is C-only for now and needs at least Java, python, and C# bindings
- More standard crypto primitives: NIST P-256 or other curves, AES, and SHA2-HMAC
- Signature API: ability to do public-key signatures
Since all these items are marked TODO, it’s clear that Dan recognizes the need for them as well. Perhaps NaCl will mature into the library of choice in the future. If you’re a cryptographer and have a chance to review it, please publish your findings. If you’re a developer, how about contributing language bindings?
On a side note, I’m convinced that the right way to create a crypto library is to do a single implementation in C with architecture awareness (e.g., cache layout, some assembly language) and then offer language bindings. This is the route NaCl and cryptlib took. It’s nearly impossible to prevent side channel attacks when your crypto is implemented in a high-level language.
I’d like to encourage more external review of Keyczar from the community at large. The DSA bug was avoidable and something I missed when reviewing the Python implementation. More eyes on the code would have probably caught it. Most of Keyczar had to be rewritten from scratch in order to open source it, and now there is a C++ implementation that was written by an external contributor. So there is a lot of new code that needs more scrutiny.
I’m interested in checking out DJB’s library. I’ve always been impressed with his high-performance implementations.
Steve, thanks for commenting. I do think it needs more review. Hopefully it gets more eyes and becomes more robust. I still like Keyczar and its approach, I just needed to emphasize it’s not a mature implementation yet.
Another thing often missing from these high level libraries is an implementation of cipher-set negotiation. This will become important 5 or 10 years down the track when we decide we want to phase out an old, broken algorithm from our app – if there’s no cipher-set negotiation then we have no choice but to have a flag day when we upgrade every client and server together. In many cases that would be enough to put the whole thing into the too-hard basket, which would not be good for security.
kme, yes, migration is an issue both in terms of rolling keys and ciphers (as you mention). I don’t think most people need better cipher suite negotiation though. It’s more of a policy thing. The whole business of SSL certs is “pay $ to get the warning to go away”. So what if sites that still used MD5 certs generated a warning in IE 8+? You have financially-assisted cipher-suite upgrades. :-)
I was thinking more in terms of bespoke applications using some homegrown non-SSL protocol (which seems to be more what NaCL is aimed at). These high level libraries will help developers get the crypto right, which is great, but if they’re still writing their own cipher suite negotiation, then half the time it’ll be vulnerable to a version-downgrade attack.
kme, absolutely a good point. You don’t want to allow the developer to build a protocol that says “use crypto_box_foo() or crypto_box_bar()”, based on an unprotected field.
“and the authenticator is Poly1305.”
Link here is broken.
Thanks, it is fixed now.