Search code examples
pythonencryptionfernet

Error: Fernet key must be 32 url-safe base64-encoded bytes


I'm currently working on an ecrypting/decrypting program in Python using Fernet. Here's my code so far:

from cryptography.fernet import Fernet

def decrypter():
  enc_message = input("Input an encrypted string:\n")

  key = input("Input a key:\n")

  fernet = Fernet(key)

  dec_message = fernet.decrypt(enc_message).decode()
  print(dec_message)

def encrypter():
  message = input("Input a string to encrypt:\n")
  key = Fernet.generate_key()
  fernet = Fernet(key)


  enc_message = fernet.encrypt(message.encode())

  print("")
  print("Original string: ", message)
  print("")
  print("Encrypted string: ", repr(enc_message))
  print("")
  print("Key: ", repr(key))
  print("")
  dec_message = fernet.decrypt(enc_message).decode()

  print("Decrypted string: ", dec_message)

encrypter()
decrypter()

Eventually I plan on adding more quality-of-life features, but right now the encrypter function asks you for a string to encrypt, generates a key using Fernet, encrypts your string, and then prints your original string, your newly encrypted string, and the encryption key. (This is not the part that needs fixing.)

The idea of the decrypter function is that it takes an encrypted string and key from the encrypter function. It then decrypts the string using the key and prints it.

My problem is that the key is causing an error. I'm not sure if I've coded the decrypter wrong or if I'm just inputting the key in incorrectly.

My apologies if this is an easily solve-able question, I'm new to Python and couldn't really find any answers specifically for this online. Any help is much appreciated!


Solution

  • Your current approach to this is to do all the input and printing within the functions dectrypter and encryptor. That means if you ever wanted to do something slightly different with the results of encrypting you'd have to rewrite those functions.

    Your code would be more reusable and modular if your keep the input and printing separate for the functions which do the work, like this:

    from cryptography.fernet import Fernet
    
    def encrypter(key,plaintext):
        fernet = Fernet(key)
        enc_message = fernet.encrypt(plaintext.encode())
        return enc_message
    
    def decrypter(key,ciphertext):
        fernet = Fernet(key)
        dec_message = fernet.decrypt(ciphertext).decode()
        return dec_message
    
    def generatekey():
        key = Fernet.generate_key()
        return key
    
    if __name__=="__main__":
        # comment out input() so code can be tested simply
        #plaintext = input("Input a string to encrypt:\n")
        plaintext= "A test message"
    
        key = generatekey()
    
        ciphertext = encrypter(key,plaintext)
    
        print("")
        print("Original string: ", plaintext)
        print("")
        print("Encrypted string: ", repr(ciphertext))
        print("")
        print("Key: ", repr(key))
        print("")
    
        decoded_message = decrypter(key,ciphertext)
    
        print("Decrypted string: ", decoded_message)
    

    Now you could write another file which imported the above file and uses the generatekey, encrypter and decrypter, perhaps taking input from the user, without knowing or using fernet at all :-)