7 ms·
TL;DR For random-seek block encryption, don't use XTS, use CTR. It's simple. I like simple maths and code, it's less to screw up and less for implementations
by midas007 12y ago
TL;DR For random-seek block encryption, don't use XTS, use CTR.
It's simple. I like simple maths and code, it's less to screw up and less for implementations to screw up. For example, I don't trust EC or GCM, even if some people thinks they're the new hotness, because complexity creates more opportunities for obfuscation and puts the code further out of reach of the already few eyeballs actually (or not) looking at it.
Maybe 'cpervica explain why
- tptacek 12y agoWhat? No. Don't do that.
- ronaldx 12y agoThis is why you should never tell people what not to do, without also telling them what they should be doing ;)
- midas007 12y ago? What's wrong with CTR? CTR is basically an OTP. Being OTP, encryption and decryption are basically the same construction (thank you XOR). cipherblockdata = blockcipher(key, nonce . block #) ^ plainblockdata plainblockdata = blockcipher(key, nonce . block #) ^ cipherblockdata If MAC is needed, that can happen after encrypting, before decrypting. (Needed if bytes traverse network, but maybe not for local disk or file encryption unless.) Edit fixed my maths:
- tptacek 12y agoCTR is not a one-time pad. Read the article: it discusses using CTR for disk encryption.
- midas007 12y agoPretty hilariously wrong, and you know it. Supposed OTP constructions are defined as e(i) == E(...) ^ m(i) m(i) == D(...) ^ e(i) where E(...) = D(...) and where ... doesnt contain any of the following e(j) for any j m(k) for any k j and k in same domain as i Then, take a look at CTR... CTR is E(i) = blockcipher(key, nonce . i) and D(i) = E(i) e(i) == blockcipher(key, nonce . i) ^ m(i) m(i) == blockcipher(key, nonce . i) ^ e(i) (i == counter, since it's the same in this example where counter and blocks start at the same number) Therefore CTR is an OTP.
- lvh 12y agoThat looks like the definition of a symmetric stream cipher, not OTP. You're missing the part where the OTP keystream has to be truly random. The output of a block cipher in CTR mode is not truly random.
- midas007 12y agoIndistinguishable from a PRF A good block cipher satisfied this property, otherwise it's not a PRF and insecure. Hair-splitting, really. Actual OTP is an imaginary construction that requires an endless supply of truly random bits that have to be securely stored or somehow recreated during decryption. It shifts the hard part to that fn, and just XORs the result with the pt or ct block.
- tptacek 12y agoNo. What you've done here is redefined "OTP" to mean "any stream cipher". No.
- midas007 12y agoThat's the whole point of OTP as an imaginary construction! It's a way to take any block cipher and turn it into a stream cipher with the power of XOR. (I'm only going to ask this nicely once: cease and desist stalking and harassment.)
- tptacek 12y agoNo, you have your terminology thoroughly confused. An OTP is an information-theoretically secure cipher where the key is as long as the plaintext. The only relationship between a one-time pad and CTR is the XOR operation. Furthermore, the article you're responding to explains what's wrong with simple stream ciphers for disk sector encryption.
- schoen 12y agoCTR isn't an OTP in the classic sense of OTP, because you rely on the security of blockcipher. For example, if you used blockcipher=single DES, the attacker can break the cipher by breaking single DES by brute force. Indeed, even if blockcipher=AES256, the attacker can still break CTR by merely guessing key in 2²⁵⁶ operations. (Likely only one such value of key will yield meaningful plaintext throughout the entire multi-block message.) That is contrary to the information-theoretic security property of OTP, where the attacker can't tell whether they've correctly guessed the key. More to tptacek's point, if you're using the block offset as i, then if you write the same block 30 times, you used the same value blockcipher(key, nonce . i) each time. That isn't a one-time use of that part of the pad, it's a 30-time use of that part of the pad. It's extremely possible that an attacker who has observed all 30 ciphertexts can actually decrypt many of them in combination. In Boneh's Coursera class, we did it successfully with like 4 or 5 ciphertexts, and I've seen a paper that describes doing it automatically for the majority of the text with only two ciphertexts, assuming the plaintext is English written in ASCII.
- lvh 12y agoUh, yeah, except not a cryptographic hash function, first of all :-) Secondly, CTR has serious issues too. It is trivial to bit-fiddle. The naive implementation you're suggesting leaks the keystream in one CCA query. Just because CTR in and of itself is easy to get right doesn't mean that any system composed using CTR is easy to get right.
- midas007 12y agoFixed. That's beyond the scope of which mode, but it's important. However the less code one has, the fewer places there are for things to hide.
- tptacek 12y agoNo, malleability is not beyond the scope of which "mode" you encrypt something with. That's like saying that security is beyond the scope of which "mode" you encrypt with. People used to believe you could divorce confidentiality from integrity, back in the 1990s, but that turned out not to me true, due to adaptive chosen ciphertext attacks.
- tptacek 12y agoThe trivial malleability of CTR is apparently why NIST rejected it, but it's important to remember that most unauthenticated block cipher modes are malleable, including XTS.
- tcas 12y agoIt's explained pretty well in the article. Basically with CTR using the block # as the nonce you break the security assumptions of a nonce (use only once). If the cryptofunc is static, and you are editing a document in place, an attacker can see exactly which bytes changed and do other statistical attacks. Think about a file that you preallocate with NULLs. If you get an image of the disk before you write to the file and then an image once you write to the file, you can simply XOR the before and after to get the ciphertext. e.g. using block 100 cipherblock_before = cryptofunc(100) ^ 0x00 = cryptofunc(100) cipherblock_after = cryptofunc(100) ^ data cipherblock_after ^ cipherblock_before = data
- midas007 12y agoYes, it's a known weakness. You have to rekey every X blocks.
- tptacek 12y agoNo, rekeying does not solve that problem, not to mention which you've just handwaved a hard problem (varying the key over different sectors). That's doable (though it again doesn't fix the problem with your proposal), but the resulting mode isn't CTR.
- midas007 12y agoYes it does, and it's still CTR. Further, every solution is going to have other machinery solving specific concerns. You don't call XTS something else because you've used scrypt or PBKDF2 as the PBKDF. Work is work.
- tptacek 12y agoThis is a sequence of non-sequiturs, none of which respond to my comment. I'll make it easier for you: Propose a scheme whereby you use AES-CTR to encrypt a 100 megabyte disk of 512-byte sectors, whereby the scheme "rekeys" every "few sectors". Be specific.
- deleted 12y ago[deleted]