Marco Ricci commited on 2025-01-11 19:04:57
Zeige 1 geänderte Dateien mit 33 Einfügungen und 11 Löschungen.
This is a breaking API change, because some function return types have been widened.
... | ... |
@@ -126,7 +126,10 @@ class MasterKeys(TypedDict): |
126 | 126 |
"""""" |
127 | 127 |
|
128 | 128 |
|
129 |
-def derive_master_keys_keys(password: str | bytes, iterations: int) -> KeyPair: |
|
129 |
+def derive_master_keys_keys( |
|
130 |
+ password: str | Buffer, |
|
131 |
+ iterations: int, |
|
132 |
+) -> KeyPair: |
|
130 | 133 |
"""Derive encryption and signing keys for the master keys data. |
131 | 134 |
|
132 | 135 |
The master password is run through a key derivation function to |
... | ... |
@@ -161,7 +164,7 @@ def derive_master_keys_keys(password: str | bytes, iterations: int) -> KeyPair: |
161 | 164 |
length=2 * KEY_SIZE, |
162 | 165 |
salt=STOREROOM_MASTER_KEYS_UUID, |
163 | 166 |
iterations=iterations, |
164 |
- ).derive(password) |
|
167 |
+ ).derive(bytes(password)) |
|
165 | 168 |
encryption_key, signing_key = struct.unpack( |
166 | 169 |
f'{KEY_SIZE}s {KEY_SIZE}s', master_keys_keys_blob |
167 | 170 |
) |
... | ... |
@@ -183,7 +186,10 @@ def derive_master_keys_keys(password: str | bytes, iterations: int) -> KeyPair: |
183 | 186 |
} |
184 | 187 |
|
185 | 188 |
|
186 |
-def decrypt_master_keys_data(data: bytes, keys: KeyPair) -> MasterKeys: |
|
189 |
+def decrypt_master_keys_data( |
|
190 |
+ data: Buffer, |
|
191 |
+ keys: KeyPair, |
|
192 |
+) -> MasterKeys: |
|
187 | 193 |
r"""Decrypt the master keys data. |
188 | 194 |
|
189 | 195 |
The master keys data contains: |
... | ... |
@@ -230,6 +236,7 @@ def decrypt_master_keys_data(data: bytes, keys: KeyPair) -> MasterKeys: |
230 | 236 |
removal. |
231 | 237 |
|
232 | 238 |
""" |
239 |
+ data = memoryview(data).toreadonly().cast('c') |
|
233 | 240 |
ciphertext, claimed_mac = struct.unpack( |
234 | 241 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
235 | 242 |
) |
... | ... |
@@ -273,7 +280,10 @@ def decrypt_master_keys_data(data: bytes, keys: KeyPair) -> MasterKeys: |
273 | 280 |
} |
274 | 281 |
|
275 | 282 |
|
276 |
-def decrypt_session_keys(data: bytes, master_keys: MasterKeys) -> KeyPair: |
|
283 |
+def decrypt_session_keys( |
|
284 |
+ data: Buffer, |
|
285 |
+ master_keys: MasterKeys, |
|
286 |
+) -> KeyPair: |
|
277 | 287 |
r"""Decrypt the bucket item's session keys. |
278 | 288 |
|
279 | 289 |
The bucket item's session keys are single-use keys for encrypting |
... | ... |
@@ -318,6 +328,7 @@ def decrypt_session_keys(data: bytes, master_keys: MasterKeys) -> KeyPair: |
318 | 328 |
removal. |
319 | 329 |
|
320 | 330 |
""" |
331 |
+ data = memoryview(data).toreadonly().cast('c') |
|
321 | 332 |
ciphertext, claimed_mac = struct.unpack( |
322 | 333 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
323 | 334 |
) |
... | ... |
@@ -379,7 +390,10 @@ def decrypt_session_keys(data: bytes, master_keys: MasterKeys) -> KeyPair: |
379 | 390 |
return session_keys |
380 | 391 |
|
381 | 392 |
|
382 |
-def decrypt_contents(data: bytes, session_keys: KeyPair) -> bytes: |
|
393 |
+def decrypt_contents( |
|
394 |
+ data: Buffer, |
|
395 |
+ session_keys: KeyPair, |
|
396 |
+) -> Buffer: |
|
383 | 397 |
"""Decrypt the bucket item's contents. |
384 | 398 |
|
385 | 399 |
The data consists of: |
... | ... |
@@ -420,6 +434,7 @@ def decrypt_contents(data: bytes, session_keys: KeyPair) -> bytes: |
420 | 434 |
removal. |
421 | 435 |
|
422 | 436 |
""" |
437 |
+ data = memoryview(data).toreadonly().cast('c') |
|
423 | 438 |
ciphertext, claimed_mac = struct.unpack( |
424 | 439 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
425 | 440 |
) |
... | ... |
@@ -463,7 +478,10 @@ def decrypt_contents(data: bytes, session_keys: KeyPair) -> bytes: |
463 | 478 |
return plaintext |
464 | 479 |
|
465 | 480 |
|
466 |
-def decrypt_bucket_item(bucket_item: bytes, master_keys: MasterKeys) -> bytes: |
|
481 |
+def decrypt_bucket_item( |
|
482 |
+ bucket_item: Buffer, |
|
483 |
+ master_keys: MasterKeys, |
|
484 |
+) -> Buffer: |
|
467 | 485 |
"""Decrypt a bucket item. |
468 | 486 |
|
469 | 487 |
Args: |
... | ... |
@@ -491,6 +509,7 @@ def decrypt_bucket_item(bucket_item: bytes, master_keys: MasterKeys) -> bytes: |
491 | 509 |
removal. |
492 | 510 |
|
493 | 511 |
""" |
512 |
+ bucket_item = memoryview(bucket_item).toreadonly().cast('c') |
|
494 | 513 |
logger.debug( |
495 | 514 |
_msg.TranslatedString( |
496 | 515 |
_msg.DebugMsgTemplate.DECRYPT_BUCKET_ITEM_KEY_INFO, |
... | ... |
@@ -518,7 +537,7 @@ def decrypt_bucket_file( |
518 | 537 |
master_keys: MasterKeys, |
519 | 538 |
*, |
520 | 539 |
root_dir: str | bytes | os.PathLike = '.', |
521 |
-) -> Iterator[bytes]: |
|
540 |
+) -> Iterator[Buffer]: |
|
522 | 541 |
"""Decrypt a complete bucket. |
523 | 542 |
|
524 | 543 |
Args: |
... | ... |
@@ -599,7 +618,7 @@ def _store(config: dict[str, Any], path: str, json_contents: bytes) -> None: |
599 | 618 |
|
600 | 619 |
def export_storeroom_data( # noqa: C901,PLR0912,PLR0914,PLR0915 |
601 | 620 |
storeroom_path: str | bytes | os.PathLike | None = None, |
602 |
- master_keys_key: str | bytes | None = None, |
|
621 |
+ master_keys_key: str | Buffer | None = None, |
|
603 | 622 |
) -> dict[str, Any]: |
604 | 623 |
"""Export the full configuration stored in the storeroom. |
605 | 624 |
|
... | ... |
@@ -632,6 +651,8 @@ def export_storeroom_data( # noqa: C901,PLR0912,PLR0914,PLR0915 |
632 | 651 |
storeroom_path = exporter.get_vault_path() |
633 | 652 |
if master_keys_key is None: |
634 | 653 |
master_keys_key = exporter.get_vault_key() |
654 |
+ elif not isinstance(master_keys_key, str): |
|
655 |
+ master_keys_key = memoryview(master_keys_key).toreadonly().cast('c') |
|
635 | 656 |
with open( |
636 | 657 |
os.path.join(os.fsdecode(storeroom_path), '.keys'), encoding='utf-8' |
637 | 658 |
) as master_keys_file: |
... | ... |
@@ -676,9 +697,10 @@ def export_storeroom_data( # noqa: C901,PLR0912,PLR0914,PLR0915 |
676 | 697 |
bucket_number=file, |
677 | 698 |
) |
678 | 699 |
) |
679 |
- bucket_contents = list( |
|
680 |
- decrypt_bucket_file(file, master_keys, root_dir=storeroom_path) |
|
681 |
- ) |
|
700 |
+ bucket_contents = [ |
|
701 |
+ bytes(item) |
|
702 |
+ for item in decrypt_bucket_file(file, master_keys, root_dir=storeroom_path) |
|
703 |
+ ] |
|
682 | 704 |
bucket_index = json.loads(bucket_contents.pop(0)) |
683 | 705 |
for pos, item in enumerate(bucket_index): |
684 | 706 |
json_contents[item] = bucket_contents[pos] |
685 | 707 |