Django Python:如何解密 Python shell 中的 AES-CTR 模式加密文件?

Django Python: How do I decrypt an AES-CTR mode encrypted file in the Python shell?

我正在使用 https://github.com/eblocha/django-encrypted-files 加密通过 Django 中的一个简单联系表单应用程序上传到服务器的文件。 django-encrypted-files 在 CTR 模式下使用 AES 通过上传处理​​程序加密上传的文件,同时将文件流式传输到服务器。

我想做的是通过 FTP 下载文件并在 Python shell 中本地解密来手动解密加密文件。我不想也不需要从服务器流式解密文件或修改django-encrypted-files;我只想在 Python shell.

本地手动下载然后解密文件

问题是我无法使用本地 Python 解密。 Cryptography 中的文档显示了使用 Python shell 中输入的示例文本进行加密和解密的示例。但是没有encrypting/decrypting一个文件的例子

下面是我在 Python shell 中尝试使用的代码。通过Django上传的原始文件是uploaded_file.txt。从服务器下载的加密文件为encrypted.txt;用于保存解密文本的文件是 decrypted.txt.

但是当我尝试下面的代码时,decrypted.txt 是空的。这是写文件的问题吗?或者 iv?

有问题

在本地解密 AES-CTR 模式文件的工作示例是什么 Python shell?

uploaded_file.txt: https://paste.c-net.org/MiltonElliot

encrypted.txt: https://paste.c-net.org/ChasesPrints

Python shell:

import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
key = b'\x1a>\xf8\xcd\xe2\x8e_~V\x14\x98\xc2\x1f\xf9\xea\xf8\xd7c\xb3`!d\xd4\xe3+\xf7Q\x83\xb5~\x8f\xdd'
iv = os.urandom(16)
cipher = Cipher(algorithms.AES(key), modes.CTR(iv))
decryptor = cipher.decryptor()
openfile = open("encrypted.txt", 'rb')
savefile = open("decrypted.txt", "wb")
read = openfile.read()
savefile.write(read[16:])
445 // output
exit

但是 decrypted.txt 文件是空的。


这可能相关也可能不相关;这是在流式传输到服务器时加密的函数:

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from django.core.files.uploadhandler import FileUploadHandler

class EncryptedFileUploadHandler(FileUploadHandler):
    """Encrypt data as it is uploaded"""
    def __init__(self, request=None, key=None):
        super().__init__(request=request)
        self.key = key or settings.AES_KEY
    
    def new_file(self, *args, **kwargs):
        self.nonce = os.urandom(16)
        self.encryptor = Cipher(algorithms.AES(self.key),modes.CTR(self.nonce)).encryptor()
        self.nonce_passed = False
        return super().new_file(*args,**kwargs)

    def receive_data_chunk(self, raw_data, start):
        if not self.nonce_passed:
            self.nonce_passed = True
            return self.nonce + self.encryptor.update(raw_data)
        else:
            return self.encryptor.update(raw_data)
    
    def file_complete(self, file_size):
        return

在加密过程中,IV 和密文连接在一起:IV || ciphertext。在解密过程中,使用了随机 IV,这是错误的。相反,必须应用加密的 IV。为此,必须将 IV 和密文分开。
此外,必须调用 update()finalize() 方法,它们执行实际的解密。

以下代码与您的代码基本匹配,由缺少的部分扩展:

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

# Read ciphertext
openfile = open("encrypted.txt", 'rb')
read = openfile.read()
openfile.close()

# Separate IV and ciphertext; decrypt
iv = read[:16]
ciphertext = read[16:]
key = b'\x1a>\xf8\xcd\xe2\x8e_~V\x14\x98\xc2\x1f\xf9\xea\xf8\xd7c\xb3`!d\xd4\xe3+\xf7Q\x83\xb5~\x8f\xdd'
cipher = Cipher(algorithms.AES(key), modes.CTR(iv))
decryptor = cipher.decryptor()
decrypted = decryptor.update(ciphertext) + decryptor.finalize()

# Store decrypted data
savefile = open("decrypted.txt", "wb")
savefile.write(decrypted)
savefile.close()

此代码成功解密了链接文件中的密文(使用发布的密钥)。