Base64-URL encoded key (32 bytes = signing key + encryption key)
Text will be encrypted with AES-128-CBC
Output
Enter a message and key, then click Encrypt or Decrypt.
No recently used tools
Loading categories...
Base64-URL encoded key (32 bytes = signing key + encryption key)
Text will be encrypted with AES-128-CBC
Enter a message and key, then click Encrypt or Decrypt.
Fernet guarantees that a message encrypted using it cannot be manipulated or read without the key. All encryption uses AES-128 in CBC mode with HMAC-SHA256 authentication. The Fernet specification is part of the Python cryptography library and provides a simple, high-level symmetric encryption API.
Unlike raw AES, Fernet is an authenticated encryption scheme: any tampering with the ciphertext is detected before any plaintext is returned. This prevents padding oracle attacks and other manipulation-based vulnerabilities.
A Fernet key is the base64url encoding of the following fields:
The signing key (first 16 bytes) is used for HMAC-SHA256 authentication. The encryption key (last 16 bytes) is used for AES-128-CBC encryption. Both are generated from cryptographically secure random bytes.
A Fernet token is the base64url encoding of the concatenation of the following fields:
| Field | Size | Description |
|---|---|---|
| Version | 8 bits | Always 0x80 (128) for current Fernet spec |
| Timestamp | 64 bits | Seconds since January 1, 1970 UTC when token was created |
| IV | 128 bits | Random initialization vector for AES-CBC |
| Ciphertext | Variable | PKCS7-padded plaintext encrypted with AES-128-CBC (multiple of 128 bits) |
| HMAC | 256 bits | SHA256 HMAC of Version || Timestamp || IV || Ciphertext |
Try these examples using the Python tab above, or copy them to run locally.
"Key:", key.decode())
f = Fernet(key)
token = f.encrypt(b"Hello 8gwifi.org")
print("Token:", token.decode())
plaintext = f.decrypt(token)
print("Decrypted:", plaintext.decode())"Hello 8gwifi.org")
# Decode the token
data = base64.urlsafe_b64decode(token)
version = data[0]
timestamp = struct.unpack(">Q", data[1:9])[0]
iv = data[9:25]
ciphertext = data[25:-32]
hmac_val = data[-32:]
print(f"Version: 0x{version:02x}")
print(f"Timestamp: {datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)}")
print(f"IV: {iv.hex()}")
print(f"Ciphertext: {ciphertext.hex()}")
print(f"HMAC: {hmac_val.hex()}")You can derive a Fernet key from a password using PBKDF2-HMAC-SHA256. This is useful when you want users to encrypt/decrypt with a memorable password rather than a random key.
"my_secret_password"
salt = os.urandom(16)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
key = base64.urlsafe_b64encode(kdf.derive(password))
print("Derived Key:", key.decode())
f = Fernet(key)
token = f.encrypt(b"Hello 8gwifi.org")
print("Token:", token.decode())
print("Decrypted:", f.decrypt(token).decode())Fernet is ideal for encrypting data that easily fits in memory. As a design feature it does not expose unauthenticated bytes. This means that the complete message contents must be available in memory, making Fernet generally unsuitable for very large files at this time.
For large file encryption, consider AES-GCM (which supports streaming) or chunked encryption approaches. Fernet also does not support key rotation natively — you must re-encrypt data with a new key manually.
pip install cryptography. Then use: from cryptography.fernet import Fernet; key = Fernet.generate_key(); f = Fernet(key); token = f.encrypt(b'message'); print(f.decrypt(token)). Tokens generated by this tool are fully compatible with Python Fernet.This Fernet encryption/decryption tool is maintained by Anish Nath. It implements the standard Fernet specification as defined by the Python cryptography library.
The tool generates cryptographically secure Fernet keys, encrypts plaintext messages into Fernet tokens, and decrypts tokens back to their original plaintext. All operations use AES-128-CBC with HMAC-SHA256 authentication as per the Fernet spec.