1

I am making a program which encrypts and decrypts texts. I am using Python 3.7 and cryptography.fernet library. I want to enter some information about my program's encryption standard to the GitHub page but I didn't understand which encryption does Fernet uses.

Here is my sample code which I am used in my project. I want to encrypt with 256-bit (AES-256) key but the key which this code generates is longer than 32 characters. It's 44 characters. But in official web site of cryptography library it says this code generates 128-bit key. What is the name of this 44 character (352-bit) key? Or is there any way for 256-bit symmetric encryption without PyCrypto?

from cryptography.fernet import Fernet
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC

textEncrypt = "Secret Data"
password = "Password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),length=32,salt=salt,iterations=100000)
key = base64.urlsafe_b64encode(kdf.derive(password))
fernet = Fernet(key)
encryptedText = fernet.encrypt(textEncrypt.encode())

Here is the key which this code generates: aAT_LESBw_ZGlPA52cj4zQd6jBdx6gk5RmQWbpLY7e0=

Yılmaz Alpaslan
  • 327
  • 3
  • 16

1 Answers1

1

It is well written in the documentation;

Implementation

Fernet is built on top of a number of standard cryptographic primitives. Specifically it uses:

  • AES in CBC mode with a 128-bit key for encryption; using PKCS7 padding.
  • HMAC using SHA256 for authentication.
  • Initialization vectors are generated using os.urandom().

For complete details consult the specification.

Therefore you cannot use AES-256 with Fernet

  • Cryptography.io library has other modes too, in the hazardous material layer including CBC, CTR, and GCM for AES-256, too.

PyCrypto can use a wide range of mode of operations for AES-256 including CBC, CTR, GCM, SIV, and OCB


Not clear how you get 44 bytes, here is the way to get the 32-bytes;

from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
import os


textEncrypt = "Secret Data"
password = "Password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),length=32,salt=salt,iterations=100000)

key = kdf.derive(str.encode(password))
print(len(key))
print(key)

and outputs

32
b'K\xf6\x10a\xd6B`\x8a\x83\x13\xc2\xcfOJ\xcb\x02k$~\xf7v\x01\x80\xd0\xda\x93!\xaf\xa9B\x94\xfe'
kelalaka
  • 5,064
  • 5
  • 27
  • 44
  • Fernet is just one part of the cryptography library, it also supports all the other modes in the "hazardous materials" part of the API. – President James K. Polk May 03 '21 at 12:48
  • @PresidentJamesK.Polk you are absolutely right. – kelalaka May 03 '21 at 12:54
  • But I am unable to install PyCrypto anymore, maybe because PyCrypto is dead. Also so how much characters is in a 128-bit key? Is it 44? – Yılmaz Alpaslan May 03 '21 at 12:55
  • 128-bit key has 16-bytes. what is the encoding? – kelalaka May 03 '21 at 12:58
  • Sorry but I am new to encryption, I don't know which encoding I am using. But I gave the code in the question. If you want, I can send the full code. My key is 43 or 44 characters long. So it isn't a 128-bit key, right? – Yılmaz Alpaslan May 03 '21 at 13:04
  • It is base64. Could you write your imports, too? – kelalaka May 03 '21 at 13:10
  • I really wonder how you get the 44. I've included a code to generate 32-byte key – kelalaka May 03 '21 at 13:42
  • My imports are: from cryptography.fernet import Fernet, from platform import release, import pyperclip, import os, import base64, from cryptography.hazmat.primitives import hashes, from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC, import time, from datetime import datetime, import sys, os, traceback, types, from tkinter import *, from tkinter import messagebox, from tkinter import ttk, from tkinter.ttk import *, – Yılmaz Alpaslan May 03 '21 at 14:39
  • So, my code is working as yours, right? Also, your code provides an error on my 3.8. – kelalaka May 03 '21 at 16:44
  • Yes it works without erros, but generated key doesn't looks like a 256-bit key. You said it's 32 bytes. Yes it has 32 characters but I cannot use it to encrypt. How can I convert it to a 256-bit key-looking key? Whatever, thanks for helping though. I will look the link you sent in answer. – Yılmaz Alpaslan May 03 '21 at 18:09
  • 32-byte makes 256-bit and Fernet doesn't support AES-256. You should either use Hazardous, PyCrypto, or NaCl. I cannot reproduce your 44-byte. Always make sure that you understand what you get. In general, the library documentations provides examples. And stick to them. Once you have a working code you can ask a review at [codereview.se] you will learn a lot from the expert. – kelalaka May 03 '21 at 18:22
  • After a long time, I understood why key is still 44 charaters long even I was generating a 32 charaters long AES-256 key. Base64 makes the AES-256 key 44 charaters long when encoding it. – Yılmaz Alpaslan Jun 10 '21 at 19:35