This is making the rounds on Twitter. I think the narrative is pretty unfair to 1Password, and that they're bending over backwards to seem reasonable and attentive†.
The problem as I understand it is that 1Pw runs PBKDF2-HMAC-SHA1 twice. 1Pw stores encrypted passwords using AES-CBC. It derives a 128 bit AES key from the first run of PBKDF2, and the 128 bit CBC IV from the balance of the first and the first bits of the second. Based on that design, it appears that 1Pw believed that the secrecy of the IV would contribute to the difficulty of cracking the encrypted blob, but of course it doesn't, because the trailing bytes of the blob are known plaintext and an attacker can use the key without knowing the IV to check if their password guess is right.
This is not a great design. But it's bad in a way that wastes cycles for users. The fact that 1Pw does extra PBKDF2 work that doesn't bind on attackers don't make 1Pw meaningfully weaker than any other app that uses PBKDF2, because it was already weird that they were tapping PBKDF2 twice to begin with. A more idiomatic use of PBKDF2 in this situation would be to tap PBKDF2 once, and then expand it (say with SHA2) to 256 bits. That design, which is totally reasonable and would not be the subject of a news story, would be equivalently secure to the "flawed" approach 1Pw took.
There is another problem with the construction 1Pw uses, which is that they chose PBKDF2-HMAC-SHA1. PBKDF2 with SHA hashes are among the easiest KDFs to crack on GPUs††, because SHAx was designed to be fast in hardware. 1Pw would have been much better off with scrypt, or even bcrypt (which is still a pain to implement in GPUs). But PBKDF2 is an industry best practice; to ding someone for using it while the rest of the world still uses "salted hashes" seems unreasonable.
What's happening here, besides the echo-chamber effect, is that the implementation of the brute force cracker for this particular encrypt blob is clever. In a rush to applaud cleverness, Twitter seems to have lept to the conclusion that "clever attack" means "vulnerable target". That's usually a correct assumption, but it isn't in this case.
Corrections more than welcome.
† They deserve some kind of medal for that, by the way, because I have no dog in this fight at all and I can't seem to shut up about the unfairness of it all.
†† It turns out there's a clever way to optimize this on a GPU by precomputing the ipad/opad in HMAC, too, which sped the cracker up.
I don't see why you say that the problem is that they run it twice. As I understand it, the problem is that they use AES with an 128-bit key, and they use it in CBC mode, which gets easily defeated once you know the last plaintext.
As I can see, they had various courses of action (don't take this to mean that they were remiss in securing their product, as they used best practices everywhere):
* Use AES-256, maybe deriving the key from a first run of the KDF and the IV from a second one, although that might also make for an attack.
* Use CTR mode. Unless I'm mistaken, the attacker would then need to guess both the key and the nonce to verify the block, which is significantly higher complexity.
* Re-encrypt the last block with the IV. This way, the attacker would have to decrypt with the other 128-bit key, and would need to know both to decrypt the last block.
* Pad the beginning, rather than the end. Or, since the string is of known length, just make it a multiple of the block size, and use no padding.
I'm really a crypto novice, though, so I might be completely mistaken. That said, it's a bit too bad that they didn't spend a bit of time thinking how they would crack their own product, they might have come up with this attack and mitigated it.
At any rate, running the KDF twice isn't a problem, unless you mean that it wastes CPU cycles for no good reason. In that case, I agree.
You're not mistaken in that there are constructions they could have used that would tie both the first and the second PBKDF2 output to the whole decryption. Their construction doesn't, and that appears to have been a mistake.
But it's not a meaningful mistake, for two reasons: (1) they were being naive about how they used PBKDF2 to begin with (again: don't call it a second time to generate a key or a nonce) and the attack on their encrypted blobs still requires a brute force attack on the first output, and (2) we're discussing a minimal improvement on the complexity of an attack on their system, but there are much bigger improvements available to them if they move off PBKDF2.
But, really: deriving keys from PBKDF2 is just fine. If they had just used PBKDF2 (once!) to generate an AES key, and then used /dev/random to generate an IV, nobody would be talking about them right now.
(For what it's worth, a CTR nonce only gives you 64 more bits to play with).
I definitely agree with you on all your mentioned points, but I'm unclear on a few things:
* What do you mean that it requires a brute force attack on the first output? As I understand it, the attacker doesn't need to match all 256 bits of the derived key (only the first 128 bits), so the complexity is reduced by a lot. If those match, you can just run the KDF "properly" on the passphrase you guessed and get the rest of the bits, i.e. the IV. It thus weakens PBKDF2 to only need 2002 rounds of SHA, rather than 8000, and still allows you to decrypt the whole stream.
* If they used a random IV, they'd have to include it in the stream, which wouldn't really do anything more for security. The IV doesn't matter at all now either, but at least now it's secret. This attack doesn't use the key space of AES or the IV, though, so it's a bit moot.
* The CTR nonce would prevent the attacker from taking the 128-bit "shortcut", as they'd need all 256 bits of the derived key to decrypt the last block, which is the improvement I'm referring to.
Please correct me if I'm mistaken, I find crypto very interesting and would like to know where I'm wrong.
IVs are not really meant to be secret, IIRC. They're just meant to be different each time, to avoid getting the same cypher text if you have to encrypt another plaintext that begins with the same block.
To clarify, not that this should ever matter for you because you should never work with these primitives directly, but a CBC IV needs not only to be unique but also unpredictable (which is a different property than "secret", of course).
This would be used in a chosen plaintext attack, right? If you saw a ciphertext C1 with IV1, and you were able to choose the following Pj and predict the corresponding IVj, then you could verify whether the plaintext of C1 was P1~ by choosing Pj = P1~ XOR IV1 XOR IVj, so that Cj = C1 iff Pj = P1~. This would allow you to test likely values of P1~ from a dictionary.
Jeffrey got back to me with a way-more-reasonable-than-expected answer:
---------------------------------------------
Hi Bernardo,
I'm sorry for not getting back to you earlier. I think I answered your question elsewhere, and so failed to get to the email followup.
The Belenko and Sklyorov analysis of a large number of password managers found that many of them (including 1Password) were vulnerable to a "padding oracle" attack.
We discussed the problem the day that the report came out, and released an update to 1Password for iOS (Mac and Windows versions were not affected) within a few weeks.
The specific vulnerability (that pretty much affected everyone who used the standard cryptographic libraries) is fascinating, and I'm hoping to write more about it some day. But for the moment, please see
which includes some links to the issue and what we did about it. The key paragraph is
"The [New York Times] article cites some of the research behind Elcomsoft’s scathing review (PDF) of password managers on mobile devices, which we wrote about last March. That report did included some issues in 1Password on iOS (which we quickly addressed), but it also shows that there is enormous variation in the quality of password managers. 1Password is clearly among the best."
It is hard to stay ahead of potential threats, and we slipped up in that case so had to play "catch up" instead. Although there was never a practical threat to people's data, as developing a practical tool to exploit the vulnerability would take some time. But the design flaw certainly opened the door for people to create such tools, so we did need to get this fixed quickly.
Still we try to look toward the future in our design and defend against potential threats that don't yet exist. We should have defended against all potential chosen ciphertext attacks (CCAs) no matter how "theoretical" before the padding oracle (a type of CCA attack) was actually discovered.
I hope that helps. Please let me know if you have further questions.
Cheers,
-j
–-
Jeffrey Goldberg
Chief Defender Against the Dark Arts @ AgileBits
That's cool, but it's worth noting that was not a new attack at all. It was known for 10 years before that, and very well known for 2. Elcomsoft didn't even pretend it was new (though they didn't credit previous work or name it, oddly), they just pointed out that 1Password was vulnerable to it.
It was only around the time of the Elcomsoft report that we (at AgileBits) became aware of the importance of authenticated encryption. The theorems had been around for more than a decade, but news didn't filter down to application developers (or if it did it went in one ear and out the other). This is a big problem in general.
Part of the problem stems from the fact that application developers are also (correctly) reluctant to use things that aren't in standard libraries and that don't have standards behind them. Even today, Apple's CommonCrypto offers no authenticated encryption modes, and only documents CBC and ECB. (CTR is available, but not documented as such.) And back to the current issue, we would have moved to scrypt from PBKDF2 already if it were readily available in well-reviewed implementations.
But also this stuff is hard (fun, but hard). And not every development team is going to have the expertise on board to really follow this stuff. They are just going to go with what's in the most easily accessible libraries, and if we are lucky, they won't use their encryption keys as IVs for CBC.
Lots of people are talking about how to improve the situation. I'm "cautiously optimistic".
The problem as I understand it is that 1Pw runs PBKDF2-HMAC-SHA1 twice. 1Pw stores encrypted passwords using AES-CBC. It derives a 128 bit AES key from the first run of PBKDF2, and the 128 bit CBC IV from the balance of the first and the first bits of the second. Based on that design, it appears that 1Pw believed that the secrecy of the IV would contribute to the difficulty of cracking the encrypted blob, but of course it doesn't, because the trailing bytes of the blob are known plaintext and an attacker can use the key without knowing the IV to check if their password guess is right.
This is not a great design. But it's bad in a way that wastes cycles for users. The fact that 1Pw does extra PBKDF2 work that doesn't bind on attackers don't make 1Pw meaningfully weaker than any other app that uses PBKDF2, because it was already weird that they were tapping PBKDF2 twice to begin with. A more idiomatic use of PBKDF2 in this situation would be to tap PBKDF2 once, and then expand it (say with SHA2) to 256 bits. That design, which is totally reasonable and would not be the subject of a news story, would be equivalently secure to the "flawed" approach 1Pw took.
There is another problem with the construction 1Pw uses, which is that they chose PBKDF2-HMAC-SHA1. PBKDF2 with SHA hashes are among the easiest KDFs to crack on GPUs††, because SHAx was designed to be fast in hardware. 1Pw would have been much better off with scrypt, or even bcrypt (which is still a pain to implement in GPUs). But PBKDF2 is an industry best practice; to ding someone for using it while the rest of the world still uses "salted hashes" seems unreasonable.
What's happening here, besides the echo-chamber effect, is that the implementation of the brute force cracker for this particular encrypt blob is clever. In a rush to applaud cleverness, Twitter seems to have lept to the conclusion that "clever attack" means "vulnerable target". That's usually a correct assumption, but it isn't in this case.
Corrections more than welcome.
† They deserve some kind of medal for that, by the way, because I have no dog in this fight at all and I can't seem to shut up about the unfairness of it all.
†† It turns out there's a clever way to optimize this on a GPU by precomputing the ipad/opad in HMAC, too, which sped the cracker up.