Decrypt with Fernet, TypeError: token must be bytes

Decrypt with Fernet, TypeError: token must be bytes

编程语言:Python

我有三个文件,一个是生成密钥,第二个是加密,另一个是解密..第一个和第二个文件可以..但是解密文件不起作用

生成密钥文件:

from cryptography.fernet import Fernet

def generate_key():
    """
    Generates a key and save it into a file
    """
    key = Fernet.generate_key()
    with open("secret.key", "wb") as key_file:
        key_file.write(key)

generate_key()

加密文件-

from cryptography.fernet import Fernet

def load_key():
    return open("secret.key", "rb").read()

def encrypt_message(message):
    key = load_key()
    encoded_message = message.encode()
    f = Fernet(key)
    encrypted_message = f.encrypt(encoded_message)
    
    print(encrypted_message)

    EncryptedTextWriteFile = open("encrypt.txt", "r+")
    EncryptedTextWriteFile.write(str(encrypted_message))

notEncryptedFile = open("text.txt", "r")
notEncryptedText = notEncryptedFile.read()

if __name__ == "__main__":
    encrypt_message(notEncryptedText)

notEncryptedFile.close()

解密文件 -

from cryptography.fernet import Fernet

def load_key():
    return open("secret.key", "rb").read()

def decrypt_message(encrypted_message):
    key = load_key()
    f = Fernet(key)
    decrypted_message = f.decrypt(encrypted_message)
    shit = decrypted_message.decode()

    print(shit)

    DencryptedTextWriteFile = open("decrypt.txt", "r+")
    DencryptedTextWriteFile.write(shit)

EncryptedFile = open("decrypt.txt", "r")
EncryptedText = EncryptedFile.read()

if __name__ == "__main__":
    decrypt_message(EncryptedText)

我试过的字符串-(这个测试在text.txt)

hirusha

我得到的错误:

Traceback (most recent call last):
  File "d:/development/Python/Everything/Releases/0.2/Build 02/_Releases/Encoder and Decoder/decrypt.py", line 27, in <module>
    decrypt_message(EncryptedText)
  File "d:/development/Python/Everything/Releases/0.2/Build 02/_Releases/Encoder and Decoder/decrypt.py", line 15, in decrypt_message
    decrypted_message = f.decrypt(encrypted_message)
  File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\fernet.py", line 75, in decrypt
    timestamp, data = Fernet._get_unverified_token_data(token)
  File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\fernet.py", line 100, in _get_unverified_token_data
    utils._check_bytes("token", token)
  File "C:\Users\hirusha\AppData\Local\Programs\Python\Python38\lib\site-packages\cryptography\utils.py", line 29, in _check_bytes
    raise TypeError("{} must be bytes".format(name))
TypeError: token must be byte

问题是当您打开文件 decrypt.txt 并读取文件时,它被转换为字符串。但是.decrypt函数只接受字节输入。

我认为这应该可以解决您的问题:

生成密钥并将其存储在 key.key 文件中:

from cryptography.fernet import Fernet
def write_key():
    """
    Generates a key and save it into a file
    """
    key = Fernet.generate_key()
    with open("key.key", "wb") as key_file:
        key_file.write(key)
write_key()

加密文件并将其存储在 enc_text.txt 文件中:

from cryptography.fernet import Fernet
with open("key.key","rb") as f:
    key=f.read()
f = Fernet(key)

with open('text.txt', 'rb') as original_file:
    original = original_file.read()

encrypted = f.encrypt(original)

with open ('enc_text.txt', 'wb') as encrypted_file:
    encrypted_file.write(encrypted)

解密enc_text.txt文件并将输出写入decrypt.txt

from cryptography.fernet import Fernet
with open("key.key","rb") as f:
    key=f.read()
f = Fernet(key)

with open('enc_text.txt', 'rb') as encrypted_file:
    encrypted = encrypted_file.read()

decrypted = f.decrypt(encrypted)

with open('decrypt.txt', 'wb') as decrypted_file:
    decrypted_file.write(decrypted)

在我写这篇文章的时候被 post 编辑了。这是正确的,但我仍然想post这个,以便更深入地了解这意味着什么。

大多数(如果不是全部)加密工具在 bytes 上工作,而不是 str。这既是因为如今加密二进制(非字符串)数据更为普遍,也是因为加密算法对数字起作用,而 bytesrange(0, 256).

中的数字字符串

在解密程序中,您在这一行加载密文:

EncryptedFile = open("decrypt.txt", "r")

将此与加载加密密钥的方式进行对比:

def load_key():
    return open("secret.key", "rb").read()

不同的是open的模式参数:如果字符串中有b,则表示它以二进制模式运行,工作在bytes而不是str。这是一个例子:

>>> text = open('test.txt', 'r').read()
>>> text
'Hello World!\n'
>>> binary = open('test.txt', 'rb').read()
>>> binary
b'Hello World!\n'
>>> type(text)
<class 'str'>
>>> type(binary)
<class 'bytes'>

这个区别很重要,因为 str 表示字符序列,而这些可以编码为二进制 in vastly different ways。您选择哪一个将影响进入加密算法的 1 和 0,从而影响结果。

尽管也以文本模式读取纯文本文件,但加密程序之所以起作用,是因为这一行:

encoded_message = message.encode()

str.encode 使用提供的编码将字符串转换为 bytes,如果未指定,则使用默认编码(通常为 UTF-8)。在解密程序中看到的 bytes.decode 方法做相反的事情:它将 bytes 转换为 str.

>>> text = '稲妻の腕を借らん草枕'
>>> text.encode()
b'\xe7\xa8\xb2\xe5\xa6\xbb\xe3\x81\xae\xe8\x85\x95\xe3\x82\x92\xe5\x80\x9f\xe3\x82\x89\xe3\x82\x93\xe8\x8d\x89\xe6\x9e\x95'
>>> text.encode('utf-16')
b'\xff\xfe2z\xbbYn0U\x81\x920\x1fP\x890\x930I\x83\x95g'
>>> u16_data = text.encode('utf-16')
>>> u16_data.decode('utf-16')
'稲妻の腕を借らん草枕'
>>> u16_data.decode()  # this is why specifying the encoding is important
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte