{"record":{"id":"1674c64f6407d7b5","repo":"astrid-runtime/astrid","slug":"fingerprint-ed25519-public-key-e","errorCode":null,"errorMessage":"fingerprint Ed25519 public key: {e}","messagePattern":"fingerprint Ed25519 public key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/keypair.rs","lineNumber":607,"sourceCode":"        .all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-')\n    {\n        bail!(\"keypair name {name:?} contains invalid chars; only a-z, 0-9, '-' are allowed\");\n    }\n    Ok(())\n}\n\nfn default_name() -> String {\n    let mut bytes = [0u8; 4];\n    SysRng\n        .try_fill_bytes(&mut bytes)\n        .expect(\"OS CSPRNG unavailable while generating default keypair name\");\n    format!(\"key-{}\", hex::encode(bytes))\n}\n\nfn fingerprint_pubkey(hex_pub: &str) -> Result<String> {\n    PublicKeyFingerprint::from_ed25519_hex(hex_pub)\n        .map(PublicKeyFingerprint::into_inner)\n        .map_err(|e| anyhow::anyhow!(\"fingerprint Ed25519 public key: {e}\"))\n}\n\n/// Convert a 64-char hex ed25519 public key into the `ed25519:<base64>`\n/// wire form that `[distro.signing].pubkey`, `astrid distro seal`, and\n/// the distro trust store consume. Reuses `astrid-crypto`'s encoder so\n/// the base64 variant matches the verifier byte-for-byte.\nfn pubkey_hex_to_wire(pub_hex: &str) -> Result<String> {\n    let pk = astrid_crypto::PublicKey::from_hex(pub_hex.trim())\n        .map_err(|e| anyhow::anyhow!(\"decode public key hex: {e}\"))?;\n    Ok(format!(\"ed25519:{}\", pk.to_base64()))\n}\n\n/// Encode a 32-byte ed25519 public key in the `OpenSSH` wire format\n/// (`ssh-ed25519 <base64>` — RFC 8709 §4). Lets operators paste the\n/// same key into `authorized_keys` if they want to reuse it for SSH.\n/// The body is a length-prefixed type tag followed by the key.\nfn encode_openssh_ed25519(pubkey: &[u8]) -> String {\n    use base64::Engine;","sourceCodeStart":589,"sourceCodeEnd":625,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/keypair.rs#L589-L625","documentation":"fingerprint_pubkey converts a hex-encoded Ed25519 public key into the short `key-<hex>` fingerprint via astrid_crypto::PublicKeyFingerprint::from_ed25519_hex. When the input is not valid 64-char hex encoding of a 32-byte Ed25519 public key, the fingerprint parser fails and the error is wrapped as \"fingerprint Ed25519 public key: {e}\".","triggerScenarios":"Called from run_generate, read_meta, or fingerprint_is_stable_and_distinct with a string that isn't exactly 64 lowercase/uppercase hex chars (wrong length, non-hex characters, empty string, or the `ed25519:<base64>` wire form passed instead of hex).","commonSituations":"Storing the base64 wire form in metadata and later fingerprinting it directly; truncated key from copy/paste; reading a key file with trailing whitespace/newlines or a PEM header.","solutions":["Pass the 64-char hex public key (not the `ed25519:<base64>` wire form) to fingerprinting; convert wire form back to hex first if needed","Trim whitespace and strip any `0x` prefix or PEM headers from the key string before calling","Regenerate the keypair if the stored key is corrupt (astrid keypair generate)"],"exampleFix":"// before\nlet fp = fingerprint_pubkey(&wire)?; // \"ed25519:AbCd...\" not hex\n// after\nlet fp = fingerprint_pubkey(&hex_pub.trim())?; // 64-char hex","handlingStrategy":"validation","validationCode":"fn is_hex_ed25519_pubkey(s: &str) -> bool {\n    let s = s.trim();\n    s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":"fn fingerprintable(s: &str) -> bool {\n    let s = s.trim();\n    s.len() == 64 && s.chars().all(|c| c.is_ascii_hexdigit())\n}","tryCatchPattern":"match fingerprint_pubkey(hex_pub) {\n    Ok(fp) => fp,\n    Err(e) if e.to_string().starts_with(\"fingerprint Ed25519 public key\") => {\n        eprintln!(\"Key is not 64-char hex; convert wire form or re-copy the key\");\n        return Err(e);\n    }\n}","preventionTips":["Store keys in one canonical form (hex for metadata, wire form only in config) and convert explicitly","Trim whitespace/newlines when reading keys from files","Validate key length/format before persisting key metadata"],"tags":["crypto","ed25519","key-format"],"backgroundTag":"invalid-argument-format","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}