0
votes

I am trying to encrypt/decrypt with pycrypto in python. for the most part things have worked smooth but I am getting an odd problem when decrypting data.I have tried to encrypt/decrypt some jpgs for testing and although they encrypt/decrypt without issue, the decrypted files cannot be opened/are corrupted. To try to find the problem I saved a textfile with a random sentence similar to "test this file for integrity blah blah blah" and it decrypts correctly only after ".... integrity blah blah blah", everything before integrity is still in garbled characters. I'm not that knowledgable on AES, but im assuming that this is an encoding/decoding or padding error.

Here is my code:

#encryption
iv = Random.new().read( AES.block_size)

filePath = input("Path to file for encryption: ")
selFile = open(filePath, 'rb')
getBytes = bytes(selFile.read())

encPW = input("Enter password: ")
hashpw = hashlib.sha256(encPW.encode('UTF-8').digest())

destination = input("Destination path for encrypted file: ")

aes = AES.new(hashpw, AES.Mode_CFB, iv)
encFile = base65.b64encode(aes.encrypt(getBytes))

writetofile = open(destination, 'wb')
writetofile.write(encFile)
writetofile.close()
print("Encryption successful")

#Decryption
iv = Random.new().read( AES.block_size)

filePath = input("Path to file for decryption: ")
selFile = open(filePath, 'rb')
getBytes = bytes(selFile.read())

decPW = input("Enter password: ")
hashdecpw = hashlib.sha256(encPW.encode('UTF-8').digest())

destination = input("Destination path for decrypted file: ")

aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
decFile = aes.decrypt(getBytes)

writetofile = open(destination, 'wb')
writetofile.write(decFile)
writetofile.close()
print("Decryption successful")

Any ideas on what could be causing the loss of the first characters, and preventing me from encrypting/decrypting files correctly?

2
Please do not vandalize your posts.DJMcMayhem
Please do not vandalize your posts. Once you've posted a question, you have licensed the content to the Stack Overflow community at large (under the CC-by-SA license). If you would like to disassociate this post from your account, see What is the proper route for a disassociation request?.Bugs

2 Answers

1
votes

You have at least three issues:

  • You probably mean hashlib.sha256(encPW.encode('UTF-8')).digest() instead of hashlib.sha256(encPW.encode('UTF-8').digest()) (the closing brace is at the wrong position)

  • You're encoding the ciphertext with Base64 before writing it to a file. You've forgot to decode it after reading it back from the file before decrypting it. For example:

    getBytes = base64.b64decode(bytes(selFile.read()))
    
  • This is the big one: You need the exact same IV during the decryption that you've used for encryption. The IV is not secret, but it needs to be unique for every encryption that you've done with the same key. Commonly the IV is written in front of the ciphertext and read back for decryption.

    #encryption
    encFile = base64.b64encode(iv + aes.encrypt(getBytes))
    
    #decryption
    getBytes = base64.b64decode(bytes(selFile.read()))
    iv = getBytes[:16]
    aes = AES.new(hashdecpw, AES.Mode_CFB, iv)
    decFile = aes.decrypt(getBytes[16:])
    
1
votes

You're generating a new IV for encryption and decryption seperately, which comes to yield such problems. Here's what I recommend doing:

def encrypt(inpath, outpath, password):
    iv = Random.new().read(AES.block_size)
    with open(inpath, "rb") as f:
        contents = f.read()
    # A context manager automatically calls f.close()
    key = pbkdf2.crypt(password, "")
    # See notes

    aes = AES.new(key, AES.Mode_CFB, iv)
    encrypted = aes.encrypt(contents)
    with open(outpath, "wb") as f:
        f.write(iv + b":")
        f.write(encrypted)
    print("Encryption successful")


def decrypt(inpath, outpath, password):
    with open(inpath, "rb") as f:
        contents = f.read()

    iv, encrypted = contents.split(b":")
    key = pbkdf2.crypt(password, "")
    aes = AES.new(key, AES.Mode_CFB, iv)

    decrypted = aes.decrypt(contents)
    with open(outpath, "wb") as f:
        f.write(decrypted)
    print("Decryption successful")

Some notes:

  • An IV is not meant to be secret, so it can be randomly generated once and then written to a file to be used later for decryption (as shown in this example)

  • A hashing algorithm is not strong enough for deriving keys, which is why there are special tools called key derivation algorithms (like PBKDF2 in python). Use those instead!

I have not tested this code myself, so it may not work properly.