5
votes

I've written my own encryption method using AES in a project I've been working on lately using PyCrypto. I use a hash to generate a 32-byte password and feed that to AES-256bit encryption using CBC. The file input is padding using PKCS#7 padding to conform to be divisible by 16.

I can encrypt and decrypt the file without incident and the input file originally encrypted along with the output file have the same SHA-256 hash.

The only problem I'm finding is that if I supply the wrong passphrase, decryption still happens. This is a problem for what I'm doing, as I need to have decryption fail fast if the passphrase is wrong.

How can I make this happen? I've heard of other methods of AES encryption, but it seems that PyCrypto only supports ECB, CBC, CFB, OFB, CTR, and OpenPGP. How can I implement cryptographically strong AES which will fail decryption without the right passphrase?

3
I've written my own encryption method -- Well there's your problem.user395760
I didn't write my own encryption method. I wrote a program which uses AES as an encryption method. I'm not that daft.Naftuli Kay
AES is just a primitive (a block cipher). I get that my "encryption method" you mean a way to use this primitive (and others) for a higher-level purpose (password-based encryption of arbitrary amounts of data). That's what I meant: This is still something you probably shouldn't do yourself.user395760
Can you recommend a secure encryption method which offers 256-bit encryption, uses a strong and slow hash method as its key, and can encrypt without knowing the full length of the file? If there were a drop-in solution which met all of my requirements, that would be awesome.Naftuli Kay
I'm pretty sure there are existing solutions, but I'm no expert. At least for the hashing part, there's PBKDF2. Applying a stream cipher to arbitrary-length plaintexts is also done on a regular basis by expert-written and -reviewed software (and on the other side, crypto people come up with more sophisticated attacks every other month). As for combining the two, I'm stumped but presume there are existing standards, though perhaps no open source implementations.user395760

3 Answers

3
votes

There is nothing about AES (or any other encryption algorithm for that matter) that could allow you to know whether you have the correct key. That said, it's a very useful feature when you actually want to use cryptography outside of the realm of mathematics.

What you need to do is add a block with a known value at the start of your message, that way after decrypting the first block you can compare it against the known value and know whether you have the wrong key. If the data you're encrypting has a known header you could use this instead.

Alternatively you could send a cryptographic hash (for example SHA-256) of the key along with the message, an attacker would only be able to recover the key if they could break the hash.

5
votes

The best way of making sure that your ciphertext won't decrypt when it has been changed is to add an authentication tag. An authentication tag is used to provide authentication and integrity of the ciphertext.

This tag may consist of a MAC (e.g. AES-CMAC or HMAC using SHA-256) over the ciphertext. This however requires a second key to be secure.

Another method is to use authenticated encryption such as GCM. GCM uses a single key and generates an authentication tag (the size can be configured).

Make sure you use a correctly generated IV. The IV could be prefixed to the ciphertext, and should be included when calculating the authentication tag), and don't forget that the size of your plain text may not be hidden.

You should verify the correctness of the tag before decryption of the ciphertext.

Note that in general, you should not encrypt passwords, unless you require access to the precise password at a later date. For verification of passwords, use PBKDF2 instead.

0
votes

To provide the desired fail-fast property, you'll need to prepend a header to the data being enciphered. I suggest using a random "confounder" nonce (similar to a cryptographic salt) concatenated with a known constant "magic number"; the presence of a confounder will, much like a salt, provide a measure of defense against attacks based on precomputed tables.

With such a header present, you need only decipher the header and validate the magic number field; if it does not match the known constant, the key is no good. If it does match, discard the header and process the remainder of the input.