为什么Python加密失败?

问题描述 投票:0回答:1

我正在写一个聊天程序。我想保存聊天记录并重新加载。为了安全起见,我将加密数据然后压缩它。但无论我一直在尝试什么,我都无法弄清楚为什么会失败。这个问题与我的两种方法

export_history
import_history
有关。

def export_history(self, filename='chat_history.json.enc'):
    cipher = Fernet(self.key) # First, I generate a cipher (the key is generated using Fernet.generate_key() when the class is initialized).
    encrypted_data = base64.b64encode(cipher.encrypt(json.dumps([msg.to_dict() for msg in self.messages]).encode())) # I then encrypt the chat history using the key. I first write it as a json format though.
    file_data = self.key + encrypted_data # Here, I add my key to the beginning to my encrypted data. I know this is unsafe if I wanted to publish this program, but it's as a temporary placeholder, until I build the entire framework.
    compressed_data = lzma.compress(file_data) # Then I try to compress the data.
    encoded_data = base64.b64encode(compressed_data) # I encode the data.

    # Save encoded data to file using lzma
    with lzma.open(filename, 'wb') as file: # I open my chat history.
        file.write(encoded_data) # I save the compressed and encrypted data to the file.
def import_history(self, filename='chat_history.json.enc'):
    try:
        # Use lzma.open to read the file
        with lzma.open(filename, 'rb') as file: # I open the chat history file.
            # Read and decode base64 data
            file_data = file.read() # I read the contents of the file.
            compressed_data = base64.b64decode(file_data) # I decode the data so the decompression can use it.

            print(f"Read {len(compressed_data)} bytes of base64-decoded data.") # This is just for visual feedback.

            # Decompress the data using lzma
            decompressed_data = lzma.decompress(compressed_data) # I decompress the data.

            print(f"Decompressed to {len(decompressed_data)} bytes.") # Again, visual feedback.

            # Extract key and encrypted data
            key = decompressed_data[:32] # I get the encryption key.
            encrypted_data = decompressed_data[32:] # I get the encrypted data.

            print(f"The key was: {base64.urlsafe_b64decode(key)}") # I display the key, only for a visual.
            print(f"The raw data was: {base64.urlsafe_b64decode(encrypted_data)}") # I display the encrypted data.

            try:
                # Decrypt and load chat history
                cipher = Fernet(base64.urlsafe_b64encode(key))  # Throws "Fernet key must be 32 url-safe base64-encoded bytes." is not decoded using base64.urlsafe_b64encode(key) first.
                decrypted_data = cipher.decrypt(encrypted_data) # Throws "InvalidToken" when I do use base64.urlsafe_b64encode(key) on the pervious statement, but it doesn't even get to this point when I don't.
                data = json.loads(decrypted_data.decode())

                self.messages = [ChatRoomMessage.ChatRoomMessage(msg['sender'], msg['content'], datetime.datetime.fromisoformat(msg['timestamp'])) for msg in data]
                self.key = key  # Remove base64 encoding here

            except InvalidToken as e:
                print(f"Error during decryption: {e}")
                # Handle the error (e.g., notify the user, log the error, etc.)

    except FileNotFoundError:
        pass

我已经尝试了很多修复方法。我尝试在程序的不同部分使用不同的方法对数据进行编码和解码,我尝试向人工智能寻求帮助,他们似乎甚至不理解这个问题,更不用说试图帮助我解决它了。

我期望发生的事情是代码获取聊天记录,将其格式化为json格式,然后我想加密数据,在数据的开头添加加密密钥(是的,这是不安全的,但我需要在考虑安全性之前让它工作),压缩数据,然后将数据保存到文件中。然后当我重新加载时,我期望它加载文件,解压文件数据,提取密钥,解密数据,采取json格式并将其转回聊天记录,然后显示聊天记录(在另一个类中处理)效果很好)。

在我添加压缩和加密之前,这个类运行得非常好!我能够保存和加载聊天记录。一旦我添加了压缩和加密,它就会不断抛出异常。这些错误似乎与我尝试解密它的时间有关,但它可能发生在解密之前或解密过程中。甚至有可能我可能漏掉了一个步骤(比如添加数据验证部分),我记得以前使用AES时,我以为我必须手动管理它。我可能是错的,但无论如何,我不确定为什么它不起作用。

这是在我保存文件之前。

这是一些示例数据。假设我在聊天窗口中说:

User: Hi!
User: HRU?

原始密钥看起来像:

b'CTbY1OCUIzgQg-IxB56gjKzeHpQh8ZsQJdPWPs_NJQA='

原始 json 数据如下所示:

b'[{"sender": "User", "content": "Hi!", "timestamp": "2023-11-27T01:54:01.430667"}, {"sender": "User", "content": "HRU?", "timestamp": "2023-11-27T01:54:03.654174"}]'

加密后的json数据如下所示:

b'Z0FBQUFBQmxaRDBOYzFJTndYX3VQdDVkSTBPc0ZyQ3lrLU5lVHFSdXZCTXRsNEw0MEpnVjhtSFhPVld0ak5kRVhYekJLakk3UmQyV3R1Nzk0VHg0SERvdWxNd0lvNkZ2cWRSeGY4UTRJUHJYRTRFM3ZNaklLc0hpN0NwVkFMT0Y5akFRUFNoMU5jcHptd1dvOHZQd1l1TWlJZ0hKaXFPX3ZjdHE5czFxcTdSTmszMFZyT01sZEM4RkE5bzZwTTVHSW5tUmRCb2EzcU1DSUJOUUgxQnoteUZxbXVKQkdEd0VzeUpLdGh3enpKbmgwbmFuM1VubF8wZWdxcUdoLWxOVTB4NTdHemc1U2ZGYmNSS0Z1N01maUoxT1Z6Wng3X21BQlpXZ2lwalU5VTBtelpYYVRZZFFnaDA9'

未压缩的文件数据如下所示:

b'CTbY1OCUIzgQg-IxB56gjKzeHpQh8ZsQJdPWPs_NJQA=Z0FBQUFBQmxaRDBOYzFJTndYX3VQdDVkSTBPc0ZyQ3lrLU5lVHFSdXZCTXRsNEw0MEpnVjhtSFhPVld0ak5kRVhYekJLakk3UmQyV3R1Nzk0VHg0SERvdWxNd0lvNkZ2cWRSeGY4UTRJUHJYRTRFM3ZNaklLc0hpN0NwVkFMT0Y5akFRUFNoMU5jcHptd1dvOHZQd1l1TWlJZ0hKaXFPX3ZjdHE5czFxcTdSTmszMFZyT01sZEM4RkE5bzZwTTVHSW5tUmRCb2EzcU1DSUJOUUgxQnoteUZxbXVKQkdEd0VzeUpLdGh3enpKbmgwbmFuM1VubF8wZWdxcUdoLWxOVTB4NTdHemc1U2ZGYmNSS0Z1N01maUoxT1Z6Wng3X21BQlpXZ2lwalU5VTBtelpYYVRZZFFnaDA9'

