Cross-platform AES data format and implementations

Why Not Scrypt?

“NeXT Steve” asks a very good question in RNCryptor Issue #110:

Could you implement Scrypt for this function ?


This isn’t a comment on the security of scrypt. It isn’t a comment on its developer, Colin Percival, who was a major influence in my developing RNCryptor. I like scrypt. I hope it becomes popular. I have a great deal of respect for Colin.

RNCryptor will not support scrypt (or bcrypt) for the likely future because it’s not generally available in cryptographic toolkits. In particular, it’s not available in any of the toolkits that the current RNCryptor implementations rely on: Common Crypto, SecretKeyFactory, Crypto.Protocol.KDF, SJCL, and OpenSSL. I hope to provide implementations in more languages soon.1 I expect almost all of them to have SHA-2, HMAC, AES-CBC, and PBKDF2 readily available, and I expect few of them will have scrypt or bcrypt in their most popular or built-in crypto libraries.

A primary goal of the RNCryptor format is to be easy to use and easy to implement on a wide variety of platforms. Its entire point is to make “doing AES correctly” the same as “doing AES easily.” It avoids creating any more dependencies than necessary, and it strongly avoids requiring implementers to write cryptographic primitives. It avoids adding options that make implementations more complicated.2 My ideal is that a basic implementation of RNCryptor should be possible in a couple hundred lines of code. The current Ruby implementation is 80 lines including comments, and includes almost no math. That’s what I want it to look like.

This goal means I pick from readily available primitives to build a secure implementation. If I had my pick of primitives, I would almost certainly use an authenticated mode like CCM rather than CBC.3 But there are no authenticated modes that are commonly available. So RNCryptor uses AES-CBC+HMAC.

Thomas Pornin, probably my favorite contributor to crypto.stackexchange.com, sums it up well discussing bcrypt:

NIST has issued Special Publication SP 800-132 on the subject of storing hashed passwords. Basically they recommend PBKDF2. This does not mean that they deem bcrypt insecure; they say nothing at all about bcrypt. It just means that NIST deems PBKDF2 “secure enough” (and it certainly is much better than a simple hash !)….

While I recommend bcrypt, I still follow NIST in that if you implement PBKDF2 and use it properly (with a “high” iteration count), then it is quite probable that password storage is no longer the worst of your security issues.While I recommend bcrypt, I still follow NIST in that if you implement PBKDF2 and use it properly (with a “high” iteration count), then it is quite probable that password storage is no longer the worst of your security issues.

PBKDF2 is sufficiently secure, and it’s the most commonly available KDF. So it’s what RNCryptor is going to rely on for the foreseeable future.

  1. On the short-term radar: C#, C++, Scala (also Akka), Haskell. Others of medium-term interest: VB, Lua, Go, D. As always, please contact me if there’s a language you’re interested in helping with. RNCryptor is designed to be easy to implement and I can walk you through it.

  2. Currently there is just one option: use a password or a raw key. I often debate whether it’s worth having that option (and several implementations do not support raw keys). In the next release of the spec, I plan to add a second option, number of PBKDF2 rounds, because it has been of such high demand and is absolutely necessary to implement RNCryptor in JavaScript.

  3. I know Colin Percival’s arguments for preferring encrypt-than-mac rather than authenticated encryption (AE). While I understand where he’s going with the argument, I believe it’s much easier for downstream developers to use AE correctly. This is why I’ve also come to disagree with his stance on CTR, even though that’s what I used in the original version of RNCryptor. It’s just too easy to do CTR wrong, and then it’s totally insecure. If you mess up CBC a little bit, it doesn’t completely fall apart. CBC also happens to be the most commonly available mode, so it’s the strong favorite for RNCryptor anyway.