0

I would like to store encrypted backup of text files on my computer. I'm developing a python script using Pycrypto to achieve that, based on this code to use the library. (current code)

The basic idea is :

  1. Generate new/Read existing AES + signature keys
  2. Encrypt the data using the first key (AES 256-CBC)
  3. Sign the encrypted data using the second key with HMAC-SHA256

The generation of bytes for the keys is simply the result of Random.get_random_bytes(KEY_SIZE + SIG_SIZE), so 64 bytes in my case.

Now, to improve the security, I would like to add a password protection to the key (if somebody find the keys file). My initial idea is to hash salt+password and XOR the result with the random bytes in the key-file.

If I use SHA256 (to be consistent), it means I output 32 bytes and should XOR twice (for each 32 bytes key) and I don't like that (not sure but sounds like a potential attack). Using a different salt for each key ?

Finally, is there a standard way to store the salt and keys ? I don't like the idea of inventing my own scheme (usually a bad idea in cryptography). Is there some good practices ?

Update: thanks to the answer of Polynomial, I got the following code :

from Crypto import Random
from Crypto.Protocol.KDF import PBKDF2

def generate_new_keys(password, enc_key_size=32, sig_key_size=32):
    rand_bytes = Random.get_random_bytes(enc_key_size + sig_key_size)
    # save the salt
    with open('keys.salt','w') as f:
        f.write(rand_bytes.encode("base64").replace("\n",""))
    # derive the two keys using PBKDF2
    enc_key = PBKDF2(password, rand_bytes[:enc_key_size], dkLen=enc_key_size)
    sig_key = PBKDF2(password, rand_bytes[enc_key_size:], dkLen=sig_key_size)
    return (ency_key, sig_key)

1 Answer 1

5

Don't try to come up with your own encryption scheme. The one you propose is vulnerable to a known plaintext attack, which makes key material trivial to recover if any bits of the original file are known.

For example, if I know that the first byte of plaintext is always 0x4B, and I can see that the first byte of ciphertext is 0xC7, I can compute 0x4B ^ 0xC7 and get the first byte of the key, which would be 0x8C. From there I can skip ahead 32 bytes and decrypt that byte of ciphertext, and again, and again. Using that information I might discover more information about your plaintext, and use that to decrypt more of the data.

Encrypt your key file with a block cipher (e.g. AES) using an appropriate mode of operation (e.g. CBC), with a key derived using a proper key derivation algorithm, such as PBKDF2. Using a plain hash function for key derivation is a bad idea, as it's extremely fast and allows an attacker to crack the password efficiently. If your mode of operation requires an initialization vector (IV) it should be random and unique, but is not secret information.

5
  • Thank you for the attack explanations, as I thought, not good to use own scheme. So to sum up, I should use my two block of random bytes as salt ? Commented Dec 17, 2012 at 11:23
  • Also, is it better to store sha256(salt+password) to check if the entered password is correct or let the program fail if the entered password is incorrect ? Commented Dec 17, 2012 at 11:44
  • 2
    The salt for the key should be a random value stored in plaintext in the file, along with the IV for AES. Don't bother storing the hash, just make the first 4 bytes of the encrypted data static (e.g. "MTKF") so you can check that the decryption produced a correct output.
    – Polynomial
    Commented Dec 17, 2012 at 11:51
  • Wouldn't first X bytes plaintext (4 for 'MTKF') + first X bytes of ciphertext + first X bytes of IV still produce the first X bytes of the key (P ^ C ^ I = K)? If anything of the plaintext is to be static as a "checksum", I would suggest it be the last X bytes; in CBC mode any error in ciphering is compounded with each block, so if the last block is what you expect then you know the message wasn't tampered with. CBC-MAC creates checksums using this exact property of CBC block mode.
    – KeithS
    Commented Dec 19, 2012 at 22:22
  • @KeithS Not if you're using a proper cipher like AES, rather than a home-brew one.
    – Polynomial
    Commented Dec 19, 2012 at 23:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .