【问题标题】:python 3 encrypt and decrypt image using AESpython 3使用AES加密和解密图像
【发布时间】:2020-12-13 12:46:21
【问题描述】:

我正在使用 AES 加密和解密图像。我已经继承了代码,所以如果你们发现有问题,请指导我。我正在尝试理解并修复代码。

    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))

我的图片大小为 66 kb,大约为 67584 字节。考虑到 AES 使用 16 个字节,此代码应该会出错,但它会生成加密文件。当我尝试使用解密时

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)```

我收到如下错误

TypeError:需要一个整数(获取类型字节)

当我以字节为单位输入块时,我收到以下错误

输入字符串的长度必须是 16 的倍数

当我在控制台上的源文件大小显示为 65536 时,我很困惑如何修复错误“长度为 16 的倍数”。

【问题讨论】:

标签: python-3.x encryption


【解决方案1】:

文件大小存储不正确。要将文件大小以大端顺序存储在前 16 个字节中(可能是针对decrypt 方法,尽管 16 个字节实际上太大了),请在加密中替换:

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

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

在解密中:

filesize = bytes(inf.read(16))

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

通过这些更改,加密和解密按预期工作。

注意:您使用零填充变体进行填充并存储文件大小(可能仅)以在解密后删除填充。有一种更有效的方法,PKCS7 填充。在这里,要删除多少字节的信息已经包含在填充本身中。因此不必存储文件大小(至少不必删除填充)。此外,通过方法padunpadPyCryptodome 中也支持填充。

【讨论】:

  • 您对处理此代码还有其他建议吗?任何指针都会有所帮助。
【解决方案2】:

好吧,我无法验证给定的代码,因为我不知道您的确切需求或用法或实现的想法,但是如果您想查看我写的关于如何使用 python 加密和解密图像的类似代码通过 AES 加密,获得关键点(然后您可以根据自己的需要调整并让您的代码工作,或者如果您只是想要它的功能,也可以使用我的)

您可以考虑我前一段时间写的逐步博客演练它可能会有所帮助(建议在使用代码之前更好地理解代码)How to Encrypt and Decrypt Images using Python and pycryptodome

但是,如果您只需要代码及其依赖项,您也可以从其官方 github repo CrypImg 分叉它

注意:你应该在使用前安装必要的模块,你可以在上面给出的 github repo 代码中的 requirements.txt 中获取它们。

我知道我无法直接解决您的问题,但只是因为我自己在经历了很多挑战后才让它正常工作,如果它符合您的需要,我想尝试提供帮助,这样您也可以让它正常工作。

我的代码:

#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()

以上应用代码在MIT LICENSE AGREEMENT下获得许可

和加密后(将目录条目留空,以便递归加密/解密当前工作目录中的所有图像,否则进入文件夹目录)

希望对你有所帮助。

------------------更新------------------ ----

代码已更新,使用更方便,最新版本代码请查看github repoCryptimg

【讨论】:

    猜你喜欢
    • 2011-10-12
    • 2014-11-21
    • 2018-09-07
    • 2015-01-20
    • 2014-01-05
    • 2019-01-06
    • 1970-01-01
    • 2019-11-04
    • 2019-10-27
    相关资源
    最近更新 更多