Cryptography token object raises exception and cannot decrypt even though the tokens are identical
Asked Answered
I

2

6

code overview: The tokens are identical, but in between encryption and decryption, the encrypted object is stored into a module-level dictionary--still, the encryption token does not change.

Why won't this work? I imagine there are things behind the scenes regarding the encrypted object that make it unique, but I would have assumed all it needs is the correct key for the decryption to work.

Here is the minimal related code:

import sys
from cryptography.fernet import Fernet
import json
import os

key = Fernet.generate_key()
f = Fernet(key)


with open("storage.json", "a+") as file:
    if os.stat("storage.json").st_size == 0:
        file.write("{}")
    file.seek(0)
    storage = json.load(file)


def write(data):
    with open("storage.json", "w") as file:
        json.dump(data, file)


def encrypt(pw):
    token = f.encrypt(bytes(pw, "utf-8"))
    return token


def decrypt(token):
    return f.decrypt(token)

if len(sys.argv) == 1:
    to_encrypt = input("A key to encrypt: ")
    storage[to_encrypt] = encrypt(to_encrypt).decode("utf-8")
    print("encrypted:", storage[to_encrypt])
    # print("storage:", storage)
    try:
        write(storage)
    except Exception as e:
        print("error:", e)

elif len(sys.argv) == 2:
    to_decrypt = input("Key to decrypt: ")
    # print(storage[to_d])
    print("decrypted:", f.decrypt(bytes(storage[to_decrypt], "utf-8")))

To make it work: run the program with no arguments--it will create a json file, input your string and its encryption into the file, and exit.
Then, run the program passing any single argument. Try to obtain the same string you previously input.

This traceback should occur:

Traceback (most recent call last):
  File "/Users/sjung/lib/python3.5/site-packages/cryptography/fernet.py", line 101, in decrypt
    h.verify(data[-32:])
  File "/Users/sjung/lib/python3.5/site-packages/cryptography/hazmat/primitives/hmac.py", line 69, in verify
    ctx.verify(signature)
  File "/Users/sjung/lib/python3.5/site-packages/cryptography/hazmat/backends/openssl/hmac.py", line 73, in verify
    raise InvalidSignature("Signature did not match digest.")
cryptography.exceptions.InvalidSignature: Signature did not match digest.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test_a.py", line 43, in <module>
    print("decrypted:", f.decrypt(bytes(storage[to_decrypt], "utf-8")))
  File "/Users/sjung/lib/python3.5/site-packages/cryptography/fernet.py", line 103, in decrypt
    raise InvalidToken
cryptography.fernet.InvalidToken

edit: comment out the elif line to try it without exiting the system. This does work.

Interlaminate answered 13/10, 2017 at 18:24 Comment(1)
Aside: deep nested calls such as print("decrypted:", f.decrypt(bytes(storage[to_decrypt], "utf-8"))) are hard to debug, instead use multiple steps and intermediate variables. Then trace execution in a debugger or add print statements for the intermediate values. Also the line number in error messages will provide a better idea of there the actual error is.Ferreous
I
5

The key generated by Fernet.generate_key() must also be the same key when decrypting. My example code has been creating a new key every time.

https://github.com/pyca/cryptography/issues/3982

Interlaminate answered 13/10, 2017 at 19:50 Comment(2)
how to generate the same key?Repossess
after generating, check your files. you can find the resulting key and use it again.Interlaminate
Q
0

Old question but it was the first search result.

Here's a simplified reproduction of the problem:

>>> from cryptography.fernet import Fernet
>>> key = Fernet.generate_key()
>>> fernet = Fernet(key)
>>>
>>>
>>> encrypted = fernet.encrypt(bytes("something to be encrypted", "utf-8"))
>>> encrypted
b'gAAAAABihhpoZvERjEo65o09n0yZczfl2comtFM4VQgjdKTRVRoXbVowSwowh3S6EbY57x5RgwdFg_uQU03-8pGZfqhGSYiqBWCsM6b3gnk91wzmj4vdfNU='
>>>
>>>
>>> fernet.decrypt(encrypted)
b'something to be encrypted'
>>>
>>>
>>> key2 = Fernet.generate_key()
>>> fernet2 = Fernet(key)
>>>
>>>
>>> fernet2.decrypt(encrypted)
Traceback (most recent call last):
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/fernet.py", line 119, in _verify_signature
    h.verify(data[-32:])
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/hazmat/primitives/hmac.py", line 74, in verify
    ctx.verify(signature)
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/hmac.py", line 75, in verify
    raise InvalidSignature("Signature did not match digest.")
cryptography.exceptions.InvalidSignature: Signature did not match digest.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/fernet.py", line 80, in decrypt
    return self._decrypt_data(data, timestamp, time_info)
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/fernet.py", line 137, in _decrypt_data
    self._verify_signature(data)
  File "/home/vadmin/.local/lib/python3.8/site-packages/cryptography/fernet.py", line 121, in _verify_signature
    raise InvalidToken
cryptography.fernet.InvalidToken

This proves that using a different key raises this error.

Qp answered 19/5, 2022 at 10:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.