使用 PyCryptodome 无法解码时如何找到正确的密钥

How to find the right key when decryption is not decodable with PyCryptodome

我是密码学的新手。有一个 file.aes 使用带有 128 位密钥和 ECB 的 AES 加密。我不知道原始文件是什么格式。我得到了一组密钥,有人告诉我其中一个可以正确解密。所以我用 PyCryptodome 写了一个 python 脚本如下:

from Crypto.Cipher import AES

keys = [some 32 character keys]

file_in = open("file.aes", "rb")
ciphertext = file_in.read()

for key in keys:
    print (key)
    cipher = AES.new(str.encode(key), AES.MODE_ECB)
    data = cipher.decrypt(ciphertext)
    print(data)

对于所有的密钥解密 returns 字节的数据是不可理解的,像这样:

b'\xdd\xc1\xd4\x80\xd5\xe6\x92\xe7\xf3/\n\xa4\x90\x0b\x98(\x8a\xb8\xdf\xd1K\n\xeagW\xe9f\x80\xef9\x8e\xd5...'

我尝试用asciiutf-8utf-16utf-32解码,希望能看到明文,他们都returnUnicodeDecodeError:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xa7 in position 0: ordinal not in range(128)

如何找到数据的正确编码?

我也开始怀疑原始文件是否也只是一个难以理解的二进制文件。光看不能识别,怎么知道哪个解密成功正确?


编辑:

按照建议,我尝试加密和解密一个 utf-8 编码的普通文件,如下所示。解密没有问题。

from Crypto.Cipher import AES

key = b'ipu9TUv54yv]isFMh5@;t.5w34E2Ry@{'
cipher = AES.new(key, AES.MODE_ECB)

file_in = open("file", "rb")
data = file_in.read()
length = 16 - (len(data) % 16)
data += bytes([length]) * length

ciphertext = cipher.encrypt(data)
print(ciphertext)

plaintext = cipher.decrypt(ciphertext)
print(plaintext.decode())

更新:新想法。由于我正在测试一堆大部分无效的密钥,因此解密数据可解码和 return 错误可能是正常的。我应该使用 try 和 except。我还应该尝试 python 在 documentation.

中列出的所有编解码器
from Crypto.Cipher import AES

keys = [some 32 character keys]
codecs = [all codecs]

file_in = open("file.aes", "rb")
ciphertext = file_in.read()

for key in keys:
    print (key)
    cipher = AES.new(str.encode(key), AES.MODE_ECB)
    data = cipher.decrypt(ciphertext)
    for codec in codecs:
        try :
            print(data.decode(codec))
        except:
            pass

在 print 语句上添加 decode 和 try-except 后,尝试所有编码,我发现 none 个键可以打印任何内容。

我找到了一种使用 OpenSSL 成功解密它的方法。

写一个脚本调用OpenSSL,用keyset,python bash or bat都无所谓。无论密钥正确与否,它都会创建一个输出文件,该文件可以被覆盖,但我们不关心。如果密钥错误,它会打印出错误的解密错误并以代码 1 退出。找到它不打印任何内容的密钥或以代码 0 退出。然后单独使用密钥进行解密。在我的例子中,我找到了 8 个键,但其中只有一个是可读的。

这里是 python 这个想法的实现:

keys = [a list of all possible keys]

for key in keys:
    # out.txt will be repeatedly overwritten
    command = "openssl enc -d -aes-128-ecb -in file.aes -out out.txt -K " + key
    output = os.system(command)
    # If OpenSSL exited with code 0
    if (output == 0):
        # Generates a separate file for that key
        command = "openssl enc -d -aes-128-ecb -in file.aes -out " + key + ".txt -K " + key
        output = os.system(command)