| 57 | return self._encrypt_from_parts(data, current_time, iv) |
| 58 | |
| 59 | def _encrypt_from_parts( |
| 60 | self, data: bytes, current_time: int, iv: bytes |
| 61 | ) -> bytes: |
| 62 | utils._check_bytes("data", data) |
| 63 | |
| 64 | padder = padding.PKCS7(algorithms.AES.block_size).padder() |
| 65 | padded_data = padder.update(data) + padder.finalize() |
| 66 | encryptor = Cipher( |
| 67 | algorithms.AES(self._encryption_key), |
| 68 | modes.CBC(iv), |
| 69 | ).encryptor() |
| 70 | ciphertext = encryptor.update(padded_data) + encryptor.finalize() |
| 71 | |
| 72 | basic_parts = ( |
| 73 | b"\x80" |
| 74 | + current_time.to_bytes(length=8, byteorder="big") |
| 75 | + iv |
| 76 | + ciphertext |
| 77 | ) |
| 78 | |
| 79 | h = HMAC(self._signing_key, hashes.SHA256()) |
| 80 | h.update(basic_parts) |
| 81 | hmac = h.finalize() |
| 82 | return base64.urlsafe_b64encode(basic_parts + hmac) |
| 83 | |
| 84 | def decrypt(self, token: bytes | str, ttl: int | None = None) -> bytes: |
| 85 | timestamp, data = Fernet._get_unverified_token_data(token) |