Summary: If there is any chance that your RNCryptor passwords include multi-byte characters (Chinese, for example), you really need to upgrade to RNCryptor 2.2 when it comes out this week.
I hate it when I do stupid things. But then you all get to learn something, so luckily some good can come of my shame. Please learn something so this isn’t all for naught.
int result = CCKeyDerivationPBKDF(keySettings.PBKDFAlgorithm, // algorithm password.UTF8String, // password password.length, // passwordLength ...
I have had this bug since I first wrote this code for iOS 5 PTL, and it’s horrible. The problem, if you haven’t seen it yet, is that
-length returns the number of characters in
password, not the number of bytes. In many languages you can get away with that, but not in multi-byte languages like Chinese.
So what happens when someone uses the password “中文密码”?
password.UTF8String returns 8 bytes, but
password.length returns 4. So we truncate this password down to “中文” (2 characters, 4 bytes) and that’s what we use. That means later, you can decrypt this with anything that’s half-right. “中文xx” is good enough.
The fix is simple. You can either use
-lengthOfBytesUsingEncoding:, or you can create an
-dataUsingEncoding:. I prefer the latter, and that’s how I’ve fixed it.
The tricky bit is maintaining backward compatibility. It requires bumping the file version so we can tell which approach we used. But all of that is done and checked in.
Right now, I’m working with Curtis Farnham to make sure that the PHP version is compatible with the latest changes. This bug convinced me to finally write some test vectors so we can keep all the language implementations consistent. Once I get that straightened out, I’ll post a new version of RNCryptor (or by the end of the week either way).