Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

1Password, PBKDF2, & Implementation Flaws

…or “Crypto Is Hard, Vol. 479”

Earlier today a tweet about a new feature for oclHashcat-plus started a truly interesting debate on Twitter over the implications. The new feature is the ability to crack 1Password keychain files – at an impressive 3 million passwords per second.

To achieve this speed, two optimizations were used – the first is in precomputing ipad and opad for SHA1-HMAC, this effectively cuts the number of SHA1 calls in half. This is clever, but not the part I’m interested in, it’s the second optimization that I find interesting.

1Password uses AES128, in CBC mode to encrypt data – and it’s the design of CBC that enables the next optimization. If you have the wrong IV when you decrypt in CBC mode it corrupts the first block – but only the first block, the rest will be fine. It’s this fact that seems to have been overlooked when 1Password was designed.

The final encryption key is derived from the user’s password via PBKDF2. They generate a 320bit key (so two blocks or four calls to SHA1 after the precompute optimization); of those 320 bits, 128 bits go into the encryption key, another 128 bits go to the IV. For 1Password to work, it needs both the key and the IV – but attackers don’t.

An attacker can look at later blocks to see if they are valid and ignore the first block, by ignoring the IV generation and the first encrypted block, the number of calls to SHA1 is again cut in half.

To their credit, Jeffrey Goldberg of AgileBits (the maker of 1Password) responded very quickly and provided details about what they are doing to address it, and joined in a very open discussion about the impact of how this was implemented. Depending on who you ask, this ‘flaw’ costs either 1 or 2 bits of entropy.

For the end user, it means that an attacker only needs to perform 50% of the SHA1 calls that the 1Password software needs (maybe only 25%, depending on how optimized the 1Password code is). When it comes to password cracking, that certainly seems less secure than what was intended. As flaws go it could be far worse, but it’s likely less secure than intended.

And finally, after all of this, we come to the point:

Crypto is hard, even for smart people.

It’s so easy to accidentally introduce weaknesses like this – everything looks right, but because of how they used PBKDF2 in combination with AES128-CBC, the end result is weaker than was intended. It’s specific, fairly obscure (to many at least), details of how these two algorithms work, and how they were used together that led to this flaw.

AgileBits has made a lot of good decisions, and in general at least, seems to know what they are doing. I certainly don’t mean to beat up on them, they’ve handled this very well and the issue is fairly small. I applaud them for discussing this so openly, it’s hard to do – I know that from personal experience.

This should serve as a great example of why any new crypto implementation needs to be expert reviewed to make sure that it’s right. Nobody gets it right every time, every code base needs to be reviewed, this could (but doesn’t have to) happen to you.

Adam Caudill


Related Posts

  • 1Password 8 Early Access: Security, Comments, & FAQs

    A few days ago, 1Password (my employer) released the first preview of the new application for macOS. The response has been rather dramatic. The release was followed by an excellent blog post by Michael Fey explaining the story of how we got here, and some of the decisions that were made in the process. I’d like to now to a few minutes to answer some questions, provide some insight, and share my thoughts on this release.

  • Hash Storage: Make Attackers Work

    So you hash your passwords? Good. Do you salt? That’s good. Do you use a strong hashing algorithm (PBKDF2/bcrypt/scrypt)? Great! But how do you store the hashes? What happens when you get hit with a SQL injection attack? I’m a big believer in defense in-depth – not that marketing garbage about stacking layers of blinky-light boxes, but using techniques to add extra work for an attacker. You might not be able to stop every attack, but the more work they have to do, the better the odds they won’t get everything they want.

  • Breaking the NemucodAES Ransomware

    The Nemucod ransomware has been around, in various incarnations, for some time. Recently a new variant started spreading via email claiming to be from UPS. This new version changed how files are encrypted, clearly in an attempt to fix its prior issue of being able to decrypt files without paying the ransom, and as this is a new version, no decryptor was available1. My friends at Savage Security contacted me to help save the data of one of their clients; I immediately began studying the cryptography related portions of the software, while the Savage Security team was busy looking at other portions.

  • Ruby + GCM Nonce Reuse: When your language sets you up to fail…

    A couple hours ago, Mike Santillana posted to oss-security about a rather interesting find in Ruby’s OpenSSL library; in this case, the flaw is subtle – so much so that it’s unlikely that anyone would notice it, and it’s a matter of a seemingly insignificant choice that determines if your code is affected. When performing AES-GCM encryption, if you set the key first, then the IV, and you are fine – set the IV first, you’re in trouble.

  • Testing for SWEET32 with YAWAST

    Testing for SWEET32 isn’t simple – when the vulnerability was announced, some argued that the best solution was to assume that if a TLS server supported any of the 3DES cipher suites, consider it vulnerable. The problem is, it’s not that simple. On my employer’s corporate blog, I wrote about practical advice for dealing with SWEET32 – and pointed out that there are ways around the vulnerability, and some are quite simple.