2018-01-24 21:34:14 +00:00
|
|
|
import os
|
2018-07-06 22:44:33 +00:00
|
|
|
from typing import Optional
|
|
|
|
|
2018-01-24 21:34:14 +00:00
|
|
|
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
|
2018-01-23 07:40:36 +00:00
|
|
|
|
|
|
|
|
2018-01-24 21:52:49 +00:00
|
|
|
DEM_KEYSIZE = 32
|
|
|
|
DEM_NONCE_SIZE = 12
|
|
|
|
|
|
|
|
|
2018-01-23 07:40:36 +00:00
|
|
|
class UmbralDEM(object):
|
2018-07-06 22:44:33 +00:00
|
|
|
def __init__(self, symm_key: bytes) -> None:
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
|
|
|
Initializes an UmbralDEM object. Requires a key to perform
|
2018-01-24 21:34:14 +00:00
|
|
|
ChaCha20-Poly1305.
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
2018-01-24 21:52:49 +00:00
|
|
|
if len(symm_key) != DEM_KEYSIZE:
|
2018-01-23 09:40:13 +00:00
|
|
|
raise ValueError(
|
2018-01-24 21:52:49 +00:00
|
|
|
"Invalid key size, must be {} bytes".format(DEM_KEYSIZE)
|
2018-01-23 09:40:13 +00:00
|
|
|
)
|
|
|
|
|
2018-01-24 21:34:14 +00:00
|
|
|
self.cipher = ChaCha20Poly1305(symm_key)
|
2018-01-23 09:40:13 +00:00
|
|
|
|
2018-07-06 22:44:33 +00:00
|
|
|
def encrypt(self, data: bytes, authenticated_data: Optional[bytes] = None) -> bytes:
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
2018-01-24 21:34:14 +00:00
|
|
|
Encrypts data using ChaCha20-Poly1305 with optional authenticated data.
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
2018-01-24 21:52:49 +00:00
|
|
|
nonce = os.urandom(DEM_NONCE_SIZE)
|
2018-01-24 21:34:14 +00:00
|
|
|
enc_data = self.cipher.encrypt(nonce, data, authenticated_data)
|
2018-01-26 00:06:17 +00:00
|
|
|
# Ciphertext will be a 12 byte nonce, the ciphertext, and a 16 byte tag.
|
2018-01-24 21:34:14 +00:00
|
|
|
return nonce + enc_data
|
2018-01-23 09:40:13 +00:00
|
|
|
|
2018-07-06 22:44:33 +00:00
|
|
|
def decrypt(self, ciphertext: bytes, authenticated_data: Optional[bytes] = None) -> bytes:
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
2018-01-24 21:34:14 +00:00
|
|
|
Decrypts data using ChaCha20-Poly1305 and validates the provided
|
|
|
|
authenticated data.
|
2018-01-23 09:40:13 +00:00
|
|
|
"""
|
2018-01-31 07:19:22 +00:00
|
|
|
nonce = ciphertext[:DEM_NONCE_SIZE]
|
|
|
|
ciphertext = ciphertext[DEM_NONCE_SIZE:]
|
|
|
|
cleartext = self.cipher.decrypt(nonce, ciphertext, authenticated_data)
|
|
|
|
return cleartext
|