Skip to content

Encryption service

Encryption Service provides encryption and decryption functionality for sensitive data.

EncryptionService

Provides encryption and decryption services.

This class orchestrates the encryption and decryption processes, utilizing a specified cipher for cryptographic operations, a storage mechanism for persisting encrypted data, and a hash function for generating unique identifiers (keys) for stored ciphertexts.

Attributes:

Name Type Description
cipher

The cipher object used for encryption and decryption.

storage

The storage object used for storing and retrieving ciphertexts.

hahsfn

The hash function used to generate keys for storing ciphertexts.

Source code in topsecret/services/encryption.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
class EncryptionService:
    """Provides encryption and decryption services.

    This class orchestrates the encryption and decryption processes,
    utilizing a specified cipher for cryptographic operations, a storage
    mechanism for persisting encrypted data, and a hash function for
    generating unique identifiers (keys) for stored ciphertexts.

    Attributes:
        cipher: The cipher object used for encryption and
            decryption.
        storage: The storage object used for storing
            and retrieving ciphertexts.
        hahsfn: The hash function used to generate
            keys for storing ciphertexts.
    """

    def __init__(self, cipher: CipherProtocol, storage: CipherStorageProtocol, hashfn: Callable[[bytes], str]) -> None:
        """Initializes the instance with a cipher, storage, and hash function.

        Args:
            cipher: An object conforming to the CipherProtocol, used for
                encryption and decryption operations.
            storage: An object conforming to the CipherStorageProtocol, used for
                storing and retrieving cipher-related data.
            hashfn: A callable that takes bytes as input and returns a string
                hash, used for hashing operations within the service.
        """
        self.cipher = cipher
        self.storage = storage
        self.hashfn = hashfn

    def encrypt(self, data: bytes, passphrase: str | None = None) -> tuple[Ciphertext, Hash]:
        """Encrypts the given data and stores it.

        This method encrypts the input data using the configured cipher.
        It then calculates a hash of the ciphertext and stores the
        ciphertext along with its metadata using this hash as the key.

        Args:
            data: The byte string to be encrypted.
            passphrase: An optional passphrase for encryption. If not
                provided, the cipher's default or pre-configured
                passphrase/key might be used.

        Returns:
            A tuple containing the ciphertext and its corresponding hash.
            The first element is the encrypted data (Ciphertext), and the
            second element is the hash (Hash) of the ciphertext.
        """
        ciphertext, metadata = self.cipher.encrypt(data, passphrase)
        hash_value = self.hashfn(ciphertext)
        value = (ciphertext, metadata)
        self.storage.store(key=hash_value, value=value)
        return ciphertext, hash_value

    def decrypt(self, hash_value: Hash, passphrase: str | None = None) -> str:
        """Decrypts a ciphertext retrieved from storage using a hash value.

        This method retrieves the encrypted data (ciphertext) and its associated
        metadata from storage using the provided `hash_value`. If the entry
        is not found, a `DecryptionError` is raised. Otherwise, it delegates
        the decryption process to the configured cipher object using the
        retrieved ciphertext, metadata, and the optionally provided `passphrase`.

        Args:
            hash_value (Hash): The unique identifier used to retrieve the
                ciphertext and metadata from storage.
            passphrase (str or None, optional): The passphrase for decryption.
                Defaults to None. The behavior when None is provided (e.g.,
                using a default key or requiring a passphrase explicitly if one
                is necessary for the cipher) depends on the specific cipher
                implementation.

        Returns:
            str: The decrypted plaintext string.

        Raises:
            DecryptionError: If no ciphertext is found in storage for the
                given `hash_value`.
            Exception: Propagated if the underlying `self.cipher.decrypt()`
                method fails. This can occur for various reasons, such as an
                incorrect passphrase, corrupted ciphertext, or other
                cipher-specific issues.
        """
        try:
            value = self.storage.retrieve(key=hash_value)
        except KeyError as e:
            raise DecryptionError("Ciphertext not found in storage.") from e  # noqa: TRY003

        if value is None:
            raise DecryptionError("Ciphertext not found in storage.")  # noqa: TRY003

        ciphertext, metadata = value
        return self.cipher.decrypt(ciphertext, metadata, passphrase)

__init__(cipher, storage, hashfn)

Initializes the instance with a cipher, storage, and hash function.

Parameters:

Name Type Description Default
cipher CipherProtocol

An object conforming to the CipherProtocol, used for encryption and decryption operations.

required
storage CipherStorageProtocol

An object conforming to the CipherStorageProtocol, used for storing and retrieving cipher-related data.

required
hashfn Callable[[bytes], str]

A callable that takes bytes as input and returns a string hash, used for hashing operations within the service.

