Source code for pyflocker.ciphers.backends.cryptodome_.symmetric

"""Cryptodome backend specific templates and tools for symmetric ciphers."""

from __future__ import annotations

import typing

from pyflocker.ciphers import base, exc


[docs] class NonAEADCipherTemplate(base.BaseNonAEADCipher): """ Template class to provide the default behavior of BaseNonAEADCipher. Subclasses need to provide: - ``_encrypting`` - ``_update_func`` """ # these are *not* class variables _encrypting: bool _update_func: typing.Callable | None
[docs] def is_encrypting(self) -> bool: return self._encrypting
[docs] def update(self, data: bytes) -> bytes: if self._update_func is None: raise exc.AlreadyFinalized return self._update_func(data)
[docs] def update_into( self, data: bytes, out: bytearray | memoryview, ) -> None: if self._update_func is None: raise exc.AlreadyFinalized self._update_func(data, out)
[docs] def finalize(self) -> None: if not self._update_func: raise exc.AlreadyFinalized self._update_func = None
[docs] class AuthenticationMixin: """Mixin class to provide authentication behavior to ciphers. Classes inheriting this must provide these attributes: Attributes: _updated: A boolean indicating whether ``update()`` method of ``_cipher`` was called. _cipher: A cipher from Cryptodome package that has ``update()`` and ``verify()`` methods. _update_func: A method of ``_cipher`` that encrypts/decrypts data. It is generally ``_cipher.encrypt()`` or ``_cipher.decrypt()``. _tag: A byte sequence denoting the MAC tag generated by the cipher after encryption. """ _updated: bool _cipher: typing.Any _update_func: typing.Callable _tag: bytes | None
[docs] def authenticate(self, data: bytes) -> None: if self._update_func is None: raise exc.AlreadyFinalized if self._updated: raise TypeError assert self._cipher is not None self._cipher.update(data)
[docs] def finalize(self, tag: bytes | None = None) -> None: if self._update_func is None: raise exc.AlreadyFinalized if self.is_encrypting(): # type: ignore self._tag, self._cipher = self._cipher.digest(), None self._update_func = None # type: ignore return if tag is None: msg = "tag is required for finalization" raise ValueError(msg) cipher, self._cipher = self._cipher, None self._update_func = None # type: ignore try: cipher.verify(tag) except ValueError as e: raise exc.DecryptionError from e
[docs] def calculate_tag(self) -> bytes | None: if self._update_func is not None: raise exc.NotFinalized return self._tag
authenticate.__doc__ = base.BaseAEADCipher.authenticate.__doc__ finalize.__doc__ = base.BaseAEADCipher.finalize.__doc__ calculate_tag.__doc__ = base.BaseAEADCipher.calculate_tag.__doc__
[docs] class AEADCipherTemplate(AuthenticationMixin, base.BaseAEADCipher): """ Template class to provide the default behavior of BaseAEADCipher. Subclasses need to provide the following attributes: - ``_encrypting`` - ``_update_func`` - ``_cipher`` """ _encrypting: bool
[docs] def is_encrypting(self) -> bool: return self._encrypting
[docs] def update(self, data: bytes) -> bytes: self._updated = True if self._update_func is None: raise exc.AlreadyFinalized return self._update_func(data)
[docs] def update_into( self, data: bytes, out: bytearray | memoryview, ) -> None: self._updated = True if self._update_func is None: raise exc.AlreadyFinalized self._update_func(data, out)