Source code for spresso.utils.crypto
"""
This module provides the necessary cryptographic primitives for the system.
It is based on the `cryptography <https://cryptography.io/en/latest/>`_
package.
"""
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
[docs]def encrypt_aes_gcm(key, iv, plaintext, associated_data=b""):
"""
Method to encrypt AES in GCM mode.
Constructs a :class:`Cipher <cryptography.hazmat.primitives.ciphers.Cipher>`
object from key, iv. The plain text is passed in during encryption.
Args:
key (bytes): The symmetric key used during encryption.
iv (bytes): The initialisation vector used during encryption.
plaintext (bytes): Plain text to encrypt.
associated_data (bytes): Additional data to authenticate.
Returns:
tuple: The encrypted plain text as bytes and the authentication tag
as bytes.
Raises:
InvalidTag: The authentication tag in combination with the given
parameters is invalid.
"""
#: Construct an AES-GCM Cipher object with the given key and a
#: randomly generated IV.
encryptor = Cipher(
algorithms.AES(key),
modes.GCM(iv),
backend=default_backend()
).encryptor()
#: Associated_data will be authenticated but not encrypted,
#: it must also be passed in on decryption.
encryptor.authenticate_additional_data(associated_data)
#: Encrypt the plaintext and get the associated cipher text.
#: GCM does not require padding.
cipher_text = encryptor.update(plaintext) + encryptor.finalize()
return cipher_text, encryptor.tag
[docs]def decrypt_aes_gcm(key, iv, auth_tag, cipher_text, associated_data=b""):
"""
Method to decrypt AES in GCM mode.
Constructs a :class:`Cipher <cryptography.hazmat.primitives.ciphers.Cipher>`
object from key, iv and authentication tag. The associated data is passed in
during decryption.
Args:
key (bytes): The symmetric key used during decryption.
iv (bytes): The initialisation vector used during decryption.
auth_tag (bytes): The authentication tag used during decryption.
cipher_text (bytes): Cipher text to decrypt.
associated_data (bytes): Additional authentication data that was passed
in during encryption.
Returns:
bytes: The decrypted cipher text.
Raises:
InvalidTag: The authentication tag in combination with the given
parameters is invalid.
"""
decryptor = Cipher(
algorithms.AES(key),
modes.GCM(iv, auth_tag),
backend=default_backend()
).decryptor()
decryptor.authenticate_additional_data(associated_data)
plaintext = decryptor.update(cipher_text) + decryptor.finalize()
return plaintext
[docs]def create_signature(private_key, data):
"""
Method to create a PKCS#1 signature using SHA256.
Load a RSA private key in PEM format using :func:`load_pem_private_key
<cryptography.hazmat.primitives.serialization.load_pem_private_key>`.
Then configure a signer object and sign the passed in data.
Args:
private_key (bytes): The RSA private key used during signature
creation.
data (bytes): The data to be signed.
Returns:
bytes: The signature.
"""
private_key = serialization.load_pem_private_key(
private_key,
password=None,
backend=default_backend()
)
signer = private_key.signer(
padding.PKCS1v15(),
hashes.SHA256()
)
signer.update(data)
signed_data = signer.finalize()
return signed_data
[docs]def verify_signature(public_key, signature, data):
"""
Method to verify a PKCS#1 signature using SHA256.
Load a RSA public key in PEM format using :func:`load_pem_public_key
<cryptography.hazmat.primitives.serialization.load_pem_public_key>`.
Then configure a verifier object and verify the passed in data.
Args:
public_key (bytes): The RSA public key used in verification.
signature (bytes): The signature to verify.
data (bytes): The expected signed data, which should be verified.
Raises:
InvalidSignature: The expected data was invalid in respect to the
signature.
"""
public_key = serialization.load_pem_public_key(
public_key,
backend=default_backend()
)
verifier = public_key.verifier(
signature,
padding.PKCS1v15(),
hashes.SHA256()
)
verifier.update(data)
verifier.verify()