test(seed): pin known answers for the six unpinned derivations
`test_node_key_known_answer_vs_python_verifier` pinned the node Ed25519 and node Nostr keys, and `test_release_root_known_answer` covers the release root. The remaining six — FIPS mesh transport, identity Ed25519, identity Nostr (NIP-06), Bitcoin BIP-84 and LND aezeed entropy — were only asserted to be mutually distinct by `test_full_derivation_from_known_mnemonic`. Distinctness is satisfied by ANY change to an HKDF info string or BIP-32 path. So redefining `archipelago/lnd/entropy/v1` — the seed behind a user's Lightning wallet — broke no test, while invalidating every backup verification a user had already performed against docs/SEED-VERIFICATION.md. Same for the FIPS key that authenticates a node on the mesh. Expected values were produced independently by the Python verifier published in that doc, whose primitives were themselves cross-checked against bip_utils and cryptography's own HKDF (BIP-39 seed, both BIP-32 paths, x-only pubkey, bech32 and HKDF-SHA256 salt=None all matched byte for byte). This commit closes the loop in the other direction: the Rust implementation now agrees with those same bytes, so the doc and the code are pinned to each other. Verified: 26/26 seed tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ecd9295e96
commit
0b7fabdfa1
@@ -919,6 +919,79 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// Known answers for the derivations the test above does NOT pin.
|
||||
///
|
||||
/// `test_full_derivation_from_known_mnemonic` only asserts these are
|
||||
/// mutually distinct, which is satisfied by ANY change to an HKDF info
|
||||
/// string or BIP-32 path. That left the LND entropy — the seed behind a
|
||||
/// user's Lightning wallet — and the FIPS mesh transport key with no
|
||||
/// known-answer coverage at all: silently redefining either broke no test
|
||||
/// while invalidating every backup verification a user had already done.
|
||||
///
|
||||
/// The expected values were produced independently by the Python verifier
|
||||
/// published in `docs/SEED-VERIFICATION.md`, whose primitives were in turn
|
||||
/// cross-checked against `bip_utils` and `cryptography`'s own HKDF. If one
|
||||
/// of these assertions fails, either a derivation changed (and every
|
||||
/// published backup-verification instruction is now wrong), or the doc and
|
||||
/// the code have drifted apart — both are release-blocking.
|
||||
#[test]
|
||||
fn test_all_derivations_known_answers_vs_python_verifier() {
|
||||
let (_, seed) = MasterSeed::from_mnemonic_words(TEST_MNEMONIC).unwrap();
|
||||
|
||||
// HKDF "archipelago/fips/secp256k1/v1"
|
||||
assert_eq!(
|
||||
derive_fips_key(&seed).unwrap().public_key().to_hex(),
|
||||
"31865360f8cfb8bc3d0d5343bf09f1bc5c17b7f0b509120e94cdbed47d203bca",
|
||||
"FIPS mesh transport key"
|
||||
);
|
||||
|
||||
// HKDF "archipelago/identity/{i}/ed25519/v1"
|
||||
assert_eq!(
|
||||
hex::encode(
|
||||
derive_identity_ed25519(&seed, 0)
|
||||
.unwrap()
|
||||
.verifying_key()
|
||||
.as_bytes()
|
||||
),
|
||||
"c0415866117dd570e908e1b178bf1dd8f7b9cdb8eb662353165c6f4877fe222b",
|
||||
"identity[0] Ed25519"
|
||||
);
|
||||
assert_eq!(
|
||||
hex::encode(
|
||||
derive_identity_ed25519(&seed, 1)
|
||||
.unwrap()
|
||||
.verifying_key()
|
||||
.as_bytes()
|
||||
),
|
||||
"be7a0e1fe2711dedbbba976a70443e0a70e673bcf7b6e6a8fb20d1d2684e5eba",
|
||||
"identity[1] Ed25519 — pins the index into the info string"
|
||||
);
|
||||
|
||||
// BIP-32 m/44'/1237'/0'/0/{i} (NIP-06)
|
||||
assert_eq!(
|
||||
derive_nostr_identity_key(&seed, 0)
|
||||
.unwrap()
|
||||
.public_key()
|
||||
.to_hex(),
|
||||
"1ca7e48a33d62063f25d79f18617cc892ef064628aaf80af485e41849343ca52",
|
||||
"identity[0] Nostr (NIP-06)"
|
||||
);
|
||||
|
||||
// BIP-32 m/84'/0'/0'
|
||||
assert_eq!(
|
||||
hex::encode(derive_bitcoin_xprv(&seed).unwrap().private_key.secret_bytes()),
|
||||
"57558e8c90c2e72f0c121d0fb8844bbbe7a872f0065d21b218a990450b9f93be",
|
||||
"Bitcoin BIP-84 account key"
|
||||
);
|
||||
|
||||
// HKDF "archipelago/lnd/entropy/v1" (16 bytes)
|
||||
assert_eq!(
|
||||
hex::encode(derive_lnd_entropy(&seed).unwrap()),
|
||||
"5c86f10629bd86cdd269b82a76cc51e4",
|
||||
"LND aezeed entropy"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_release_root_deterministic_and_domain_separated() {
|
||||
let (_, seed) = MasterSeed::from_mnemonic_words(TEST_MNEMONIC).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user