12

I was making a small application to encrypt files and ran into the problem of verifying that the provided key is the correct one when decrypting. My idea was to store the (padded, encrypted) key along with the encrypted file so when you want to decrypt, the program first checks if the first couple of bytes (un-padded) equals the provided key. I'm no security expert and I can't see a problem with the approach but i still have a feeling that this would be a bad practice some how.

Is this approach OK from a security perspective? Is there perhaps already another solution to the initial problem?

17

While there's no obvious vulnerability here, a better option is simply to store a static string, rather than the key itself. If an attacker finds a side-channel attack which allows them to discover one block of plaintext, your approach would leak the passphrase and thus break the whole system, whereas the fixed text option would not.

  • FWIW, this is the method that TrueCrypt uses. – Polynomial Dec 29 '16 at 16:12
  • 1
    Not sure about static. In the movie The Imitation Game they said that the German crypting had been broken because of static prefixes to some encrypted messages, and we don't know what kind of cypher OP wants to use. Maybe prefix equal to random x and some f(x) would be better. – Serge Seredenko Dec 29 '16 at 18:18
  • 9
    @SergeSeredenko This is only the case with weak cryptosystems, such as Enigma, which are vulnerable to known-plaintext attacks. Modern ciphers (e.g. AES, DES) are heavily resistant to known-plaintext attacks. – Polynomial Dec 29 '16 at 18:22
  • 1
    @SergeSeredenko Such a scheme would be breakable once the password dictionary exceeded a certain size, simply by finding key bytes which produce valid binary structures containing only ASCII strings. Each key byte could be independently discovered to be part of a small known set, producing (in aggregate) only a few hundred or thousand possible master passwords. If the master password has any structure, the true password could be deduced from that. If not, candidates could be compared against any captured offline hash. – Polynomial Dec 29 '16 at 18:40
  • 1
    @SergeSeredenko Just to validate my thoughts, I wrote some code which generated 10,000 random password databases, each containing 30 passwords of length between 20 and 40 characters (random), using a dictionary of a-z, A-Z, 0-9, plus 29 ASCII symbols. Each list item is delimited by a null, though with no trailing null. These databases were encrypted using a repeating-xor of a 22-character password (mixed case, numerics and symbols). In 3 cases I could recover the password definitively. The best case was a keyspace of size 409,227,831,936,000 - still one 3x10^28th of the password's keyspace. – Polynomial Dec 29 '16 at 19:10
10

You could do this:

  1. Generate cryptographically secure random 128-byte key

  2. Generate hash of random key

  3. Encrypt the file with the random generated key

  4. Encrypt the random key with the user provided key

  5. Put the following values in the file:

    encrypted random key:random key hash:encrypted file data

When want to decrypt the data, you use the user provided data to decrypt the encrypted random key, then you hash it and compare with the stored hash. If they are the same, you use the now decrypted random key to decrypt the data.

  • "hash:encrypted file data" shouldn’t that be "hash: random key"? – idmean Dec 30 '16 at 8:57
  • @idmean I understood it as encrypt(random key, user key) + ':' + hash(random key) + ':' + encrypt(data, random key), where ':' is just some delimiter. – Gustavo Rodrigues Dec 30 '16 at 14:52
  • @GustavoRodrigues Of course, now I see. I read that as kind of key-value-pairs. – idmean Dec 30 '16 at 14:54
3

Including a static string sounds as if it could be vulnerable to a known plaintext attack. Instead I'd to the following (but would be pleased to hear if it's a bad idea!);

  1. Hash your plaintext and prepend the hash to it
  2. Encrypt everything with your encryption technique

When you decrypt it, check if the hash at the beginning matches the hash you expect. This makes you able to detect if you got the correct decryption key and as a plus you get integrity checking for free. If you want to speed this up, say you'd like to encrypt large amounts of data where it is not feasible to run a hashing function over the entire payload, reduce the hashed portion to a few megabytes or blocks if it is a block cypher.

If you'd add an unecrypted hash of the key itself to the file, attackers may test keys without having to decrypt the whole file. This would speed up attacks a lot.

  • +1 conceptually this just treats the encryption as a lower layer (e.g. OSI layer 6), using a checksum (the hash) to validate that the lower layer(s) transmitted the message correctly. It also works, without changes, with public-key encryption. – drewbenn Dec 29 '16 at 20:33
  • What you are describing i essentially an authenticated encryption. I think authenticated encryption is the right tool for the task. But I am not sure the method you describe will actually produce a secure authenticated encryption. I have certainly come across recommendations to use designs where the data is authenticated before you start decrypting. – kasperd Dec 29 '16 at 22:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.