压缩后的文件数据如下所示:

b"\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcb\x01\x91]\x00!\x95\x08\xa8\xb2\x8f\xb1(\xb5\xcc\xd9v\xca\x93\xc2\xc3B{\x96\x9f+\x83\xa3\xab\xdcsg\x08\xb8\x0e\xed\xf8\x00y\xc3\xd42\xc0\x8bg\xa7\xd1\x06\xa1\x99\xfc\xa4\xb2G4 <\x1b\xaf\x14\xb5\x96B\x1a\xce.\xa4\xa6\xd0\xf8M\xc5\x84\xc8!\xdb\x19\xa6]U\x89\xe3\x94qA\xd2\x94\x96\xcfL\x8c\x13/\xe3P\xfa\xe89Z\x99Z\x06H'\xe7k\x85\xa1\xd0UD\x90h\xa1CI{\x96\xc5\x95\x82-\x97nS\x01\xc3\xe4\x90\xd4\x05\xb3\xf8\xa3}\xc0j\x96O\x9f\xb6\x04\x07Cu\x0e\xb5\xe8\xd7\x15r8\x9b\xf9\xdc-\xf0\x9eC\x17|\xf2\xfd\xdb\xa1d\xc5O\xaa\xe6\xd5\x07=-\xe0\xa4\xb5\xda\xc2\x03\xec\xa2\x9e\xae\xc2A\xabQ ((V\x1c\xa2\xefD\x010\xb6'\xc3\xb7k\xd8\x0eS\x17\x85\x7f-\xa9\x1d:\x1f\x01V\xb6\xe1\xba\x98+\x8801f\xa9\x13\x86$f\xc3\x1c ,G\xfc\x02QeiO\\\xa9mrAT\x9f\x8d\xe4\xc8q\xdd]y\x96[\xb1\xd5N\n\xef&\x894\x13\xf8(\xd7$Au\xddw,\x14\x07j\x02\xe1\x85F\xc0\x81\xce#P\xe4\xe0=\xd6\xb5\x14\xe5\x8f\xac\xe2K\xb3Ga\x1b\x84X\x8d\xdaw\xd0L<\x1b\xfc\x1a\x12\x1c\xd7F\x1dt \xe9=\xf5\xd3VM\xd7\xd6\xfd.\x10\xc7h\xf5>O\x9f5\x95\x0f\xd1O\x13\xd0$m\x8e\xec!\xa4\xe3}\x17OTc\x85o\xc2Z\x19+X#S\x92\xf7o\x91\x91\xb4\x8cJ\x08\xbc\xf8\x86R|p6\x1e\xc1\x87\x92O,#\xfdY\x92[\xc9nc\x1e(\xbf\xae\xbb\xef\xbfV\xb8=`\x00\x00\x00\x00\x1d\rDE\xafrKn\x00\x01\xad\x03\xcc\x03\x00\x00\xdaC\xaa\x1f\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ"

编码后的压缩文件数据如下:

b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHLAZFdACGVCKiyj7EotczZdsqTwsNCe5afK4Ojq9xzZwi4Du34AHnD1DLAi2en0Qahmfykskc0IDwbrxS1lkIazi6kptD4TcWEyCHbGaZdVYnjlHFB0pSWz0yMEy/jUProOVqZWgZIJ+drhaHQVUSQaKFDSXuWxZWCLZduUwHD5JDUBbP4o33AapZPn7YEB0N1DrXo1xVyOJv53C3wnkMXfPL926FkxU+q5tUHPS3gpLXawgPsop6uwkGrUSAoKFYcou9EATC2J8O3a9gOUxeFfy2pHTofAVa24bqYK4gwMWapE4YkZsMcICxH/AJRZWlPXKltckFUn43kyHHdXXmWW7HVTgrvJok0E/go1yRBdd13LBQHagLhhUbAgc4jUOTgPda1FOWPrOJLs0dhG4RYjdp30Ew8G/waEhzXRh10IOk99dNWTdfW/S4Qx2j1Pk+fNZUP0U8T0CRtjuwhpON9F09UY4VvwloZK1gjU5L3b5GRtIxKCLz4hlJ8cDYewYeSTywj/VmSW8luYx4ov667779WuD1gAAAAAB0NREWvcktuAAGtA8wDAADaQ6ofscRn+wIAAAAABFla'

这是我打开文件的时候

压缩后的文件数据如下所示:

b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHLAZFdACGVCKiyj7EotczZdsqTwsNCe5afK4Ojq9xzZwi4Du34AHnD1DLAi2en0Qahmfykskc0IDwbrxS1lkIazi6kptD4TcWEyCHbGaZdVYnjlHFB0pSWz0yMEy/jUProOVqZWgZIJ+drhaHQVUSQaKFDSXuWxZWCLZduUwHD5JDUBbP4o33AapZPn7YEB0N1DrXo1xVyOJv53C3wnkMXfPL926FkxU+q5tUHPS3gpLXawgPsop6uwkGrUSAoKFYcou9EATC2J8O3a9gOUxeFfy2pHTofAVa24bqYK4gwMWapE4YkZsMcICxH/AJRZWlPXKltckFUn43kyHHdXXmWW7HVTgrvJok0E/go1yRBdd13LBQHagLhhUbAgc4jUOTgPda1FOWPrOJLs0dhG4RYjdp30Ew8G/waEhzXRh10IOk99dNWTdfW/S4Qx2j1Pk+fNZUP0U8T0CRtjuwhpON9F09UY4VvwloZK1gjU5L3b5GRtIxKCLz4hlJ8cDYewYeSTywj/VmSW8luYx4ov667779WuD1gAAAAAB0NREWvcktuAAGtA8wDAADaQ6ofscRn+wIAAAAABFla'

解码后的压缩文件数据如下所示:

