Same treatment for the prose the compiler carries: doc and line comments across src/ and tests/, test assertion and error-message strings (prose surfaces: the tunnel-map registration/establish errors, the key-source decode payload, assertion messages), scripts/matrix.sh comment lines, the fuzz sidecar's comments and README (corpus seeds untouched), and the Cargo.toml comment headers plus the crates.io description. The AGENTS.md no-em-dash rule (convention 14) now holds for the whole tracked tree. Verification: repo-wide git grep is clean (single exempt hit: the verification command's own search pattern), cargo test (18 suites, zero failures, default and per-feature builds via scripts/matrix.sh), clippy --all-targets -D warnings and clippy all-features, fmt --check, doc --no-deps, and the fuzz corpus gate (fuzz/shared, 11 tests) all green.
147 lines
5.6 KiB
Rust
147 lines
5.6 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('!'));
|
|
}
|