Symmetric key encryption and decryption in cryptography: A Study of Fernet algorithm

Source: Internet
Author: User
Tags base64 decrypt hmac pkcs7 asymmetric encryption

Original article, welcome to forward the circle of friends, reproduced please indicate the source

Cryptography is a very well-known addition and decryption library in the Python language, providing a high level of abstraction at the algorithm level, very simple, intuitive, and pythonic, while preserving the low-level interfaces of various algorithms, preserving flexibility.

We know that encryption is generally divided into symmetric encryption (symmetric key encryption) and asymmetric encryption (asymmetric key encryption). , each corresponding to a number of different algorithms, each algorithm has different key length requirements, in addition to different packet encryption mode, as well as the end of the way. So it takes a high level of abstraction to encapsulate these parameters so that we don't have to worry about so many parameters when we use them, as long as we know it's safe enough.

Symmetric encryption is divided into packet encryption and sequence encryption, this article only discusses symmetric packet encryption.

Mainstream symmetric packet encryption algorithm: DES, 3DES, AES

Mainstream symmetric packet encryption mode: ECB, CBC, CFB, OFB

Mainstream fill standards: PKCS7, ISO 10126, ANSI x.923, Zero padding

In cryptography Library, the abstraction of symmetric encryption algorithm is Fernet module, including the encryption and decryption of data, signature verification function, and key expiration mechanism.

The module uses the following definition:

    • Encryption and decryption algorithm for AES, key bit length 128,CBC mode, fill the standard PKCS7
    • The signature algorithm is an HMAC of SHA256, with a key bit length of 128 bits
    • Key can set expiration time
examples of using Fernet Plus decryption are as follows:
>>>ImportOS>>> fromCryptography.hazmat.primitives.ciphersImportCipher, algorithms, modes>>> fromCryptography.hazmat.backendsImportDefault_backend>>> backend =default_backend ()>>> key = Os.urandom (32)>>> IV = Os.urandom (16)>>> cipher = cipher (algorithms. AES (key), modes. CBC (iv), backend=backend)>>> encryptor =Cipher.encryptor ()>>> ct = encryptor.update (b"a secret message") +encryptor.finalize ()>>> decryptor =Cipher.decryptor ()>>> Decryptor.update (CT) +decryptor.finalize ()'a secret message'

  in addition to specifying algorithms and patterns, and generating random keys, the CBC mode needs to generate a random initial vector IV, as well as an IV when decrypting.  The fernet module of the Cryptography library encapsulates the operation of symmetric encryption and provides three basic operations:generate symmetric key: Generate_keyEncrypt with symmetric key: Encryptdecryption with symmetric key: Decrypt  Generate_key: Visible only generates a 32-bit random number and encodes it with Base64
@classmethod     def Generate_key (CLS):         return Base64.urlsafe_b64encode (Os.urandom (32))
 after generating the 32-bit key, the first 16 bits are used to compute the HMAC, and the last 16 bits are used to decrypt
Self._signing_key = key[:16]        = key[16:]        = Backend
 Encrypt:1. Obtain the Current_time and randomly generate a 16-bit CBC initial Vector IV2. Specify padding mode as PKCS73. Use the Padding method to encrypt the original data4. Specify the AES algorithm for CBC mode encryption5. Encrypt to get ciphertext6. Merging Current_time, IV and ciphertext to get a basic_parts
Basic_parts = (            b"\x80" + struct.pack (">q", Current_time) + IV + ciphertext        )

7. Calculating the HMAC value of the Basic_parts8. Basic_parts + HMac to do base64 to return, this is what we finally get encrypted data, containing the timestamp, IV, ciphertext, HMAC
defEncrypt (self, data): Current_time=Int (time.time ()) IV= Os.urandom (16)        returnself._encrypt_from_parts (data, Current_time, IV)def_encrypt_from_parts (self, data, Current_time, iv):if  notisinstance (data, bytes):RaiseTypeError ("data must be bytes.") Padder=padding. PKCS7 (algorithms. aes.block_size). Padder () Padded_data= Padder.update (data) +padder.finalize () encryptor=Cipher (algorithms. AES (Self._encryption_key), modes. CBC (iv), Self._backend). Encryptor () ciphertext= Encryptor.update (padded_data) +encryptor.finalize () basic_parts=(b"\x80"+ Struct.pack (">q", Current_time) + IV +ciphertext) H= HMAC (Self._signing_key, hashes. SHA256 (), backend=self._backend) h.update (basic_parts) HMAC=h.finalize ()returnBase64.urlsafe_b64encode (Basic_parts + HMAC)

Decrypt:completely opposite operation of encrypt1. Get Current_time2. Base64 decode token, get data containing timestamp, IV, ciphertext, HMAC3. Determine if the key has expired based on time stamp and TTL4. Calculate the HMAC and verify the key validity with the previous HMAC5. Get IV, and ciphertext, and decrypt through the key, get through the pad's plaintext6. Unpaid operation via PKCS7 to get the clear text removed7. Return to final result 
defDecrypt (self, token, ttl=None):if  notisinstance (token, bytes):RaiseTypeError ("token must be bytes.") Current_time=Int (time.time ())Try: Data=Base64.urlsafe_b64decode (token)except(TypeError, Binascii. Error):RaiseInvalidtokenif  notDataorSix.indexbytes (data, 0)! = 0x80:            RaiseInvalidtokenTry: Timestamp,= Struct.unpack (">q", Data[1:9])        exceptStruct.error:RaiseInvalidtokenifTtl is  notNone:ifTimestamp + TTL <Current_time:RaiseInvalidtokenifCurrent_time + _max_clock_skew <Timestamp:RaiseInvalidtoken H= HMAC (Self._signing_key, hashes. SHA256 (), backend=self._backend) h.update (data[:-32])        Try: h.verify (data[-32:]) exceptinvalidsignature:RaiseInvalidtoken IV= data[9:25] Ciphertext= data[25:-32] Decryptor=Cipher (algorithms. AES (Self._encryption_key), modes. CBC (iv), Self._backend). Decryptor () plaintext_padded=decryptor.update (ciphertext)Try: plaintext_padded+=decryptor.finalize ()exceptValueError:RaiseInvalidtoken Unpadder=padding. PKCS7 (algorithms. aes.block_size). Unpadder () unpadded=unpadder.update (plaintext_padded)Try: unpadded+=unpadder.finalize ()exceptValueError:RaiseInvalidtokenreturnunpadded

 

Symmetric key encryption and decryption in cryptography: A Study of Fernet algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.