b"\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcb\x01\x91]\x00!\x95\x08\xa8\xb2\x8f\xb1(\xb5\xcc\xd9v\xca\x93\xc2\xc3B{\x96\x9f+\x83\xa3\xab\xdcsg\x08\xb8\x0e\xed\xf8\x00y\xc3\xd42\xc0\x8bg\xa7\xd1\x06\xa1\x99\xfc\xa4\xb2G4 <\x1b\xaf\x14\xb5\x96B\x1a\xce.\xa4\xa6\xd0\xf8M\xc5\x84\xc8!\xdb\x19\xa6]U\x89\xe3\x94qA\xd2\x94\x96\xcfL\x8c\x13/\xe3P\xfa\xe89Z\x99Z\x06H'\xe7k\x85\xa1\xd0UD\x90h\xa1CI{\x96\xc5\x95\x82-\x97nS\x01\xc3\xe4\x90\xd4\x05\xb3\xf8\xa3}\xc0j\x96O\x9f\xb6\x04\x07Cu\x0e\xb5\xe8\xd7\x15r8\x9b\xf9\xdc-\xf0\x9eC\x17|\xf2\xfd\xdb\xa1d\xc5O\xaa\xe6\xd5\x07=-\xe0\xa4\xb5\xda\xc2\x03\xec\xa2\x9e\xae\xc2A\xabQ ((V\x1c\xa2\xefD\x010\xb6'\xc3\xb7k\xd8\x0eS\x17\x85\x7f-\xa9\x1d:\x1f\x01V\xb6\xe1\xba\x98+\x8801f\xa9\x13\x86$f\xc3\x1c ,G\xfc\x02QeiO\\\xa9mrAT\x9f\x8d\xe4\xc8q\xdd]y\x96[\xb1\xd5N\n\xef&\x894\x13\xf8(\xd7$Au\xddw,\x14\x07j\x02\xe1\x85F\xc0\x81\xce#P\xe4\xe0=\xd6\xb5\x14\xe5\x8f\xac\xe2K\xb3Ga\x1b\x84X\x8d\xdaw\xd0L<\x1b\xfc\x1a\x12\x1c\xd7F\x1dt \xe9=\xf5\xd3VM\xd7\xd6\xfd.\x10\xc7h\xf5>O\x9f5\x95\x0f\xd1O\x13\xd0$m\x8e\xec!\xa4\xe3}\x17OTc\x85o\xc2Z\x19+X#S\x92\xf7o\x91\x91\xb4\x8cJ\x08\xbc\xf8\x86R|p6\x1e\xc1\x87\x92O,#\xfdY\x92[\xc9nc\x1e(\xbf\xae\xbb\xef\xbfV\xb8=`\x00\x00\x00\x00\x1d\rDE\xafrKn\x00\x01\xad\x03\xcc\x03\x00\x00\xdaC\xaa\x1f\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ"

解压后的文件数据如下:

b'CTbY1OCUIzgQg-IxB56gjKzeHpQh8ZsQJdPWPs_NJQA=Z0FBQUFBQmxaRDBOYzFJTndYX3VQdDVkSTBPc0ZyQ3lrLU5lVHFSdXZCTXRsNEw0MEpnVjhtSFhPVld0ak5kRVhYekJLakk3UmQyV3R1Nzk0VHg0SERvdWxNd0lvNkZ2cWRSeGY4UTRJUHJYRTRFM3ZNaklLc0hpN0NwVkFMT0Y5akFRUFNoMU5jcHptd1dvOHZQd1l1TWlJZ0hKaXFPX3ZjdHE5czFxcTdSTmszMFZyT01sZEM4RkE5bzZwTTVHSW5tUmRCb2EzcU1DSUJOUUgxQnoteUZxbXVKQkdEd0VzeUpLdGh3enpKbmgwbmFuM1VubF8wZWdxcUdoLWxOVTB4NTdHemc1U2ZGYmNSS0Z1N01maUoxT1Z6Wng3X21BQlpXZ2lwalU5VTBtelpYYVRZZFFnaDA9'

钥匙看起来像:

b'CTbY1OCUIzgQg-IxB56gjKzeHpQh8ZsQ'

加密后的数据如下所示:

b'JdPWPs_NJQA=Z0FBQUFBQmxaRDBOYzFJTndYX3VQdDVkSTBPc0ZyQ3lrLU5lVHFSdXZCTXRsNEw0MEpnVjhtSFhPVld0ak5kRVhYekJLakk3UmQyV3R1Nzk0VHg0SERvdWxNd0lvNkZ2cWRSeGY4UTRJUHJYRTRFM3ZNaklLc0hpN0NwVkFMT0Y5akFRUFNoMU5jcHptd1dvOHZQd1l1TWlJZ0hKaXFPX3ZjdHE5czFxcTdSTmszMFZyT01sZEM4RkE5bzZwTTVHSW5tUmRCb2EzcU1DSUJOUUgxQnoteUZxbXVKQkdEd0VzeUpLdGh3enpKbmgwbmFuM1VubF8wZWdxcUdoLWxOVTB4NTdHemc1U2ZGYmNSS0Z1N01maUoxT1Z6Wng3X21BQlpXZ2lwalU5VTBtelpYYVRZZFFnaDA9'
python encryption compression
1个回答
0
投票
import lzma
from cryptography.fernet import Fernet
import base64
import json

def export_history(key, filename='chat_history.json.enc'):
    cipher = Fernet(key) 
    print(f"export_history: {key=}")
    encrypted_data = base64.b64encode(cipher.encrypt(json.dumps([msg for msg in messages]).encode())) 
    print(f"export_history: {encrypted_data=}")
    file_data = key + encrypted_data
    print(f"export_history: {file_data=}")
    compressed_data = lzma.compress(file_data) 
    print(f"export_history: {compressed_data=}")
    encoded_data = base64.b64encode(compressed_data) 
    print(f"export_history: {encoded_data=}")

    
    with lzma.open(filename, 'wb') as file: 
        file.write(encoded_data) 


def import_history( filename='chat_history.json.enc'):
    try:
        
        with lzma.open(filename, 'rb') as file: 
            
            file_data = file.read()
            print(f"import_history: {file_data=}")
            compressed_data = base64.b64decode(file_data) 
            print(f"import_history: {compressed_data=}")
            decompressed_data = lzma.decompress(compressed_data) 
            print(f"import_history: {decompressed_data=}")
            key = decompressed_data[:32] 
            print(f"import_history: {key=}")
            encrypted_data = decompressed_data[32:] 
            print(f"import_history: {encrypted_data=}")
            try:
                cipher = Fernet(base64.urlsafe_b64encode(key))  
                decrypted_data = cipher.decrypt(encrypted_data) 
                print(f"import_history: {decrypted_data=}")
                data = json.loads(decrypted_data.decode())
                print(f"import_history: {data=}")
            except Exception as e:
                print(f"Error during decryption: {e}")
                

    except FileNotFoundError:
        pass


def main():
    key = Fernet.generate_key()
    
    export_history(key)
    import_history()

messages = [{"sender": "User", "content": "Hi!", "timestamp": "2023-11-27T01:54:01.430667"}, {"sender": "User", "content": "HRU?", "timestamp": "2023-11-27T01:54:03.654174"}]