required
Source code in topsecret/services/encryption.py
40
41
42
43
44
45
46
47
48
49
50
51
52
53
def __init__(self, cipher: CipherProtocol, storage: CipherStorageProtocol, hashfn: Callable[[bytes], str]) -> None:
    """Initializes the instance with a cipher, storage, and hash function.

    Args:
        cipher: An object conforming to the CipherProtocol, used for
            encryption and decryption operations.
        storage: An object conforming to the CipherStorageProtocol, used for
            storing and retrieving cipher-related data.
        hashfn: A callable that takes bytes as input and returns a string
            hash, used for hashing operations within the service.
    """
    self.cipher = cipher
    self.storage = storage
    self.hashfn = hashfn

decrypt(hash_value, passphrase=None)

Decrypts a ciphertext retrieved from storage using a hash value.

This method retrieves the encrypted data (ciphertext) and its associated metadata from storage using the provided hash_value. If the entry is not found, a DecryptionError is raised. Otherwise, it delegates the decryption process to the configured cipher object using the retrieved ciphertext, metadata, and the optionally provided passphrase.

Parameters:

Name Type Description Default
hash_value Hash

The unique identifier used to retrieve the ciphertext and metadata from storage.

required
passphrase str or None

The passphrase for decryption. Defaults to None. The behavior when None is provided (e.g., using a default key or requiring a passphrase explicitly if one is necessary for the cipher) depends on the specific cipher implementation.

None

Returns:

Name Type Description
str str

The decrypted plaintext string.

Raises:

Type Description
DecryptionError

If no ciphertext is found in storage for the given hash_value.

Exception

Propagated if the underlying self.cipher.decrypt() method fails. This can occur for various reasons, such as an incorrect passphrase, corrupted ciphertext, or other cipher-specific issues.

Source code in topsecret/services/encryption.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def decrypt(self, hash_value: Hash, passphrase: str | None = None) -> str:
    """Decrypts a ciphertext retrieved from storage using a hash value.

    This method retrieves the encrypted data (ciphertext) and its associated
    metadata from storage using the provided `hash_value`. If the entry
    is not found, a `DecryptionError` is raised. Otherwise, it delegates
    the decryption process to the configured cipher object using the
    retrieved ciphertext, metadata, and the optionally provided `passphrase`.

    Args:
        hash_value (Hash): The unique identifier used to retrieve the
            ciphertext and metadata from storage.
        passphrase (str or None, optional): The passphrase for decryption.
            Defaults to None. The behavior when None is provided (e.g.,
            using a default key or requiring a passphrase explicitly if one
            is necessary for the cipher) depends on the specific cipher
            implementation.

    Returns:
        str: The decrypted plaintext string.

    Raises:
        DecryptionError: If no ciphertext is found in storage for the
            given `hash_value`.
        Exception: Propagated if the underlying `self.cipher.decrypt()`
            method fails. This can occur for various reasons, such as an
            incorrect passphrase, corrupted ciphertext, or other
            cipher-specific issues.
    """
    try:
        value = self.storage.retrieve(key=hash_value)
    except KeyError as e:
        raise DecryptionError("Ciphertext not found in storage.") from e  # noqa: TRY003

    if value is None:
        raise DecryptionError("Ciphertext not found in storage.")  # noqa: TRY003

    ciphertext, metadata = value
    return self.cipher.decrypt(ciphertext, metadata, passphrase)

encrypt(data, passphrase=None)

Encrypts the given data and stores it.

This method encrypts the input data using the configured cipher. It then calculates a hash of the ciphertext and stores the ciphertext along with its metadata using this hash as the key.

Parameters:

Name Type Description Default
data bytes

The byte string to be encrypted.

required
passphrase str | None

An optional passphrase for encryption. If not provided, the cipher's default or pre-configured passphrase/key might be used.

None

Returns:

Type Description
Ciphertext

A tuple containing the ciphertext and its corresponding hash.

Hash

The first element is the encrypted data (Ciphertext), and the

tuple[Ciphertext, Hash]

second element is the hash (Hash) of the ciphertext.

Source code in topsecret/services/encryption.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def encrypt(self, data: bytes, passphrase: str | None = None) -> tuple[Ciphertext, Hash]:
    """Encrypts the given data and stores it.

    This method encrypts the input data using the configured cipher.
    It then calculates a hash of the ciphertext and stores the
    ciphertext along with its metadata using this hash as the key.

    Args:
        data: The byte string to be encrypted.
        passphrase: An optional passphrase for encryption. If not
            provided, the cipher's default or pre-configured
            passphrase/key might be used.

    Returns:
        A tuple containing the ciphertext and its corresponding hash.
        The first element is the encrypted data (Ciphertext), and the
        second element is the hash (Hash) of the ciphertext.
    """
    ciphertext, metadata = self.cipher.encrypt(data, passphrase)
    hash_value = self.hashfn(ciphertext)
    value = (ciphertext, metadata)
    self.storage.store(key=hash_value, value=value)
    return ciphertext, hash_value