Secrets
Domain layer is the core of the application. It contains interfaces and business logic. It is independent of any framework or technology. It should not depend on any other layer. It should only depend on the entities and value objects.
CipherProtocol
¶
Bases: Protocol
Defines a protocol for cryptographic operations, specifically encrypting and decrypting byte data.
This protocol outlines the contract for classes that provide encryption and decryption functionalities. Implementations are expected to handle the conversion of plaintext data into a secure, encrypted format (ciphertext) and vice-versa. The protocol supports operations with an optional passphrase, allowing for both passphrase-based encryption and potentially other key management schemes.
The Ciphertext
and Metadata
types mentioned in method signatures are
placeholders for the specific types that an implementing class would use for
encrypted data and its associated metadata, respectively.
Attributes:
Name | Type | Description |
---|---|---|
AUTO_KEY_SEP |
bytes
|
A class-level constant representing a byte sequence (b"|"). This separator is intended for use in "auto encryption" scenarios. While the specific mechanism of "auto encryption" is not defined by this protocol, this separator likely plays a role in demarcating or structuring data when keys are managed automatically or embedded within the ciphertext or metadata. |
Source code in topsecret/domain.py
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
|
decrypt(ciphertext, metadata, passphrase=None)
¶
Decrypts the given ciphertext back into its original string form.
This method takes ciphertext and its associated metadata, along with an optional passphrase, to reverse the encryption process. It attempts to decrypt the data and then decodes the resulting bytes into a string. The successful execution of this method relies on the correct ciphertext, metadata, and, if used during encryption, the correct passphrase.
The metadata provided must correspond to the metadata generated during the
encryption of the ciphertext
. If a passphrase was used for encryption,
the same passphrase must be provided for decryption. If no passphrase was
used (e.g., in an "auto encryption" scenario where the key is managed
differently), providing None
for the passphrase argument should allow
the decryption process to proceed using the implementation's key management
strategy.
The return type of str
implies that the original data, before encryption,
was text that was encoded into bytes (e.g., using UTF-8) and, upon
decryption, is decoded back into a string using an appropriate encoding
assumed by the implementation.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
ciphertext
|
Ciphertext
|
The encrypted data to be decrypted. This should
be the |
required |
metadata
|
Metadata
|
The metadata associated with the |
required |
passphrase
|
str | None
|
The passphrase that was used to encrypt the
data. If no passphrase was used during encryption (e.g., key was
auto-generated and managed), this should be |
None
|
Returns:
Name | Type | Description |
---|---|---|
str |
str
|
The decrypted data, decoded into a string. |
Raises:
Type | Description |
---|---|
Exception
|
While not explicitly defined in the protocol, implementations
are expected to raise an appropriate exception (e.g., a custom
|
Source code in topsecret/domain.py
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
|
encrypt(data, passphrase=None)
¶
Encrypts the provided byte data.
This method takes raw byte data and an optional passphrase, processes it through an encryption algorithm, and returns the resulting ciphertext along with associated metadata. The metadata is crucial as it may contain information required for successful decryption, such as initialization vectors (IVs), salts, or parameters related to the encryption algorithm or key derivation.
If a passphrase is not provided, the implementation is expected to handle
key management. This could involve generating a new key, using a
pre-configured key, or employing a mechanism related to "auto encryption"
(potentially using AUTO_KEY_SEP
). The specifics of this behavior are
left to the implementing class.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
bytes
|
The raw byte data to be encrypted. |
required |
passphrase
|
str | None
|
An optional passphrase to be used for deriving the encryption key. If None, the encryption method should define its behavior for key generation or retrieval according to its key management strategy. |
None
|
Returns:
Type | Description |
---|---|
tuple[Ciphertext, Metadata]
|
tuple[Ciphertext, Metadata]: A tuple containing two elements:
- Ciphertext: The encrypted version of the input |
Source code in topsecret/domain.py
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 |
|
CipherStorageProtocol
¶
Bases: Generic[K, V]
, Protocol
Protocol for a generic key-value storage mechanism.
This class defines a protocol that specifies an interface for
storing, retrieving, and checking the existence of key-value pairs. It is
designed to be generic, utilizing type variables K
for keys and V
for
values. This allows concrete implementations to define the specific types
they handle, promoting flexibility and type safety.
The primary purpose of this protocol is to abstract the underlying storage mechanism. Implementers could use various backends, such as in-memory dictionaries for testing, databases for persistent storage, or distributed caches for scalable solutions. By adhering to this protocol, different storage implementations can be used interchangeably within an application.
In the context of cipher management or secure data handling (as suggested by
the name "CipherStorageProtocol"), K
might represent a unique identifier
for a cryptographic key, a cipher suite, or a protected data entry. V
could then be the actual cryptographic material (e.g., an encryption key,
a PGP key object), a configuration object for a cipher, or the encrypted
data itself.
Implementations are expected to provide the logic for:
- retrieve(key)
: Fetching a value given its key.
- store(key, value)
: Persisting a key-value pair.
- contains(key)
: Verifying if a key is present in the storage.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
K
|
TypeVar representing the type of the keys in the storage. This allows for flexibility in choosing key types, such as strings, integers, or custom hashable objects. |
required | |
V
|
TypeVar representing the type of the values in the storage. This allows for storing various kinds of data, from simple types to complex objects or serialized data. |
required |
Source code in topsecret/domain.py
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
|
contains(key)
¶
Checks if a key exists in the storage.
This method determines whether the storage holds any value associated
with the given key
. It provides an efficient way to query the
existence of a key without incurring the potential overhead of
retrieving the actual value (as the retrieve
method would do).
This is particularly useful for pre-flight checks before attempting
a retrieve
or store
operation (e.g., to decide whether to update
or insert), or for any logic that depends on the presence or absence
of a key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
K
|
The key to check for existence in the storage. Its type
must conform to the generic type |
required |
Returns:
Name | Type | Description |
---|---|---|
bool |
bool
|
|
Source code in topsecret/domain.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
|
retrieve(key)
¶
Retrieves the value associated with the given key.
This method attempts to find an entry in the storage that matches the
provided key. If a corresponding value exists, it is returned. If the
key is not found in the storage, this method must return None
.
This explicit None
return for non-existent keys allows callers to
reliably distinguish between a key not being found and a key being
associated with a None
value (if V
itself can be NoneType
).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
K
|
The key whose associated value is to be retrieved. The type
of the key must match the generic type |
required |
Returns:
Type | Description |
---|---|
V | None
|
V | None: The value associated with the specified |
Source code in topsecret/domain.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
|
store(key, value)
¶
Stores a key-value pair in the storage.
This method is responsible for persisting the given value
under the
specified key
. If the key
already exists in the storage, the
behavior (e.g., overwrite the existing value, raise an error, or ignore
the operation) is typically defined by the concrete implementation of
this protocol. However, a common expectation for key-value stores is
that the new value will replace any existing value for that key.
The method is expected to complete the storage operation and ensure the key-value pair is durably or appropriately stored according to the implementation's guarantees.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
K
|
The key under which the |
required |
value
|
V
|
The value to be stored. Its type must conform to the
generic type |
required |
Returns:
Name | Type | Description |
---|---|---|
None |
None
|
This method does not return any value. |
Source code in topsecret/domain.py
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
|
DecryptionError
¶
Bases: Exception
Custom exception raised when decryption fails.
This exception is typically raised when an attempt to decrypt data does not succeed. This can occur for several reasons, such as: 1. The provided passphrase or key is incorrect. 2. The ciphertext has been tampered with or is corrupted. 3. The encryption algorithm or mode of operation used during encryption is different from what is being used for decryption. 4. The ciphertext is not in the expected format.
Attributes:
Name | Type | Description |
---|---|---|
message |
str
|
A human-readable string describing the error. If no message is provided during instantiation, a default message is used. |
Source code in topsecret/domain.py
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
|
__init__(message='')
¶
Initializes a new DecryptionError instance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
message
|
str
|
A custom message describing the specific decryption error. If an empty string or no message is provided, a default error message "Failed to decrypt the data. The ciphertext may be corrupted or the passphrase is incorrect." will be used. This allows for more specific error reporting when the cause of the decryption failure is known, while providing a generic message otherwise. |
''
|
Source code in topsecret/domain.py
261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
|