1

Can someone please guide us what we might be doing wrong here? The code crashes with "raise ValueError("Incorrect AES key length (%d bytes)" % len(key)) ValueError: Incorrect AES key length (89 bytes)"

Note: The file symmetric_key.txt contains the exact same sequence as the hardcoded variable i.e. [EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e

#!/usr/bin/python3

from Crypto import Random

from Crypto.Cipher import AES 

import os

import os.path

from os import listdir

from os.path import isfile, join

import time

import sys

class Encryptor:
    def __init__(self, key):
        self.key = key

    def pad(self, s):
        return s + b"\0" * (AES.block_size - len(s) % AES.block_size)

    def encrypt(self, message, key, key_size=256):
        message = self.pad(message)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(key, AES.MODE_CBC, iv)
        return iv + cipher.encrypt(message)

    def encrypt_file(self, file_name):
        with open(file_name, 'rb') as fo:
            plaintext = fo.read()
        enc = self.encrypt(plaintext, self.key)
        with open(file_name + ".enc", 'wb') as fo:
            fo.write(enc)
        os.remove(file_name)

    def decrypt(self, ciphertext, key):
        iv = ciphertext[:AES.block_size]
        cipher = AES.new(key, AES.MODE_CBC, iv)
        plaintext = cipher.decrypt(ciphertext[AES.block_size:])
        return plaintext.rstrip(b"\0")

    def decrypt_file(self, file_name):
        with open(file_name, 'rb') as fo:
            ciphertext = fo.read()
        dec = self.decrypt(ciphertext, self.key)
        with open(file_name[:-4], 'wb') as fo:
            fo.write(dec)
        os.remove(file_name)

    def getAllFiles(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        dirs = []
        for dirName, subdirList, fileList in os.walk(dir_path):
            for fname in fileList:
                if (fname != 'encryptor_git.py' and fname != 'data.txt.enc'):
                    dirs.append(dirName + "\\" + fname)
        return dirs

    def encrypt_all_files(self):
        dirs = self.getAllFiles()
        for file_name in dirs:
            self.encrypt_file(file_name)

    def decrypt_all_files(self):
        dirs = self.getAllFiles()
        for file_name in dirs:
            self.decrypt_file(file_name)

## file fetching the symmetric key
with open("symmetric_key.txt", "rb") as k1:
    key_from_file = k1.read()
    
## this hardcoded key works fine
key = b'[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e'
key = key_from_file

print (type (key))


enc = Encryptor(key) ## created object of Encryptor class 
clear = lambda: os.system('cls') 


enc.encrypt_file(str(input("Enter name of file to encrypt: ")))            

1 Answers1

1

The in-code version of the key is defined through a string literal. When Python interprets the line:

key = b'[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e'

it handles all the \xc8 kind of sequences and converts them to proper internal representation. On the other hand, the same string read from a file is left as is. I'd rather store the key in hex or base64 encoding, but if you have to deal with what you have, you can use e.g. ast.literal_eval:

key = ast.literal_eval(f'"{key_from_file}"')

Update: if key_from_file is bytes, not string, like in your example, the quotes are redundant, e.g.

key = ast.literal_eval(str(key_from_file))

That all said, the more reliable way is to use base64 to store the key.

bereal
  • 32,519
  • 6
  • 58
  • 104
  • Its still crashing after I changed the encoding to base64 for input file. ast.literal_eval is also not working in our case – Ali Masud Hussain Jun 17 '21 at 13:32
  • 1
    @AliMasudHussain how exactly is it not working, what's the error message, what's the problem with base64 etc? – bereal Jun 17 '21 at 13:50
  • it now gives an error of "ValueError: Incorrect AES key length (45 bytes)" after i separately saved the text file to base64 encoding and then input it to the key variable in binary format. Separately when i use the ast.literal_eval it gives out a similar error – Ali Masud Hussain Jun 17 '21 at 14:00
  • That code I posted makes `key` exactly 16 bytes assuming that `key_from_file` is exactly like you posted. As for base64 part, I'd like to see the code and the file content. – bereal Jun 17 '21 at 14:03
  • Sorry, I missed one detail. In your code `key_from_file` is `bytes`. So the quotes in my answer are redundant, I'll fix that. – bereal Jun 17 '21 at 14:20