password protected files

Started by
33 comments, last by Extrarius 17 years, 9 months ago
The first AP possibly misinterpreted it as using a password-seeded PRNG to generate a random number and then XORing every block with that number, as opposed to using the PRNG to generate an approximation to a one-time pad (i.e. a pseudo-random stream of numbers, of the same length as the message).

But the latter still doesn't seem especially good - if you encrypt two messages with the same password (hashed to get the PRNG seed), they'll have the same pseudo-random stream (so it's a two-time pad), so you just XOR the ciphertexts together to get the XOR of the plaintexts, and then it's relatively easy to recover some of the original text even though you don't know the password. And if you know one plaintext, you can XOR it with the ciphertext to get the output of the PRNG, and thus recover the plaintext of any other message you have that uses the same password.

(Those are (I think) easy to protect against if you start by generating a random number, storing that in the output file, and XORing that with the hashed password to get the PRNG seed, so that no two messages will use the same stream of random numbers for the encryption. But that still doesn't prevent somebody who knows a plaintext/ciphertext pair from creating their own message using the same password even if they don't know the password, since they're free to reuse the known message's seed value. And it relies on having a good PRNG, with a long enough period that it'll never get stuck in a cycle (which I'd guess requires a period of at least the square of however much data you're encrypting at once) and presumably other properties that cryptographers are happy with, and then you might as well just use an entire encryption algorithm and high-quality library implementation that cryptographers are already happy with [smile]. (And then store the salted hash of the password so you can tell users when they've typed it in wrong, using a hash function that's sufficiently hard to brute-force.))
Advertisement
Quote:Original post by Excors
The first AP possibly misinterpreted it as using a password-seeded PRNG to generate a random number and then XORing every block with that number, as opposed to using the PRNG to generate an approximation to a one-time pad (i.e. a pseudo-random stream of numbers, of the same length as the message).


Nope.

This is like the blind leading the blind.
If you're not experienced in cyrptography, you have no business trying to invent an encryption algorithm that you expect anybody (including yourself) to actually use.

There are plenty of algorithms (and implementations) available that have been examined by experts and found to work well. Use one of those, which is infinitely more secure than anything you'll think up without experience in the field (even though they require significant assumptions in order to be secure).
One such algorithm is AES (Rijndael).

Also, be aware that simply applying an encryption function to every block of data is NOT a secure way to encrypt your data. Look into block cipher modes of operation for the proper way to apply encryption algorithms.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Here is an implementation of the simple method I described above, along with a jpeg file that has been encrypted using the included executable. If you really think this method is breakable with pencil and paper, then be my guest, have a go at decrypting the image. I expect this method to be crackable within a couple days given significant cpu cycles, much like RC4-40 was (since this has some similarity to it).
.
Quote:Original post by Mastaba
Here is an implementation of the simple method I described above, along with a jpeg file that has been encrypted using the included executable. If you really think this method is breakable with pencil and paper, then be my guest, have a go at decrypting the image. I expect this method to be crackable within a couple days given significant cpu cycles, much like RC4-40 was (since this has some similarity to it).


Not good enough. The first part of my offer was "Disclose the method you used exactly" - this means source code. Source code is not included in your release.
the AP's test is a good idea. And I agree your method will be breakable in two seconds (not neccessarily with pencil and paper, maybe).

The reason you need to release the source to make this a valid test is because anyone with a copy of your program and olly will be able to reverse engineer it in two seconds. Also, I recall reading a very interesting paper a while back about the 'philosophy' of encryption. Basically, because your source is readily available to anyone with a debugger, it should be considered 'public information'. Your algorithm could be trivially broken by someone with this information, so in reality the source is part of the 'key'(private information) and should be treated as such.

Hope that made some sense.
Quote:Original post by Mastaba
Here is an implementation of the simple method I described above, along with a jpeg file that has been encrypted using the included executable. If you really think this method is breakable with pencil and paper, then be my guest, have a go at decrypting the image. I expect this method to be crackable within a couple days given significant cpu cycles, much like RC4-40 was (since this has some similarity to it).
You have a bug in your code - the function that calculates the CRC32 of the password appears to take the string length as a parameter, but the length passed is the number of characters (each 2 bytes since you use unicode) while the function seems to use it as if it were the number of bytes. Thus, the password hash is only the first half of the string (with every character followed by a NUL character).

[Edited by - Extrarius on June 27, 2006 12:20:02 PM]
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Original post by Extrarius
You have a bug in your code - the function that calculates the CRC32 of the password appears to take the string length as a parameter, but the length passed is the number of characters (each 2 bytes since you use unicode).


Good catch! I forgot to multiply the character count by the width of a character. Fortunately, I used a nice long password on the sample document.

Though it also highlights some other things I would do now, if I actually took time to make it more secure. One, thing is I would change the password to UTF-8 and then calculate the hash. Another is, instead of using a 32 bit CRC, I would use a 160 bit CRC, that would allow me to seed the RNG without doing those dodgy bit manipulations on the 32 bit hash to create the 160 bit seed. I would also of course, store the in the encrypted document a sub-document, a small consistent key (not necessarily constant!) that can quickly be unencrypted to see if the rest of the document should be unencrypted or return a password error. I would also use a RNG that was more obscure than the one I chose to use. I would also obviously use methods to infuriate those with debuggers. [wink]

This excutable as it is now does not add anything to the document, not even a hash of the password. So the unencrypted document is exactly the same size as the encrypted document. As such, this excecutable does not do any checking on the password you give to see if it is correct. Heck, this executable does not know the difference between encrypting and decrypting. It is a purely symmetric algorithim. It is up to the person at the keyboard to determine if the unencrypted document truely is unencrypted.

[Edited by - Mastaba on June 27, 2006 4:09:53 PM]
.
dsfe_decrypt will decrypt any file encrypted with Mastaba's "dsfe" program as long as you can guess the first few bytes (at least 4) of the file. The more bytes you provide, the fewer results you have to look through, but the longer it takes to find the key. The key isn't the password, but is enough to successfully decrypt the file, and a password that would hash to a given key could be computed in under 4 hours according to a few random google results. I did make a function to turn a hash into a password, but I removed the code after it ran for several minutes without success - the key is enough to decrypt files anyways.

To demonstrate the functionality, I've provided a 'template' file (the bytes you provide, must be a multiple of 4 bytes) for the jpeg image format and both the encrypted and decrypted jpeg.

It took ~57 seconds on my Athlon64 X2 3800+ to find the key for the jpeg and decrypt the file using it. This was based on 12 bytes of guessed data - the first 12 bytes of the jpeg header, which are pretty much constant. The program only uses a single thread, and it could be sped up temendously by making it multithreaded since each iteration of the main loop is entirely independant of all others (aside from storing possible keys in a list, which is something that happens fairly rarely even with only 4 bytes of provided data).

Note that this is a brute force attack of the "known plaintext" variety. I'm sure there are more complicated attacks that would be far, far faster, but I'm not an experienced cryptographer and it's not worth becoming one solely to demonstrate that custom algorithms are, as a rule, broken =-)

Some of the changes you mention would defeat this attack, but I'm fairly certain there would be other holes either in the algorithm or the implementation even then (unless you're quite knowledgable about cryptography).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

This topic is closed to new replies.

Advertisement