encrypt2.py
69 lines
| 2.1 KiB
| text/x-python
|
PythonLexer
r3522 | import os | |||
import base64 | ||||
from cryptography.fernet import Fernet, InvalidToken | ||||
from cryptography.hazmat.backends import default_backend | ||||
from cryptography.hazmat.primitives import hashes | ||||
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | ||||
class Encryptor(object): | ||||
key_format = 'enc2$salt:{}$data:{}' | ||||
pref_len = 5 # salt:, data: | ||||
def __init__(self, enc_key): | ||||
self.enc_key = enc_key | ||||
def b64_encode(self, data): | ||||
return base64.urlsafe_b64encode(data) | ||||
def b64_decode(self, data): | ||||
return base64.urlsafe_b64decode(data) | ||||
def get_encryptor(self, salt): | ||||
""" | ||||
Uses Fernet as encryptor with HMAC signature | ||||
:param salt: random salt used for encrypting the data | ||||
""" | ||||
kdf = PBKDF2HMAC( | ||||
algorithm=hashes.SHA512(), | ||||
length=32, | ||||
salt=salt, | ||||
iterations=100000, | ||||
backend=default_backend() | ||||
) | ||||
key = self.b64_encode(kdf.derive(self.enc_key)) | ||||
return Fernet(key) | ||||
def _get_parts(self, enc_data): | ||||
parts = enc_data.split('$', 3) | ||||
if len(parts) != 3: | ||||
raise ValueError('Encrypted Data has invalid format, expected {}'.format(self.key_format)) | ||||
prefix, salt, enc_data = parts | ||||
try: | ||||
salt = self.b64_decode(salt[self.pref_len:]) | ||||
except TypeError: | ||||
# bad base64 | ||||
raise ValueError('Encrypted Data salt invalid format, expected base64 format') | ||||
enc_data = enc_data[self.pref_len:] | ||||
return prefix, salt, enc_data | ||||
def encrypt(self, data): | ||||
salt = os.urandom(64) | ||||
encryptor = self.get_encryptor(salt) | ||||
enc_data = encryptor.encrypt(data) | ||||
return self.key_format.format(self.b64_encode(salt), enc_data) | ||||
def decrypt(self, data, safe=True): | ||||
parts = self._get_parts(data) | ||||
salt = parts[1] | ||||
enc_data = parts[2] | ||||
encryptor = self.get_encryptor(salt) | ||||
try: | ||||
return encryptor.decrypt(enc_data) | ||||
except (InvalidToken,): | ||||
if safe: | ||||
return '' | ||||
else: | ||||
raise | ||||