if __name__ == '__main__':
    main()

如果您打印变量值而不进行任何类型的转换,您将看到两个函数上应匹配的变量的不同之处。

这是我发布的代码的输出:

export_history: key=b'9xlL0bYJkoLlh7GpMk81ee4Wuts9TQY-wzQMszn9mdE='
export_history: encrypted_data=b'Z0FBQUFBQmxaRVp0SXA1SmgxMldhcmxCaVRQQklxS1QxSFg4ZlVNUzZMckp0QVQ3TzFKNWRFaFhpTkdBTldYMW50RGEtYjRHRUxROEl2aklwZmt6d0JZUldLYURzLW1Ia3Y2NXNPQjdmdlVpMlVnTER6VGtsWkFIdEdXN2Z6VjZGdFBCREdEcjR4NUtWckZ4cjd4ZE40cGdBWWFPd3EzbWpXTTU0QVRhM2tUbkJTU2RsNzVleDVmaGY5Qzl3YV9pU3p6TFRVSlVJTFBidWRCWS1mZGNVVVF1X1lvblRrRXFZTUswWmdTZDhGN05MZFdzT3h3YnJ6aWJQaGpTZ216MVpXZmx5OHFwcEQxVmp5R3ZadFZadzYyaHZSZ05nOUo1bGo1NE9yN01PbTY3Q08zWXJRQWVLRms9'
export_history: file_data=b'9xlL0bYJkoLlh7GpMk81ee4Wuts9TQY-wzQMszn9mdE=Z0FBQUFBQmxaRVp0SXA1SmgxMldhcmxCaVRQQklxS1QxSFg4ZlVNUzZMckp0QVQ3TzFKNWRFaFhpTkdBTldYMW50RGEtYjRHRUxROEl2aklwZmt6d0JZUldLYURzLW1Ia3Y2NXNPQjdmdlVpMlVnTER6VGtsWkFIdEdXN2Z6VjZGdFBCREdEcjR4NUtWckZ4cjd4ZE40cGdBWWFPd3EzbWpXTTU0QVRhM2tUbkJTU2RsNzVleDVmaGY5Qzl3YV9pU3p6TFRVSlVJTFBidWRCWS1mZGNVVVF1X1lvblRrRXFZTUswWmdTZDhGN05MZFdzT3h3YnJ6aWJQaGpTZ216MVpXZmx5OHFwcEQxVmp5R3ZadFZadzYyaHZSZ05nOUo1bGo1NE9yN01PbTY3Q08zWXJRQWVLRms9'
export_history: compressed_data=b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcb\x01\x8f]\x00\x1c\x9e\t\x84\xc6e\xae\xe2\xd5\x9b\x01>\xa3\xc0>#\xe8k\x80\x18\xa3s\xa1(%K\x1b\xbcy\xfc\xf4\xd9#\xd8\xe6\x06!h\\\x9d\xbb\xc5p\xb4\xbf\xe3\xa2\x15|\x18\xf3\xc9j\xa7\xb4\xc7\x16k<\xd4\xe8\xf0]\x13\xf4P\x01\x7f\xf4#tG\x82\xf9\x86\xa6\xd4\x1e\xf8W\xce\xc9d`\n\xbe\x80za\x93&\xdb\xb0\x90\x95\x8c\xb50\x95\xb5\x8f\xd4\xeb\x8c$\xb6_\xb0ge\xa9m\xec\x00^\xe2\x98R{\x96"J\x8e\x97\xa7\x8ch\x15\x17\xb13s8\xfd\xb4Hd\x11J\xfb_\x81\xa1\x1a\x0b`+\xd0%\x14\xfcZ]\x92\xdcV\xa8\xcf\x12\xd4\x1d;J\x1a}\xc7\xec\xb1^b\x1e\x1b\x96\x98i\x9d\r;\xda\xc3\x9e_\x9a\x0fj\x0c9[\xfci\xbap\xe2i%\x7f\xf0k\xfdL\xd3\xc2\x1d\xf4Jh\xbfE\x85\xe7\xc5\xa7\x83\x83g/\xa4\x97\xb9\xe29\xc4D6\xa3z\xb6\r\xd3z\xb3\xa6\xb5\x86\x8f\xaa\x83\x86\x9ex\x96\x96\x17pU\xdd\x06\xae\x06\xf8\xf2\xc39f\x1bV\xfc\x07\x8fZ\xa1\x94\xd6\xf3\xdbt\te\x9dH\x8d\xb5A\xce\xf8\xde\xc4J\xac\xef\xca\xdcL\x153\nR\xfa\x9b~\xa0rD\x98\\\xa2\xbc#KA\xdb\x17\xa3=\xa9\xa7\xb3j\xcf\xef\x90\xe4\xa9K\xd6\xf5p\x84#\xf1\xfb\x91\x0b\xd3\xb5\xef-\xff\x13\xcd\xbe\xf0/`\xae\xa2\x8c\xf6CUr\xa9\x97;>\xac\xa4OQ_\n\x0e\xab\n\xecJ\x96_v\xa3\x82\x01\xae\x12C$v\xe6`3\xbe\x82\x85\x05\x87e\xceV\xc3:\xc2\xa3\x19\xd7\xf5*\xe0+\xbf\xc5\x909\xef\xf4\xfa\xed\xa7\xea@\x00\x00\xf0\xaf\xeb\x8av\xce\xb8\xe9\x00\x01\xab\x03\xcc\x03\x00\x00\xc7\xa0\xf3\xc9\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ'
export_history: encoded_data=b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHLAY9dAByeCYTGZa7i1ZsBPqPAPiPoa4AYo3OhKCVLG7x5/PTZI9jmBiFoXJ27xXC0v+OiFXwY88lqp7THFms81OjwXRP0UAF/9CN0R4L5hqbUHvhXzslkYAq+gHphkybbsJCVjLUwlbWP1OuMJLZfsGdlqW3sAF7imFJ7liJKjpenjGgVF7Ezczj9tEhkEUr7X4GhGgtgK9AlFPxaXZLcVqjPEtQdO0oafcfssV5iHhuWmGmdDTvaw55fmg9qDDlb/Gm6cOJpJX/wa/1M08Id9Epov0WF58Wng4NnL6SXueI5xEQ2o3q2DdN6s6a1ho+qg4aeeJaWF3BV3QauBvjywzlmG1b8B49aoZTW89t0CWWdSI21Qc743sRKrO/K3EwVMwpS+pt+oHJEmFyivCNLQdsXoz2pp7Nqz++Q5KlL1vVwhCPx+5EL07XvLf8Tzb7wL2Cuooz2Q1VyqZc7PqykT1FfCg6rCuxKll92o4IBrhJDJHbmYDO+goUFh2XOVsM6wqMZ1/Uq4Cu/xZA57/T67afqQAAA8K/rinbOuOkAAasDzAMAAMeg88mxxGf7AgAAAAAEWVo='
import_history: file_data=b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHLAY9dAByeCYTGZa7i1ZsBPqPAPiPoa4AYo3OhKCVLG7x5/PTZI9jmBiFoXJ27xXC0v+OiFXwY88lqp7THFms81OjwXRP0UAF/9CN0R4L5hqbUHvhXzslkYAq+gHphkybbsJCVjLUwlbWP1OuMJLZfsGdlqW3sAF7imFJ7liJKjpenjGgVF7Ezczj9tEhkEUr7X4GhGgtgK9AlFPxaXZLcVqjPEtQdO0oafcfssV5iHhuWmGmdDTvaw55fmg9qDDlb/Gm6cOJpJX/wa/1M08Id9Epov0WF58Wng4NnL6SXueI5xEQ2o3q2DdN6s6a1ho+qg4aeeJaWF3BV3QauBvjywzlmG1b8B49aoZTW89t0CWWdSI21Qc743sRKrO/K3EwVMwpS+pt+oHJEmFyivCNLQdsXoz2pp7Nqz++Q5KlL1vVwhCPx+5EL07XvLf8Tzb7wL2Cuooz2Q1VyqZc7PqykT1FfCg6rCuxKll92o4IBrhJDJHbmYDO+goUFh2XOVsM6wqMZ1/Uq4Cu/xZA57/T67afqQAAA8K/rinbOuOkAAasDzAMAAMeg88mxxGf7AgAAAAAEWVo='
import_history: compressed_data=b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcb\x01\x8f]\x00\x1c\x9e\t\x84\xc6e\xae\xe2\xd5\x9b\x01>\xa3\xc0>#\xe8k\x80\x18\xa3s\xa1(%K\x1b\xbcy\xfc\xf4\xd9#\xd8\xe6\x06!h\\\x9d\xbb\xc5p\xb4\xbf\xe3\xa2\x15|\x18\xf3\xc9j\xa7\xb4\xc7\x16k<\xd4\xe8\xf0]\x13\xf4P\x01\x7f\xf4#tG\x82\xf9\x86\xa6\xd4\x1e\xf8W\xce\xc9d`\n\xbe\x80za\x93&\xdb\xb0\x90\x95\x8c\xb50\x95\xb5\x8f\xd4\xeb\x8c$\xb6_\xb0ge\xa9m\xec\x00^\xe2\x98R{\x96"J\x8e\x97\xa7\x8ch\x15\x17\xb13s8\xfd\xb4Hd\x11J\xfb_\x81\xa1\x1a\x0b`+\xd0%\x14\xfcZ]\x92\xdcV\xa8\xcf\x12\xd4\x1d;J\x1a}\xc7\xec\xb1^b\x1e\x1b\x96\x98i\x9d\r;\xda\xc3\x9e_\x9a\x0fj\x0c9[\xfci\xbap\xe2i%\x7f\xf0k\xfdL\xd3\xc2\x1d\xf4Jh\xbfE\x85\xe7\xc5\xa7\x83\x83g/\xa4\x97\xb9\xe29\xc4D6\xa3z\xb6\r\xd3z\xb3\xa6\xb5\x86\x8f\xaa\x83\x86\x9ex\x96\x96\x17pU\xdd\x06\xae\x06\xf8\xf2\xc39f\x1bV\xfc\x07\x8fZ\xa1\x94\xd6\xf3\xdbt\te\x9dH\x8d\xb5A\xce\xf8\xde\xc4J\xac\xef\xca\xdcL\x153\nR\xfa\x9b~\xa0rD\x98\\\xa2\xbc#KA\xdb\x17\xa3=\xa9\xa7\xb3j\xcf\xef\x90\xe4\xa9K\xd6\xf5p\x84#\xf1\xfb\x91\x0b\xd3\xb5\xef-\xff\x13\xcd\xbe\xf0/`\xae\xa2\x8c\xf6CUr\xa9\x97;>\xac\xa4OQ_\n\x0e\xab\n\xecJ\x96_v\xa3\x82\x01\xae\x12C$v\xe6`3\xbe\x82\x85\x05\x87e\xceV\xc3:\xc2\xa3\x19\xd7\xf5*\xe0+\xbf\xc5\x909\xef\xf4\xfa\xed\xa7\xea@\x00\x00\xf0\xaf\xeb\x8av\xce\xb8\xe9\x00\x01\xab\x03\xcc\x03\x00\x00\xc7\xa0\xf3\xc9\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ'
import_history: decompressed_data=b'9xlL0bYJkoLlh7GpMk81ee4Wuts9TQY-wzQMszn9mdE=Z0FBQUFBQmxaRVp0SXA1SmgxMldhcmxCaVRQQklxS1QxSFg4ZlVNUzZMckp0QVQ3TzFKNWRFaFhpTkdBTldYMW50RGEtYjRHRUxROEl2aklwZmt6d0JZUldLYURzLW1Ia3Y2NXNPQjdmdlVpMlVnTER6VGtsWkFIdEdXN2Z6VjZGdFBCREdEcjR4NUtWckZ4cjd4ZE40cGdBWWFPd3EzbWpXTTU0QVRhM2tUbkJTU2RsNzVleDVmaGY5Qzl3YV9pU3p6TFRVSlVJTFBidWRCWS1mZGNVVVF1X1lvblRrRXFZTUswWmdTZDhGN05MZFdzT3h3YnJ6aWJQaGpTZ216MVpXZmx5OHFwcEQxVmp5R3ZadFZadzYyaHZSZ05nOUo1bGo1NE9yN01PbTY3Q08zWXJRQWVLRms9'
import_history: key=b'9xlL0bYJkoLlh7GpMk81ee4Wuts9TQY-'
import_history: encrypted_data=b'wzQMszn9mdE=Z0FBQUFBQmxaRVp0SXA1SmgxMldhcmxCaVRQQklxS1QxSFg4ZlVNUzZMckp0QVQ3TzFKNWRFaFhpTkdBTldYMW50RGEtYjRHRUxROEl2aklwZmt6d0JZUldLYURzLW1Ia3Y2NXNPQjdmdlVpMlVnTER6VGtsWkFIdEdXN2Z6VjZGdFBCREdEcjR4NUtWckZ4cjd4ZE40cGdBWWFPd3EzbWpXTTU0QVRhM2tUbkJTU2RsNzVleDVmaGY5Qzl3YV9pU3p6TFRVSlVJTFBidWRCWS1mZGNVVVF1X1lvblRrRXFZTUswWmdTZDhGN05MZFdzT3h3YnJ6aWJQaGpTZ216MVpXZmx5OHFwcEQxVmp5R3ZadFZadzYyaHZSZ05nOUo1bGo1NE9yN01PbTY3Q08zWXJRQWVLRms9'

