Files
alkssh/tests/fingerprint_parity.rs
T
glm-5.3-flash 214690b9c2 test(doubles): land the wave-1 in-memory seams + unified ed25519 fixtures
The `w1-test-doubles` task: the in-memory seams every later wave's
contract tests run against, behind their production seams.

- tests/common/mod.rs — the doubles, test-only (nothing reachable from
  lib.rs, no feature): MemIdentityProvider (registered fingerprints ->
  alkcall Identity resolutions over the IdentityProvider trait; token
  path resolves none per ADR-004), TestVault (a wrapper over alkvault
  0.1's shipped in-memory construction — resolving the flagged
  vault-double question: wrap, not re-impl), MemHostKeyPolicy
  (exact (host, fingerprint) rules + explicit default verdict,
  fail-closed by default, inspectable decision log), and the fixture
  table. Module docs record the location/vault/fixture decisions and
  the row/stamp discipline (greppable Contract stamps).
- tests/vectors/ — one unified fixture set: four ssh-keygen-minted
  ed25519 keypairs (committed .key + .pub + fingerprints.txt recorded
  from ssh-keygen -lf, OpenSSH_9.6p1). The previous inline PEM
  constants in src/key_source.rs were rejected by OpenSSH itself
  (russh-only decodable); all keys were re-minted and the overlapping
  vector set retired — one fixture set now serves the parity tests,
  the custody round-trip, and every later auth/mapping test
  (src-unit tests share it via include_str!).
- tests/doubles.rs — the end-to-end rows: register -> resolve,
  seal -> source -> decode (+ locked/absent/tampered postures),
  host-key set in order, policy verdicts honored-and-logged.
- tests/fingerprint_parity.rs and src/key_source.rs tests moved onto
  the shared fixture files; src changes are #cfg(test) only.

Verification: cargo test (33 + 9 + 5 green; --all-features also green),
cargo clippy --all-targets -- -D warnings clean, cargo fmt --check
clean, taskgraph validate ok (12 tasks).
2026-10-28 07:09:17 +00:00

147 lines
5.7 KiB
Rust

//! Fingerprint-format parity — ADR-004 decision 1's contract
//! invariant proven against independent-issuer vectors (POC-1 §1).
//!
//! The vectors are the wave-1 test-key fixture set
//! (`tests/common/mod.rs`'s [`FIXTURE_KEYS`]; the committed files
//! under `tests/vectors/`), each key's fingerprint recorded
//! byte-verbatim from `ssh-keygen -lf` (OpenSSH 9.6p1, at
//! vector-generation time; see `tests/vectors/fingerprints.txt`). The
//! crate's single fingerprint path must reproduce those strings
//! exactly from every issuer shape — the committed public blob, the
//! private key's derived public half, and the committed `.pub` file —
//! so registration values from any standard issuer compare equal,
//! without cross-issuer drift.
mod common;
use std::fs;
use common::FIXTURE_KEYS;
const VECTOR_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/vectors");
/// The crate's single fingerprint path reproduces the recorded value
/// from the committed public blob alone — the public-key-only issuer
/// shape (a registry that only ever sees public material).
///
/// - *Contract stamp:* ADR-004 decision 1 (fingerprint parity with
/// `ssh-keygen -lf`; POC-1 §1's parity checkpoint shape).
#[test]
fn computed_fingerprints_match_recorded_values_for_public_blobs() {
for key in FIXTURE_KEYS {
let parsed = russh::keys::parse_public_key_base64(key.blob)
.expect("committed fixture blob parses as OpenSSH key material");
assert_eq!(
alkssh::fingerprint(&parsed),
key.fingerprint,
"parity drift on {name}",
name = key.name
);
}
}
/// The private-key path — the shape every auth/mapping test uses
/// (`decode_secret_key` → sign/serve) — yields a public half whose
/// fingerprint is the same recorded value.
///
/// - *Contract stamp:* ADR-004 decision 1 (the fingerprint string
/// format is a contract invariant across issuers).
#[test]
fn private_derived_fingerprints_match_recorded_values() {
for key in FIXTURE_KEYS {
let decoded = key.private_key();
assert_eq!(
alkssh::fingerprint(decoded.public_key()),
key.fingerprint,
"private-derived parity drift on {name}",
name = key.name
);
}
}
/// The committed fixture files are the recorded keys: each `.pub`
/// starts with the recorded blob line, and each `.key` is an
/// unencrypted OpenSSH private-key PEM (the ADR-005 decision 1 inner
/// format) whose decoded public half fingerprints to the recorded
/// value.
///
/// - *Contract stamp:* ADR-004 decision 1 (independent-issuer vectors
/// are the parity proof — the commitment must be the recorded key).
/// - *Contract stamp:* ADR-005 decision 1 (the fixtures' inner format
/// is exactly the at-rest contract: unencrypted OpenSSH PEM).
#[test]
fn committed_fixture_files_match_the_recorded_keys() {
for key in FIXTURE_KEYS {
let pub_path = format!("{VECTOR_DIR}/{}.pub", key.name);
let pub_file = fs::read_to_string(&pub_path).expect("committed .pub readable");
let expected_line = format!("ssh-ed25519 {blob} ", blob = key.blob);
assert!(
pub_file.starts_with(&expected_line),
"fixture file {name} does not start with the recorded blob",
name = key.name
);
let key_path = format!("{VECTOR_DIR}/{}.key", key.name);
let key_file = fs::read_to_string(&key_path).expect("committed .key readable");
assert!(
key_file.starts_with("-----BEGIN OPENSSH PRIVATE KEY-----"),
"fixture {name} is not an OpenSSH private-key PEM",
name = key.name
);
assert_eq!(key_file, key.pem, "committed .key is the fixture PEM");
assert!(
!key_file.contains("ENCRYPTED"),
"fixture {name} is unencrypted (ADR-005 decision 1)",
name = key.name
);
let decoded = key.private_key();
let from_file = decoded.public_key();
assert_eq!(
alkssh::fingerprint(from_file),
key.fingerprint,
"committed .key public half drifts on {name}",
name = key.name
);
}
}
/// The recorded manifest (`tests/vectors/fingerprints.txt`) records
/// every fixture — no fixture ships without its independent issuer's
/// fingerprint.
///
/// - *Contract stamp:* wave-1 test-double convention (recorded
/// `ssh-keygen -lf` fingerprints, the independent-issuer record).
#[test]
fn recorded_manifest_covers_every_fixture() {
let manifest =
fs::read_to_string(format!("{VECTOR_DIR}/fingerprints.txt")).expect("manifest readable");
for key in FIXTURE_KEYS {
assert!(
manifest.contains(&format!("{}.pub {fp}", key.name, fp = key.fingerprint)),
"manifest does not record {name} at {fp}",
name = key.name,
fp = key.fingerprint
);
}
}
/// The registered-string comparison is byte-identical: the computed
/// value meets a registered `ssh-keygen` string with no padding or
/// url-safe-alphabet drift (`+`/`/`, no `=`).
///
/// - *Contract stamp:* ADR-004 decision 1 (`SHA256:` + unpadded
/// base64, standard alphabet — byte-identical comparison by
/// contract).
#[test]
fn registered_string_compare_is_byte_identical() {
let alpha = FIXTURE_KEYS
.iter()
.find(|k| k.name == "alpha")
.expect("alpha fixture present");
let computed = alkssh::fingerprint(&alpha.public_key());
let registered: &str = alpha.fingerprint;
assert_eq!(computed, registered);
assert_eq!(registered.len(), 50, "SHA256: + 43 unpadded base64 chars");
assert!(!registered.contains('=') && !registered.contains('!'));
}