简体   繁体   English

python 3 使用AES加密和解密图像

[英]python 3 encrypt and decrypt image using AES

I am using AES to encrypt and decrypt the image.我正在使用 AES 加密和解密图像。 I have inherited the code so please guide me if you guys see something wrong.我继承了代码,所以如果你们发现有问题,请指导我。 I am trying to understand and fix the code.我正在尝试理解和修复代码。

    chunk_size = 64*1024
    output_file = filename+".enc"
    file_size = bytes(os.path.getsize(filename))
    IV = get_random_bytes(16)

    encryptor = AES.new(key, AES.MODE_CBC, IV)
    with open(filename, 'rb') as inputfile:
        with open(output_file, 'wb') as outf:
            outf.write(file_size)
            outf.write(IV)
            while True:
                chunk = bytes(inputfile.read(chunk_size))
                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                   chunk = chunk + bytes(16 - len(chunk)%16)
                outf.write(encryptor.encrypt(chunk))

My image is 66 kb which comes around - 67584 bytes.我的图像是 66 kb,大约是 67584 字节。 Considering AES works with 16 bytes this code should error out but it generate the encrypted file.考虑到 AES 使用 16 个字节,此代码应该会出错,但它会生成加密文件。 When I try to decrypt using当我尝试使用解密时

