1

I'm trying to make a basic encryption/decryption script for personal use, and it works perfectly fine. I'm posting this in the infosec section because my question revolves around how easy it is to break the encryption.

NOTE: I know little about cryptology, hence the simplistic question.

Here is a quick mock-up of my code:

from Crypto.Cipher import AES
import hashlib
from random import randint
import struct
from getpass import getpass
import os

infile = sys.argv[1]
password = hashlib.sha256(getpass('[*] Enter Password: ')).digest()
ivector = ''.join(chr(randint(0, 0xFF)) for i in range(16))

encryptor = AES.new(password, AES.MODE_CBC, ivector)

with open(infile, 'rb') as infile:
    to_encrypt = infile.read()

to_encrypt += 'password_is_correct'
while len(to_encrypt)%16 != 0:
    to_encrypt += ' ' #Pad file to a multiple of 16 for encryption

encrypted = encryptor.encrypt(to_encrypt)
size = os.path.getsize(infile)
with open(infile, 'wb') as outfile:
    outfile.write(struct.pack(size, '<Q'))
    outfile.write(ivector)
    outfile.write(encrypted)

print '[*] Encryption Completed!'

To summarize. This code will encrypt a file with a random initialization vector and a password given by the user. It will read the file to encrypt and will append the string "password_is_correct" to the end of the string. Upon decryption, the initialization vector will be read from the file, and a password will be taken from the user. If the password is correct, then the string "password_is_correct" should be in the decrypted string. Is this a valid method a password verification? Does this pose any sort of risk to file integrity as to easing the file cracking process?

The full code can be found here.

4

Yes, this is a valid method of password verification.

A disadvantage is that an attacker now knows that the plaintext "password_is_correct" corresponds to the last block in the ciphertext. Fortunately, AES is not vulnerable for known-plaintext attacks.

PGP also checks the decrypted data, but it uses properties of a random block instead of a fixed string. Another way that is often used incorrectly is to verify the padding of the message. This can make a padding oracle attack possible, although this does not apply to your situation.

Another typical way is to store a hash of the key in the message, so that the password can be verified before decrypting the message.

There are some other things that can be improved with your script:

  • Use SystemRandom to get the IV, as normal random is not cryptographically secure.
  • Use a real key derivation function such as PBKDF2 instead of SHA256 to derive the encryption key from the password.
  • Store a HMAC of the encrypted text and verify it before encryption. CBC is vulnerable to a bit-flipping attack.
  • You may want to also encrypt the filesize field.
  • 1
    Regarding known-plaintext attacks: aren't padding oracles a risk in this scenario? I suppose the attack scenario would be quite unrealistic though. – Rens van der Heijden Jun 10 '16 at 7:56
-1

What you're essentially doing here is deriving a key from a password manually and checking file integrity manually. The standard answer to this type of question is "don't do it". In short, try to use libraries to do both key derivation, encryption, and integrity checks. Password and file/encrypted file go in, encrypted file/decrypted file comes out.

File Integrity

The problem here is that you're trying to check correct decryption by checking that a string exists. However, what you're actually checking is only the end of the file. The problem with that is that your encryption process doesn't protect against manipulation of the rest of the (encrypted) file. The why is a bit complicated, but basically it could be possible to flip bits in the encrypted file intelligently to change the output. Then your file content "ABCpassword_is_correct" might become "ABDpassword_is_correct".

Since you asked, this could in some cases indeed also affect the how good the confidentiality is (your concern whether someone else can read the file without the key). If you want to know more about that I'd recommend you ask a question about it on crypto, because it is strongly related to how the actual crypto works.

Password Verification

There is a concept in cryptography called a password-based key derivation function, which is probably what you're looking for. There is also a python library that implements this functionality found here. If I understand correctly that implementation wraps around OpenSSL.

Some context: PBKDF2 is a standardized (cryptographic) protocol that gives you a key from a secret. The most important part that this does beyond what you wrote is adding a salt to the password process. You might ask why this is important -- the main reason is that you may want different keys for different files. Then, even when the IV is the same and parts of the files are the same, your encrypted files will be indistinguishable. It should be enough to use the file name or path as salt.

Other problems

I'm not sure whether the encryption process you're using is secure. I think you have similar problems with padding. Ideally you'd use standardized implementations for those. This not only avoids bugs (data recovery is hard...) but also makes sure that your implementation doesn't weaken your security. Most problems in security are caused by bad implementation, and this is also the case for cryptography.

  • I think the question was "how can I check whether the decryption went OK" and not "how can I get a key from a password". While it is a good idea to use PBKDF2 instead of SHA256 to derive the key, I don't think that was the question. – Sjoerd Jun 10 '16 at 6:59
  • @Sjoerd sorry, I guess I over-interpreted the "Is this a valid method a password verification?" part of the question. I hope it helps the OP nonetheless. – Rens van der Heijden Jun 10 '16 at 7:00
  • 1
    He is clearly using CBC, as in the code it says AES.MODE_CBC, and not ECB. – Sjoerd Jun 10 '16 at 7:01
  • While this doesn't answer the immediate question, I will definitely do my research on these and implement them in the next version. Thank you. – The Defalt Jun 10 '16 at 7:04
  • @TheDefalt I extended the answer to try and cover your questions about integrity. Hope that helps. – Rens van der Heijden Jun 10 '16 at 7:52

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.