Marco Ricci commited on 2025-01-16 01:05:38
Zeige 3 geänderte Dateien mit 48 Einfügungen und 16 Löschungen.
Parametrize `_types.SSHKeyCommentPair`, `_types.StoreroomKeyPair` and `_types.StoreroomMasterKeys` over the exact `Buffer` type being used. Also supply a `.toreadonly()` method (similar to `memoryview.toreadonly()`) that converts all `Buffer`s to `bytes` objects.
... | ... |
@@ -11,9 +11,10 @@ import enum |
11 | 11 |
import json |
12 | 12 |
import math |
13 | 13 |
import string |
14 |
-from typing import TYPE_CHECKING |
|
14 |
+from typing import TYPE_CHECKING, Generic, TypeVar |
|
15 | 15 |
|
16 | 16 |
from typing_extensions import ( |
17 |
+ Buffer, |
|
17 | 18 |
NamedTuple, |
18 | 19 |
NotRequired, |
19 | 20 |
TypedDict, |
... | ... |
@@ -577,7 +578,10 @@ def clean_up_falsy_vault_config_values( # noqa: C901,PLR0912 |
577 | 578 |
return cleanup_completed |
578 | 579 |
|
579 | 580 |
|
580 |
-class SSHKeyCommentPair(NamedTuple): |
|
581 |
+B = TypeVar('B', bound=Buffer) |
|
582 |
+ |
|
583 |
+ |
|
584 |
+class SSHKeyCommentPair(NamedTuple, Generic[B]): |
|
581 | 585 |
"""SSH key plus comment pair. For typing purposes. |
582 | 586 |
|
583 | 587 |
Attributes: |
... | ... |
@@ -586,11 +590,18 @@ class SSHKeyCommentPair(NamedTuple): |
586 | 590 |
|
587 | 591 |
""" |
588 | 592 |
|
589 |
- key: bytes | bytearray |
|
593 |
+ key: B |
|
590 | 594 |
"""""" |
591 |
- comment: bytes | bytearray |
|
595 |
+ comment: B |
|
592 | 596 |
"""""" |
593 | 597 |
|
598 |
+ def toreadonly(self) -> SSHKeyCommentPair[bytes]: |
|
599 |
+ """Return a copy with read-only entries.""" |
|
600 |
+ return SSHKeyCommentPair( |
|
601 |
+ key=bytes(self.key), |
|
602 |
+ comment=bytes(self.comment), |
|
603 |
+ ) |
|
604 |
+ |
|
594 | 605 |
|
595 | 606 |
class SSH_AGENTC(enum.Enum): # noqa: N801 |
596 | 607 |
"""SSH agent protocol numbers: client requests. |
... | ... |
@@ -662,7 +673,7 @@ class SSH_AGENT(enum.Enum): # noqa: N801 |
662 | 673 |
"""""" |
663 | 674 |
|
664 | 675 |
|
665 |
-class StoreroomKeyPair(NamedTuple): |
|
676 |
+class StoreroomKeyPair(NamedTuple, Generic[B]): |
|
666 | 677 |
"""A pair of AES256 keys, one for encryption and one for signing. |
667 | 678 |
|
668 | 679 |
Attributes: |
... | ... |
@@ -674,13 +685,20 @@ class StoreroomKeyPair(NamedTuple): |
674 | 685 |
|
675 | 686 |
""" |
676 | 687 |
|
677 |
- encryption_key: bytes |
|
688 |
+ encryption_key: B |
|
678 | 689 |
"""""" |
679 |
- signing_key: bytes |
|
690 |
+ signing_key: B |
|
680 | 691 |
"""""" |
681 | 692 |
|
693 |
+ def toreadonly(self) -> StoreroomKeyPair[bytes]: |
|
694 |
+ """Return a copy with read-only entries.""" |
|
695 |
+ return StoreroomKeyPair( |
|
696 |
+ encryption_key=bytes(self.encryption_key), |
|
697 |
+ signing_key=bytes(self.signing_key), |
|
698 |
+ ) |
|
699 |
+ |
|
682 | 700 |
|
683 |
-class StoreroomMasterKeys(NamedTuple): |
|
701 |
+class StoreroomMasterKeys(NamedTuple, Generic[B]): |
|
684 | 702 |
"""A triple of AES256 keys, for encryption, signing and hashing. |
685 | 703 |
|
686 | 704 |
Attributes: |
... | ... |
@@ -695,9 +713,17 @@ class StoreroomMasterKeys(NamedTuple): |
695 | 713 |
|
696 | 714 |
""" |
697 | 715 |
|
698 |
- hashing_key: bytes |
|
716 |
+ hashing_key: B |
|
699 | 717 |
"""""" |
700 |
- encryption_key: bytes |
|
718 |
+ encryption_key: B |
|
701 | 719 |
"""""" |
702 |
- signing_key: bytes |
|
720 |
+ signing_key: B |
|
703 | 721 |
"""""" |
722 |
+ |
|
723 |
+ def toreadonly(self) -> StoreroomMasterKeys[bytes]: |
|
724 |
+ """Return a copy with read-only entries.""" |
|
725 |
+ return StoreroomMasterKeys( |
|
726 |
+ hashing_key=bytes(self.hashing_key), |
|
727 |
+ encryption_key=bytes(self.encryption_key), |
|
728 |
+ signing_key=bytes(self.signing_key), |
|
729 |
+ ) |
... | ... |
@@ -147,7 +147,7 @@ def derive_master_keys_keys( |
147 | 147 |
return _types.StoreroomKeyPair( |
148 | 148 |
encryption_key=encryption_key, |
149 | 149 |
signing_key=signing_key, |
150 |
- ) |
|
150 |
+ ).toreadonly() |
|
151 | 151 |
|
152 | 152 |
|
153 | 153 |
def decrypt_master_keys_data( |
... | ... |
@@ -201,6 +201,7 @@ def decrypt_master_keys_data( |
201 | 201 |
|
202 | 202 |
""" |
203 | 203 |
data = memoryview(data).toreadonly().cast('c') |
204 |
+ keys = keys.toreadonly() |
|
204 | 205 |
ciphertext, claimed_mac = struct.unpack( |
205 | 206 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
206 | 207 |
) |
... | ... |
@@ -241,7 +242,7 @@ def decrypt_master_keys_data( |
241 | 242 |
hashing_key=hashing_key, |
242 | 243 |
encryption_key=encryption_key, |
243 | 244 |
signing_key=signing_key, |
244 |
- ) |
|
245 |
+ ).toreadonly() |
|
245 | 246 |
|
246 | 247 |
|
247 | 248 |
def decrypt_session_keys( |
... | ... |
@@ -293,6 +294,7 @@ def decrypt_session_keys( |
293 | 294 |
|
294 | 295 |
""" |
295 | 296 |
data = memoryview(data).toreadonly().cast('c') |
297 |
+ master_keys = master_keys.toreadonly() |
|
296 | 298 |
ciphertext, claimed_mac = struct.unpack( |
297 | 299 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
298 | 300 |
) |
... | ... |
@@ -333,7 +335,7 @@ def decrypt_session_keys( |
333 | 335 |
session_keys = _types.StoreroomKeyPair( |
334 | 336 |
encryption_key=session_encryption_key, |
335 | 337 |
signing_key=session_signing_key, |
336 |
- ) |
|
338 |
+ ).toreadonly() |
|
337 | 339 |
|
338 | 340 |
logger.debug( |
339 | 341 |
_msg.TranslatedString( |
... | ... |
@@ -399,6 +401,7 @@ def decrypt_contents( |
399 | 401 |
|
400 | 402 |
""" |
401 | 403 |
data = memoryview(data).toreadonly().cast('c') |
404 |
+ session_keys = session_keys.toreadonly() |
|
402 | 405 |
ciphertext, claimed_mac = struct.unpack( |
403 | 406 |
f'{len(data) - MAC_SIZE}s {MAC_SIZE}s', data |
404 | 407 |
) |
... | ... |
@@ -474,6 +477,7 @@ def decrypt_bucket_item( |
474 | 477 |
|
475 | 478 |
""" |
476 | 479 |
bucket_item = memoryview(bucket_item).toreadonly().cast('c') |
480 |
+ master_keys = master_keys.toreadonly() |
|
477 | 481 |
logger.debug( |
478 | 482 |
_msg.TranslatedString( |
479 | 483 |
_msg.DebugMsgTemplate.DECRYPT_BUCKET_ITEM_KEY_INFO, |
... | ... |
@@ -532,6 +536,7 @@ def decrypt_bucket_file( |
532 | 536 |
removal. |
533 | 537 |
|
534 | 538 |
""" |
539 |
+ master_keys = master_keys.toreadonly() |
|
535 | 540 |
with open( |
536 | 541 |
os.path.join(os.fsdecode(root_dir), filename), 'rb' |
537 | 542 |
) as bucket_file: |
... | ... |
@@ -559,9 +559,10 @@ class TestAgentInteraction: |
559 | 559 |
with monkeypatch.context() as monkeypatch2: |
560 | 560 |
client = ssh_agent.SSHAgentClient() |
561 | 561 |
monkeypatch2.setattr(client, 'request', request) |
562 |
- SSHKeyCommentPair = _types.SSHKeyCommentPair # noqa: N806 |
|
562 |
+ Pair = _types.SSHKeyCommentPair # noqa: N806 |
|
563 |
+ com = b'no comment' |
|
563 | 564 |
loaded_keys = [ |
564 |
- SSHKeyCommentPair(v.public_key_data, b'no comment') |
|
565 |
+ Pair(v.public_key_data, com).toreadonly() |
|
565 | 566 |
for v in tests.SUPPORTED_KEYS.values() |
566 | 567 |
] |
567 | 568 |
monkeypatch2.setattr(client, 'list_keys', lambda: loaded_keys) |
568 | 569 |