在任何突出显示所选文本的其他实例(例如 VSCode)的 IDE 中,您会看到导出和导入中的密钥最多只匹配

9xlL0bYJkoLlh7GpMk81ee4Wuts9TQY-

您使用

key = decompressed_data[:32]
,但 32 个字节是在密钥编码为 Base64 之前。

导出时,您可以在

file_data
的开头添加
key
的字节数,或者只是添加一个空格作为分隔符,如
file_data = key + ' ' + encrypted_data

这里将密钥的长度添加到写入文件的数据的开头。

# on export

key_size_in_bytes = len(key)
print(f"export_history: {key_size_in_bytes=}")
key_size_in_bytes_repr = key_size_in_bytes.to_bytes(2, byteorder='big')
print(f"export_history: {key_size_in_bytes_repr=}")
file_data = key_size_in_bytes_repr + key + encrypted_data


# on import
key_size_bytes = int.from_bytes(decompressed_data[:2], byteorder='big')
print(f"import_history: {key_size_bytes=}")

key_base64 = decompressed_data[2:key_size_bytes+2].decode('utf-8')
print(f"import_history: {key_base64=}")

encrypted_data = decompressed_data[key_size_bytes+2:]
print(f"import_history: {encrypted_data=}")

由于您已经在

key_base64
中拥有了 base64 密钥,因此您必须进行更改