def decrypt(key, filename):
        chunk_size = 64*1024
        output_file = filename[:-4]
        with open(filename, 'rb') as inf:
            filesize = bytes(inf.read(16))
            IV = inf.read(16)
            decryptor = AES.new(key, AES.MODE_CBC, IV)
            with open(output_file, 'wb') as outf:
                while True:
                    chunk = inf.read(chunk_size)
                    print(len(chunk))
                    if len(chunk)==0:
                        break
                    outf.write(decryptor.decrypt(chunk))
                outf.truncate(filesize)```

I get an error like below我收到如下错误

TypeError: an integer is required (got type bytes) TypeError:需要一个 integer(获取类型字节)

and when I type chunk in bytes I get the following error当我以字节为单位输入块时,出现以下错误

Input strings must be a multiple of 16 in length输入字符串的长度必须是 16 的倍数

I am confused how can I fix error "multiple of 16 in length" when my filesize on the console for source is shown as 65536.当我在控制台上的源文件大小显示为 65536 时,我很困惑如何修复错误“长度为 16 的倍数”。

The file size is stored improperly.文件大小存储不正确。 To store the file size in the first 16 bytes (as it's presumably intended with regard to the decrypt method, although 16 bytes are actually too large) in big endian order, replace in the encryption:要将文件大小以大端顺序存储在前 16 个字节中(因为它可能是关于decrypt方法的,尽管 16 个字节实际上太大了),请在加密中替换:

file_size = bytes(os.path.getsize(filename))

with

file_size = os.path.getsize(filename).to_bytes(16, byteorder='big')

and in the decryption:并在解密中:

filesize = bytes(inf.read(16))

with

filesize = int.from_bytes(inf.read(16), byteorder='big')

With these changes, encryption and decryption work as intended.通过这些更改,加密和解密按预期工作。

Note: You use a Zero padding variant for padding and store the file size (probably only) to remove the padding after decryption.注意:您使用零填充变体进行填充并存储文件大小(可能仅)以在解密后删除填充。 There is a more efficient method, PKCS7 padding.有一种更有效的方法,PKCS7 填充。 Here the information how many bytes to remove is already included in the padding itself.在这里,要删除多少字节的信息已经包含在填充本身中。 So the file size does not have to be stored (at least not to remove the padding).因此不必存储文件大小(至少不必删除填充)。 In addition, padding is also supported in PyCryptodome by the methods pad and unpad .此外, PyCryptodome还通过padunpad方法支持填充。

Well I am not able to verify the given code since I dont know your exact need or usage or the idea of the implementation, but if you want to see a similar code I wrote about how to encrypt and decrypt the images using python by AES encryption, to get the crux idea(you may then be able to tweak and get your code working according to your needs, or use mine if you just want what it does)好吧,我无法验证给定的代码,因为我不知道您的确切需求或用法或实现的想法,但是如果您想查看我写的关于如何使用 python 通过 AES 加密加密和解密图像的类似代码, 得到关键的想法(然后你可以根据你的需要调整和让你的代码工作,或者如果你只是想要它的功能,可以使用我的)

You may consider a step by step blog walkthrough I wrote a while back it might help(Recommended before using the code for better understanding of the code) How to Encrypt and Decrypt Images using Python and pycryptodome您可以考虑我写了一段时间的逐步博客演练它可能会有所帮助(建议在使用代码之前更好地理解代码) 如何使用 Python 和 pycryptodome 加密和解密图像

However if you just need the code and its dependencies you may as well fork it from its official github repo CrypImg但是,如果您只需要代码及其依赖项,您也可以从其官方 github repo CrypImg中分叉它

Note: You should get the neccessary modules installed before using, you may get them in the requirements.txt given along with the code in the github repo above.注意:您应该在使用前安装必要的模块,您可以在给出的 requirements.txt 以及上面 github repo 中的代码中获取它们。

I know I was not able to directly solve your problem, but just because I myself got it working after a lot of challenges I wanted to try to help if it matches what you need so you may get it working as well.我知道我无法直接解决您的问题,但只是因为我自己在经历了很多挑战后才让它工作,所以如果它符合您的需要,我想尝试提供帮助,这样您也可以让它正常工作。

My code:我的代码:

#Importing Stuff
from Crypto.Cipher import AES
import io
import PIL.Image
from tkinter import *
import os

#Private Stuff
key = b'Key of length 16' #Todo Enter a Key(Like a password only) Here of Length 16 (Both Key and ivb required keep both safely and securely)
iv = b'ivb of length 16' #Todo Enter a ivb (Like a password only) Here of Length 16 (Both Key and ivb required keep both safely and securely)




#Encrypting Image
def encrypt_image():
    global key,iv,entry_for_folder
    file_path=str(entry_for_folder.get())
    if(file_path=="" or file_path[0]==" "):
        file_path=os.getcwd()
    files=[]
    # r=root, d=directories, f = files
    for r, d, f in os.walk(file_path):
        for file in f:
            if((('.JPG' in file) or ('.jpg' in file)) and ('.enc' not in file)):
                files.append(os.path.join(r, file))
    for file_name in files:
        input_file = open(file_name,"rb")
        input_data = input_file.read()
        input_file.close()

        cfb_cipher = AES.new(key, AES.MODE_CFB, iv)
        enc_data = cfb_cipher.encrypt(input_data)

        enc_file = open(file_name+".enc", "wb")
        enc_file.write(enc_data)
        enc_file.close()


#Decrypting Image
def decrypt_image():
    global key,iv,entry_for_folder
    file_path = str(entry_for_folder.get())
    if (file_path == "" or file_path[0] == " "):
        file_path = os.getcwd()
    files = []
    # r=root, d=directories, f = files
    for r, d, f in os.walk(file_path):
        for file in f:
            if '.enc' in file:
                files.append(os.path.join(r, file))
    for file_name in files:
        enc_file2 = open(file_name,"rb")
        enc_data2 = enc_file2.read()
        enc_file2.close()

        cfb_decipher = AES.new(key, AES.MODE_CFB, iv)
        plain_data = (cfb_decipher.decrypt(enc_data2))

        imageStream = io.BytesIO(plain_data)
        imageFile = PIL.Image.open(imageStream)
        if('.jpg' in file_name):
            imageFile.save((file_name[:-8])+".JPG")
        elif('.JPG' in file_name):
            imageFile.save((file_name[:-8])+".jpg")




#Tkinter Stuff

root=Tk()

root.title("Simple AES Encryption and Decryption of JPG Images")

folder_directory_label=Label(text="Enter the Folder Directory")
folder_directory_label.pack()

entry_for_folder=Entry(root)
entry_for_folder.pack()


encrypt=Button(text="Encrypt All",command=encrypt_image)
encrypt.pack()
label=Label(text="Leave Blank for Current Working Directory")
label.pack()
decrypt=Button(text="Decrypt All",command=decrypt_image)
decrypt.pack()



root.mainloop()

This above app code is Licensed under MIT LICENSE AGREEMENT上面的应用程序代码根据 麻省理工学院许可协议获得许可

加密前

and After Encryption(leave the directory entry blank for the encrypting/decrypting all images recursively in the current working directory else enter a folder directory)和加密后(将目录条目留空,以便在当前工作目录中递归地加密/解密所有图像,否则输入文件夹目录)

加密后

Hope it Helps a little.希望它有点帮助。

------------------ Update ------------------------- ------------------更新--------------

The Code is updated for more convenient usage, please check the github repo Cryptimg For the latest version of the code.代码已更新,使用更方便,请查看 github repo Cryptimg获取最新版本的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM