FernetFernet builds on best practice cryptography methods, and allows developers to provide a simple method of encrypting and authenticating. Overall it uses 128-bit AES symmetric encryption in a CBC mode with PKCS7 padding and HMAC using SHA256 for authentication. Note: It may take a few seconds to generate, so please wait for the results. Generate an example and use the decrypt page: [Fernet Decrypt] |
Outline
The token has a version number, a time stamp, the IV, the cipher text and an HMAC signature:
- Version: 8 bits
- Timestamp: 64 bits (the number of seconds since between January 1, 1970 UTC and the time of the encryption).
- IV: 128 bits
- Ciphertext - variable length: Multiple of 128 bits
- HMAC: 256 bits
Here is an example:
67 4141414141426346 3745716c4c45323343566871445a6447 48623743347a6477395f5034643730634c796a434e485a42534d396b79724e526d4743325a573030433862 57355364776348447731673178636c4d704c7953674764416c626b6a53773d3d
This is:
67 - Version (8 bits) 4141414141426346 - Date (64 bits) 3745716c4c45323343566871445a6447 - Salt (128 bits) 48623743347a6477395f5034643730634c796a434e485a42534d396b79724e526d4743325a573030433862 - Ciphered message 57355364776348447731673178636c4d704c7953674764416c626b6a53773d3d - HMAC
Code
Fernet is used to define best practice cryptography methods, and Harmat supports core cryptographical primitives:.
# https://asecuritysite.com/encryption/fernet from cryptography.fernet import Fernet from cryptography.hazmat.primitives import hashes from cryptography.hazmat.backends import default_backend import sys import binascii import base64 password="hello" val="hello world" def get_key(password): digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) digest.update(password) return base64.urlsafe_b64encode(digest.finalize()) if (len(sys.argv)>1): val=sys.argv[1] if (len(sys.argv)>2): password=str(sys.argv[2]) if (len(password)>1): key = get_key(password.encode()) else: key = Fernet.generate_key() print("Key: ",binascii.hexlify(bytearray(key))) cipher_suite = Fernet(key) cipher_text = cipher_suite.encrypt(val.encode()) cipher=binascii.hexlify(bytearray(cipher_text)) print("Cipher: ",cipher) print("\nVersion:\t",cipher[0:2]) print("Time stamp:\t",cipher[2:18]) print("IV:\t\t",cipher[18:50]) print("HMAC:\t\t",cipher[-64:]) plain_text = cipher_suite.decrypt(cipher_text) print("\nPlain text: ",plain_text)
A sample run for "hello" is:
Key: 4c504a4e756c2d776f77346d3644737178626e696e687357486c776670304a656377517a59704f4c6d43513d Cipher: 674141414141426346375567792d36663450495159425a797632525a54643953544c48723278372d657965472d7a68597a50556535584c494f416b614c79674f6a44715841556d54464b674675617a6e4e475f5f4e76416874496652375a7a5468673d3d Version: 67 Time stamp: 4141414141426346 IV: 375567792d36663450495159425a7976 Cipher: 32525a54643953544c48723278372d657965472d7a68597a50556535584c494f416b614c79674f6a447158 HMAC: 41556d54464b674675617a6e4e475f5f4e76416874496652375a7a5468673d3d Plain text: hello
A sample run for "hello world" is:
Key: 4c504a4e756c2d776f77346d3644737178626e696e687357486c776670304a656377517a59704f4c6d43513d Cipher: 674141414141426346375673794b7150413743372d332d6179344e7838504f4c49625359512d4b556546554751386e595841706d30785678696f76756c45323430427033766d575f5062626d524c366c505a314334355863596a4c5731786f3935513d3d Version: 67 Time stamp: 4141414141426346 IV: 375673794b7150413743372d332d6179 Cipher: 344e7838504f4c49625359512d4b556546554751386e595841706d30785678696f76756c45323430427033 HMAC: 766d575f5062626d524c366c505a314334355863596a4c5731786f3935513d3d Plain text: hello world
The reason the cipher text is longer as we have a block size of 128 bits (16 ASCII characters).
Presentation
The following is an outline presentation [slides]: