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 |