# this
cipher = Fernet(base64.urlsafe_b64decode(key)) 

# to
cipher = Fernet(key_base64)

现在经过所有这些更改,您仍然会收到错误:

cryptography.fernet.InvalidToken

这可能很难找到,因为您如何嵌套函数调用,如

encrypted_data = base64.b64encode(cipher.encrypt(json.dumps([msg for msg in messages]).encode())) 

# Change json.dumps([msg for msg in messages]).encode() to string for easier reading

encrypted_data = base64.b64encode(cipher.encrypt(string))

首先对字符串进行加密,然后对其进行 Base64 编码。然后对其进行压缩并进行 Base64 编码,然后写入文件,因此导出的步骤是:

  • 字符串(json.dumps)
  • 密码.加密
  • base64.b64编码
  • lzma.压缩
  • base64.b64编码

但是导入步骤是:

  • base64.b64解码
  • lzma.解压缩
  • 密码.解密
  • 字符串(json.loads)

如果每个步骤都单独占一行,那么就很容易看出。

所以在

cipher.decrypt
之前我们必须再次解码base64:

base64_decoded_encrypted_data = base64.b64decode(encrypted_data)
decrypted_data = cipher.decrypt(base64_decoded_encrypted_data)

这是打印的最终完整输出:

export_history: key=b'NlxKPLoEnHCY45LaZkb0yyyvj5oemOYlCraqWIW5Nbw='
export_history: encrypted_data=b'Z0FBQUFBQmxaRTZVU05HZTlac3VtaGo0cFFQV0dmYURtZVJjQ25VSW9iM1Q5cFo5aGRQVm5MMEZnY1BPUVI0bmpjeXdYVWUxa1hkb1NPNnBCekszTVlNcHlIYXBaTkFvRTgtRExZWXA5MHBlVjY4dXQtR01tdTI1MXI1b1RWLTdIeFhPekN0MnhWcHFNR3E3SWZKUlJTaU8tSm13S2hCVkVPVHFqMzBHSDVVYTBZeG9KWUhTZTZoLU0zMUdaNFhNanB3aml1dDBMY3JkeG1FZ3RrVGN1NzF1dXpHWWRfQUI5Wl9PZ3Voa1hIWmdDQndZaGRDYllURmRoWGx6OGFiRUdGWVB0M0p5NmRWWGNrU19TOXYwdTQ4MnVLdHR3Vlh5RzlUZWFjTzFZUnU1cnIzcGZqZWVWUW89'
export_history: key_size_in_bytes=44
export_history: key_size_in_bytes_repr=b'\x00,'
export_history: file_data=b'\x00,NlxKPLoEnHCY45LaZkb0yyyvj5oemOYlCraqWIW5Nbw=Z0FBQUFBQmxaRTZVU05HZTlac3VtaGo0cFFQV0dmYURtZVJjQ25VSW9iM1Q5cFo5aGRQVm5MMEZnY1BPUVI0bmpjeXdYVWUxa1hkb1NPNnBCekszTVlNcHlIYXBaTkFvRTgtRExZWXA5MHBlVjY4dXQtR01tdTI1MXI1b1RWLTdIeFhPekN0MnhWcHFNR3E3SWZKUlJTaU8tSm13S2hCVkVPVHFqMzBHSDVVYTBZeG9KWUhTZTZoLU0zMUdaNFhNanB3aml1dDBMY3JkeG1FZ3RrVGN1NzF1dXpHWWRfQUI5Wl9PZ3Voa1hIWmdDQndZaGRDYllURmRoWGx6OGFiRUdGWVB0M0p5NmRWWGNrU19TOXYwdTQ4MnVLdHR3Vlh5RzlUZWFjTzFZUnU1cnIzcGZqZWVWUW89'
export_history: compressed_data=b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcd\x01\x8f]\x00\x00\x0b\xe7%\x1a\x17 \x92\xb9\xa6Dtd\x11E\xf5U\xd1\xf2\xbf\xe5`.m\xe2\xf05%\xffN\x8d \xd5\xd6\xddM\x1c \x06\x8dFg\xa2\x1a\xa7\x1e\x85~hF\x84\x99\xf1\xbf\x048\x08\xb8\xde\xe3\x96\x169\x83\x17\x03\xe2\xca\x10\xbc\x8cI\xb552\x98\x0e4@\xb9]\xc2\xe9,\xbf\xae\xdb6|\xfd\x1b1\xa6\xd6\x1fv8\xa7\xacQ\xbb\x8a\xcd\xdc\xad\x07\x8c\x86\xc2U\x7f\x8b\xf1\x89\xa1\xee\x0f\xb4\x1c8%\x17HS*\x1b\x07<\xc1\xae+a\x84\xf8\x85\x00\xbe\x9e\x17\xa0\xc0\xd5E W=f\x1cY\x15\xa5E\xda\xb5^CJ\xec\xa8.\xfer\x80\xa7\xf41\xd6G\xc5w\xba\x9b\xa5WL}j\xf5l\x9c\x88K\xbbh\xf2NK\x01\xbfS\x06\xce1\xa66M\x88E\xe9i}P\xe6\x14\x8aI5Y\x9b.\x0eTz\xcb\xd6\xd1\xd9\xdf^\xe6?\x0eQ22\x1a\x15b\xa3\xb0\xdc:\xc6\x05\x91\xbdxu\x02\xab\xba%8%\xdb8\x99O\xb7\x8a\x9f+{f\xbe\xd6/9I\xea\x0f\xf3\x19H{\xe3\x8a8c\xd9\xb9\xbb\x9d\x1a\xe3Y \xbfF\x8b\x87\xd3\xc0.\x89d\xc5\xf3\x18\x03v\x9f\xa8\x1cS\xe0\xa9\x8f\x9b\\Z[\x87\xf5l\xf9\xb3g\x80\x14\x97\x1c\xf1\xaf\xf4\x7f\xf9\x10\x96>\x18\xf1Z\x1c\xf8f\x119\x1cKi\x9d\xfe\xf2\xad"\xae\x9e]\xf3\xdc\\/K\x16\x90\x1f\xa7.uWZgS*s\x9a\x82\xd1"y\xd4\x1e\xd7WA\xf2\xaey\x0e\xb3\x96\x98\xdc\xf1\xb5\xec\xea]I\xe7|\x88\x01&\x11:\x7f\xc4\x12\x8cj\x88\xa1\xe7\x1d\xa1.\xf6\x00\x00*\xc1\xf0\xe8 vb\x98\x00\x01\xab\x03\xce\x03\x00\x00Lh\xfac\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ'     
export_history: encoded_data=b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHNAY9dAAAL5yUaFyCSuaZEdGQRRfVV0fK/5WAubeLwNSX/To0g1dbdTRwgBo1GZ6Iapx6FfmhGhJnxvwQ4CLje45YWOYMXA+LKELyMSbU1MpgONEC5XcLpLL+u2zZ8/RsxptYfdjinrFG7is3crQeMhsJVf4vxiaHuD7QcOCUXSFMqGwc8wa4rYYT4hQC+nhegwNVFIFc9ZhxZFaVF2rVeQ0rsqC7+coCn9DHWR8V3upulV0x9avVsnIhLu2jyTksBv1MGzjGmNk2IRelpfVDmFIpJNVmbLg5UesvW0dnfXuY/DlEyMhoVYqOw3DrGBZG9eHUCq7olOCXbOJlPt4qfK3tmvtYvOUnqD/MZSHvjijhj2bm7nRrjWSC/RouH08AuiWTF8xgDdp+oHFPgqY+bXFpbh/Vs+bNngBSXHPGv9H/5EJY+GPFaHPhmETkcS2md/vKtIq6eXfPcXC9LFpAfpy51V1pnUypzmoLRInnUHtdXQfKueQ6zlpjc8bXs6l1J53yIASYROn/EEoxqiKHnHaEu9gAAKsHw6CB2YpgAAasDzgMAAExo+mOxxGf7AgAAAAAEWVo='
import_history: file_data=b'/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4AHNAY9dAAAL5yUaFyCSuaZEdGQRRfVV0fK/5WAubeLwNSX/To0g1dbdTRwgBo1GZ6Iapx6FfmhGhJnxvwQ4CLje45YWOYMXA+LKELyMSbU1MpgONEC5XcLpLL+u2zZ8/RsxptYfdjinrFG7is3crQeMhsJVf4vxiaHuD7QcOCUXSFMqGwc8wa4rYYT4hQC+nhegwNVFIFc9ZhxZFaVF2rVeQ0rsqC7+coCn9DHWR8V3upulV0x9avVsnIhLu2jyTksBv1MGzjGmNk2IRelpfVDmFIpJNVmbLg5UesvW0dnfXuY/DlEyMhoVYqOw3DrGBZG9eHUCq7olOCXbOJlPt4qfK3tmvtYvOUnqD/MZSHvjijhj2bm7nRrjWSC/RouH08AuiWTF8xgDdp+oHFPgqY+bXFpbh/Vs+bNngBSXHPGv9H/5EJY+GPFaHPhmETkcS2md/vKtIq6eXfPcXC9LFpAfpy51V1pnUypzmoLRInnUHtdXQfKueQ6zlpjc8bXs6l1J53yIASYROn/EEoxqiKHnHaEu9gAAKsHw6CB2YpgAAasDzgMAAExo+mOxxGf7AgAAAAAEWVo='
import_history: compressed_data=b'\xfd7zXZ\x00\x00\x04\xe6\xd6\xb4F\x02\x00!\x01\x16\x00\x00\x00t/\xe5\xa3\xe0\x01\xcd\x01\x8f]\x00\x00\x0b\xe7%\x1a\x17 \x92\xb9\xa6Dtd\x11E\xf5U\xd1\xf2\xbf\xe5`.m\xe2\xf05%\xffN\x8d \xd5\xd6\xddM\x1c \x06\x8dFg\xa2\x1a\xa7\x1e\x85~hF\x84\x99\xf1\xbf\x048\x08\xb8\xde\xe3\x96\x169\x83\x17\x03\xe2\xca\x10\xbc\x8cI\xb552\x98\x0e4@\xb9]\xc2\xe9,\xbf\xae\xdb6|\xfd\x1b1\xa6\xd6\x1fv8\xa7\xacQ\xbb\x8a\xcd\xdc\xad\x07\x8c\x86\xc2U\x7f\x8b\xf1\x89\xa1\xee\x0f\xb4\x1c8%\x17HS*\x1b\x07<\xc1\xae+a\x84\xf8\x85\x00\xbe\x9e\x17\xa0\xc0\xd5E W=f\x1cY\x15\xa5E\xda\xb5^CJ\xec\xa8.\xfer\x80\xa7\xf41\xd6G\xc5w\xba\x9b\xa5WL}j\xf5l\x9c\x88K\xbbh\xf2NK\x01\xbfS\x06\xce1\xa66M\x88E\xe9i}P\xe6\x14\x8aI5Y\x9b.\x0eTz\xcb\xd6\xd1\xd9\xdf^\xe6?\x0eQ22\x1a\x15b\xa3\xb0\xdc:\xc6\x05\x91\xbdxu\x02\xab\xba%8%\xdb8\x99O\xb7\x8a\x9f+{f\xbe\xd6/9I\xea\x0f\xf3\x19H{\xe3\x8a8c\xd9\xb9\xbb\x9d\x1a\xe3Y \xbfF\x8b\x87\xd3\xc0.\x89d\xc5\xf3\x18\x03v\x9f\xa8\x1cS\xe0\xa9\x8f\x9b\\Z[\x87\xf5l\xf9\xb3g\x80\x14\x97\x1c\xf1\xaf\xf4\x7f\xf9\x10\x96>\x18\xf1Z\x1c\xf8f\x119\x1cKi\x9d\xfe\xf2\xad"\xae\x9e]\xf3\xdc\\/K\x16\x90\x1f\xa7.uWZgS*s\x9a\x82\xd1"y\xd4\x1e\xd7WA\xf2\xaey\x0e\xb3\x96\x98\xdc\xf1\xb5\xec\xea]I\xe7|\x88\x01&\x11:\x7f\xc4\x12\x8cj\x88\xa1\xe7\x1d\xa1.\xf6\x00\x00*\xc1\xf0\xe8 vb\x98\x00\x01\xab\x03\xce\x03\x00\x00Lh\xfac\xb1\xc4g\xfb\x02\x00\x00\x00\x00\x04YZ'     
import_history: decompressed_data=b'\x00,NlxKPLoEnHCY45LaZkb0yyyvj5oemOYlCraqWIW5Nbw=Z0FBQUFBQmxaRTZVU05HZTlac3VtaGo0cFFQV0dmYURtZVJjQ25VSW9iM1Q5cFo5aGRQVm5MMEZnY1BPUVI0bmpjeXdYVWUxa1hkb1NPNnBCekszTVlNcHlIYXBaTkFvRTgtRExZWXA5MHBlVjY4dXQtR01tdTI1MXI1b1RWLTdIeFhPekN0MnhWcHFNR3E3SWZKUlJTaU8tSm13S2hCVkVPVHFqMzBHSDVVYTBZeG9KWUhTZTZoLU0zMUdaNFhNanB3aml1dDBMY3JkeG1FZ3RrVGN1NzF1dXpHWWRfQUI5Wl9PZ3Voa1hIWmdDQndZaGRDYllURmRoWGx6OGFiRUdGWVB0M0p5NmRWWGNrU19TOXYwdTQ4MnVLdHR3Vlh5RzlUZWFjTzFZUnU1cnIzcGZqZWVWUW89'
import_history: key_size_bytes=44
import_history: key_base64='NlxKPLoEnHCY45LaZkb0yyyvj5oemOYlCraqWIW5Nbw='
import_history: encrypted_data=b'Z0FBQUFBQmxaRTZVU05HZTlac3VtaGo0cFFQV0dmYURtZVJjQ25VSW9iM1Q5cFo5aGRQVm5MMEZnY1BPUVI0bmpjeXdYVWUxa1hkb1NPNnBCekszTVlNcHlIYXBaTkFvRTgtRExZWXA5MHBlVjY4dXQtR01tdTI1MXI1b1RWLTdIeFhPekN0MnhWcHFNR3E3SWZKUlJTaU8tSm13S2hCVkVPVHFqMzBHSDVVYTBZeG9KWUhTZTZoLU0zMUdaNFhNanB3aml1dDBMY3JkeG1FZ3RrVGN1NzF1dXpHWWRfQUI5Wl9PZ3Voa1hIWmdDQndZaGRDYllURmRoWGx6OGFiRUdGWVB0M0p5NmRWWGNrU19TOXYwdTQ4MnVLdHR3Vlh5RzlUZWFjTzFZUnU1cnIzcGZqZWVWUW89'
import_history: decrypted_data=b'[{"sender": "User", "content": "Hi!", "timestamp": "2023-11-27T01:54:01.430667"}, {"sender": "User", "content": "HRU?", "timestamp": "2023-11-27T01:54:03.654174"}]'
import_history: data=[{'sender': 'User', 'content': 'Hi!', 'timestamp': '2023-11-27T01:54:01.430667'}, {'sender': 'User', 'content': 'HRU?', 'timestamp': '2023-11-27T01:54:03.654174'}]

以及整个代码:

import lzma
from cryptography.fernet import Fernet
import base64
import json

def export_history(key, filename='chat_history.json.enc'):
    cipher = Fernet(key) 
    print(f"export_history: {key=}")
    encrypted_data = base64.b64encode(cipher.encrypt(json.dumps([msg for msg in messages]).encode())) 
    print(f"export_history: {encrypted_data=}")
    
    key_size_in_bytes = len(key)
    print(f"export_history: {key_size_in_bytes=}")
    key_size_in_bytes_repr = key_size_in_bytes.to_bytes(2, byteorder='big')
    print(f"export_history: {key_size_in_bytes_repr=}")
    
    file_data = key_size_in_bytes_repr + key + encrypted_data
    print(f"export_history: {file_data=}")
    compressed_data = lzma.compress(file_data) 
    print(f"export_history: {compressed_data=}")
    encoded_data = base64.b64encode(compressed_data) 
    print(f"export_history: {encoded_data=}")

    
    with lzma.open(filename, 'wb') as file: 
        file.write(encoded_data) 


def import_history( filename='chat_history.json.enc'):
    try:
        
        with lzma.open(filename, 'rb') as file: 
            
            file_data = file.read()
            print(f"import_history: {file_data=}")
            compressed_data = base64.b64decode(file_data) 
            print(f"import_history: {compressed_data=}")
            decompressed_data = lzma.decompress(compressed_data) 
            print(f"import_history: {decompressed_data=}")
            
            key_size_bytes = int.from_bytes(decompressed_data[:2], byteorder='big')
            print(f"import_history: {key_size_bytes=}")
            
            key_base64 = decompressed_data[2:key_size_bytes+2].decode('utf-8')
            print(f"import_history: {key_base64=}")
            
            encrypted_data = decompressed_data[key_size_bytes+2:]
            print(f"import_history: {encrypted_data=}")
            
            base64_decoded_encrypted_data = base64.b64decode(encrypted_data)
            
            cipher = Fernet(key_base64)  
            decrypted_data = cipher.decrypt(base64_decoded_encrypted_data) 
            print(f"import_history: {decrypted_data=}")
            data = json.loads(decrypted_data.decode())
            print(f"import_history: {data=}")
                

    except FileNotFoundError:
        pass


def main():
    key = Fernet.generate_key()
    
    export_history(key)
    import_history()

messages = [{"sender": "User", "content": "Hi!", "timestamp": "2023-11-27T01:54:01.430667"}, {"sender": "User", "content": "HRU?", "timestamp": "2023-11-27T01:54:03.654174"}]

if __name__ == '__main__':
    main()

PS:在我的代码中,我使用

Fernet.generate_key()
,它只返回
base64.urlsafe_b64encode(os.urandom(32))

© www.soinside.com 2019 - 2024. All rights reserved.