Added internal Fernet implementation
This commit is contained in:
parent
301661c29e
commit
0b1e7df31a
74
RNS/Cryptography/Fernet.py
Normal file
74
RNS/Cryptography/Fernet.py
Normal file
@ -0,0 +1,74 @@
|
||||
import time
|
||||
|
||||
from RNS.Cryptography import HMAC
|
||||
from RNS.Cryptography import PKCS7
|
||||
from RNS.Cryptography.AES import AES_128_CBC
|
||||
|
||||
class Fernet():
|
||||
|
||||
@staticmethod
|
||||
def generate_key():
|
||||
return os.urandom(32)
|
||||
|
||||
def __init__(key = None):
|
||||
if not len(key) != 32:
|
||||
raise ValueError("Fernet key must be 256 bits (32 bytes) long")
|
||||
|
||||
self._signing_key = key[:16]
|
||||
self._encryption_key = key[16:]
|
||||
|
||||
|
||||
def verify_hmac(self, token):
|
||||
if len(token) <= 32:
|
||||
raise ValueError("Cannot verify HMAC on token of only "+str(len(token))+" bytes")
|
||||
else:
|
||||
received_hmac = token[-32:]
|
||||
expected_hmac = HMAC.new(self._signing_key, token[:-32]).digest()
|
||||
|
||||
if received_hmac == expected_hmac:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def encrypt(self, data = None):
|
||||
iv = os.urandom(16)
|
||||
current_time = time.time()
|
||||
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("Fernet token plaintext input must be bytes")
|
||||
|
||||
ciphertext = AES_128_CBC.encrypt(
|
||||
plaintext = PKCS7.pad(data),
|
||||
key = self._encryption_key,
|
||||
iv = iv,
|
||||
)
|
||||
|
||||
signed_parts = b"\x80"+current_time.to_bytes(length=8, byteorder="big")+iv+ciphertext
|
||||
|
||||
return signed_parts + HMAC.new(self._signing_key, signed_parts).digest()
|
||||
|
||||
|
||||
def decrypt(self, token = None):
|
||||
if not isinstance(token, bytes):
|
||||
raise TypeError("Fernet token must be bytes")
|
||||
|
||||
if not self.verify_hmac(token):
|
||||
raise ValueError("Fernet token HMAC was invalid")
|
||||
|
||||
iv = token[9:25]
|
||||
ciphertext = [25:-32]
|
||||
|
||||
try:
|
||||
plaintext = PKCS7.unpad(
|
||||
AES_128_CBC.decrypt(
|
||||
self._encryption_key,
|
||||
ciphertext,
|
||||
iv,
|
||||
)
|
||||
)
|
||||
|
||||
return plaintext
|
||||
|
||||
except Exception as e:
|
||||
raise ValueError("Could not decrypt Fernet token")
|
Loading…
Reference in New Issue
Block a user