Fernet Encrypt & Decrypt Online

Authenticated AES-128-CBC Fernet spec →
AES-128-CBC HMAC-SHA256 Free Python Compatible
Fernet Tool

Base64-URL encoded key (32 bytes = signing key + encryption key)

Text will be encrypted with AES-128-CBC

Output

Encryption
Plaintext
🔑 AES-128-CBC
HMAC-SHA256
Fernet Token

Enter a message and key, then click Encrypt or Decrypt.

Python Compiler

What is Fernet Encryption?

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.

Fernet Key Format

A Fernet key is the base64url encoding of the following fields:

Key Structure (32 bytes total)
Signing-key (128 bits) || Encryption-key (128 bits)

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.

Fernet Token Format

A Fernet token is the base64url encoding of the concatenation of the following fields:

Token Structure
Version || Timestamp || IV || Ciphertext || HMAC
FieldSizeDescription
Version8 bitsAlways 0x80 (128) for current Fernet spec
Timestamp64 bitsSeconds since January 1, 1970 UTC when token was created
IV128 bitsRandom initialization vector for AES-CBC
CiphertextVariablePKCS7-padded plaintext encrypted with AES-128-CBC (multiple of 128 bits)
HMAC256 bitsSHA256 HMAC of Version || Timestamp || IV || Ciphertext

Fernet Python Examples

Try these examples using the Python tab above, or copy them to run locally.

Basic Encrypt & Decrypt

Python: Basic Fernet encrypt/decrypt
from cryptography.fernet import Fernet key = Fernet.generate_key() print("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())

Token Inspection

Python: Inspect Fernet token fields
import base64, struct, datetime from cryptography.fernet import Fernet key = Fernet.generate_key() f = Fernet(key) token = f.encrypt(b"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()}")

Using Password with Fernet (PBKDF2)

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.

Python: Password-derived Fernet key
import base64, os from cryptography.fernet import Fernet from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC password = b"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 Limitations

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.

Frequently Asked Questions

A Fernet key is 32 bytes, base64url (URL-safe) encoded. It contains a 128-bit signing key and a 128-bit encryption key concatenated together. The key is used for both HMAC-SHA256 authentication and AES-128-CBC encryption.
Fernet uses AES-128 in CBC mode for encryption and HMAC-SHA256 for authentication. The signing key handles HMAC and the encryption key handles AES. All encryption is authenticated, meaning tampering is detected before any plaintext is returned.
Select Decrypt mode, paste the Fernet token into the message field, enter the same base64url-encoded key that was used for encryption, and click Decrypt. The tool verifies the HMAC, checks the version byte, and returns the original plaintext.
No. Encryption and decryption are processed server-side but no data is stored, logged, or transmitted to third parties. For maximum security, you can use the Python cryptography library locally.
Fernet is built on top of AES-128-CBC but adds authenticated encryption via HMAC-SHA256, a version byte, a timestamp, and a random IV. Raw AES does not include authentication, so Fernet provides stronger guarantees against tampering.
Install the cryptography library with 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.

About This Tool

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.

Support This Free Tool

Every coffee helps keep the servers running. Every book sale funds the next tool I'm dreaming up. You're not just supporting a site — you're helping me build what developers actually need.

500K+ users
200+ tools
100% private
Privacy Guarantee: Private keys you enter or generate are never stored on our servers. All tools are served over HTTPS.