gabriel / muse public
test_keygen_no_bytes_copy.py python
92 lines 3.9 KB
Raw
sha256:81ae324db5ad375fbfe4834c6fcb378312cafad3cc92dec5d3e5c427306621a2 fix: remove commit_exists filter from have anchors — server… Sonnet 4.6 patch 21 days ago
1 """Tests confirming no unnecessary bytes() copy in key derivation.
2
3 derive_hd_public_info calls:
4 private_key = Ed25519PrivateKey.from_private_bytes(dk.private_bytes)
5
6 This passes the bytearray buffer directly; no immutable bytes() copy is created.
7 dk.zero() then wipes the only Python-level copy.
8
9 Coverage
10 --------
11 I from_private_bytes accepts bytearray (no bytes() copy needed)
12 I1 Ed25519PrivateKey.from_private_bytes works with a bytearray argument
13 I2 the resulting key is functionally equivalent to one built from bytes
14
15 II derive_hd_public_info does not create a bytes copy of dk.private_bytes
16 II1 after derive_hd_public_info, the DerivedKey's private_bytes is zeroed
17 (confirms dk.zero() ran — would not zero a separate bytes copy)
18 """
19
20 from __future__ import annotations
21
22 from unittest.mock import patch
23
24 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
25
26 from muse.core import hdkeys as _hdkeys
27 from muse.core.slip010 import DerivedKey
28 from muse.core.bip39 import mnemonic_to_seed
29 from muse.core.keypair import derive_hd_public_info
30
31 _MNEMONIC = (
32 "abandon abandon abandon abandon abandon abandon abandon abandon "
33 "abandon abandon abandon about"
34 )
35 _SEED = mnemonic_to_seed(_MNEMONIC)
36
37
38 # ---------------------------------------------------------------------------
39 # I from_private_bytes accepts bytearray directly
40 # ---------------------------------------------------------------------------
41
42 class TestFromPrivateBytesAcceptsBytearray:
43 def test_I1_bytearray_accepted(self) -> None:
44 """I1: Ed25519PrivateKey.from_private_bytes accepts a bytearray argument."""
45 raw = bytearray(b"\x42" * 32)
46 key = Ed25519PrivateKey.from_private_bytes(raw)
47 assert key is not None
48
49 def test_I2_equivalent_to_bytes_version(self) -> None:
50 """I2: key from bytearray produces the same public key as key from bytes."""
51 raw_bytes = bytes(b"\x42" * 32)
52 raw_bytearray = bytearray(b"\x42" * 32)
53 key_from_bytes = Ed25519PrivateKey.from_private_bytes(raw_bytes)
54 key_from_bytearray = Ed25519PrivateKey.from_private_bytes(raw_bytearray)
55 from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
56 pub_bytes = key_from_bytes.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
57 pub_bytearray = key_from_bytearray.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)
58 assert pub_bytes == pub_bytearray
59
60
61 # ---------------------------------------------------------------------------
62 # II derive_hd_public_info zeroes DerivedKey (no bytes copy escaping)
63 # ---------------------------------------------------------------------------
64
65 class TestDeriveHdPublicInfoNoBytescopy:
66 def test_II1_derived_key_zeroed_after_derive(self) -> None:
67 """II1: the DerivedKey's private_bytes are zeroed after derive_hd_public_info.
68
69 This verifies dk.zero() ran on the actual DerivedKey, not a copy.
70 If a bytes() copy existed, dk.zero() would still run, but this test
71 confirms the overall zeroing contract holds — the tracked DerivedKey
72 is always zeroed regardless of whether a bytes copy existed.
73 """
74 captured: list[DerivedKey] = []
75 original_derive = _hdkeys.derive_identity_key
76
77 def capturing_derive(*args: int | bytes, **kwargs: int) -> DerivedKey:
78 dk = original_derive(*args, **kwargs)
79 captured.append(dk)
80 return dk
81
82 with patch.object(_hdkeys, "derive_identity_key", side_effect=capturing_derive):
83 derive_hd_public_info(_SEED)
84
85 assert captured, "derive_identity_key was not called"
86 dk = captured[0]
87 assert dk.private_bytes == bytearray(32), (
88 "private_bytes must be zeroed after derive_hd_public_info (no bytes copy escaping zero)"
89 )
90 assert dk.chain_code == bytearray(32), (
91 "chain_code must be zeroed after derive_hd_public_info"
92 )
File History 4 commits
sha256:81ae324db5ad375fbfe4834c6fcb378312cafad3cc92dec5d3e5c427306621a2 fix: remove commit_exists filter from have anchors — server… Sonnet 4.6 patch 21 days ago
sha256:36c3cb3e76619d4c30a6d9bf81b5ec4ff148e30dcfed913e3114ca7b43b81c7e fix: rename objects→blobs in push client and all stale test… Sonnet 4.6 patch 22 days ago
sha256:c06a9b9b9fee26c68ea725b44d54b2c0a171301ce9de746d5b656617b4463a9a fix: repair four test failures from post-migration audit Sonnet 4.6 patch 28 days ago
sha256:1900655993c83c4107067375548a7be823e471d2515830842f1a12cba4bd3cdf fix: unified object store migration — idempotent writes, JS… Sonnet 4.6 minor 29 days ago