Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

crates/installer/nordisk-narrate/src/seedkey.rs

//! **The installer's public key, out of a medium's seed** — leniently.
//!
//! The narration exists for the box that goes wrong, and one way a box goes
//! wrong is a seed that fails its own check (`nordisk_pairing::seed::Seed::check`
//! refuses it by name, and the installer's link never comes up). So the sender
//! does NOT require a seed that passes: it reads the ONE value it needs,
//! `installer_link.installer_pubkey`, out of whatever TOML is there.

use base64::Engine as _;

/// Where the medium's seed is, under the data root (gunnar-server
/// `pairing::SEED_REL`, holger the same): `<data>/pairing/seed.toml`.
pub const SEED_REL: &str = "pairing/seed.toml";

/// A WireGuard/X25519 key in its usual spelling (44 base64 characters).
pub fn key_of_b64(s: &str) -> Result<[u8; 32], String> {
    let b = base64::engine::general_purpose::STANDARD.decode(s.trim()).map_err(|e| format!("`{}…` is not base64: {e}", s.trim().chars().take(6).collect::<String>()))?;
    b.try_into().map_err(|b: Vec<u8>| format!("a key is 32 bytes, this one is {}", b.len()))
}

/// The same key, spelled back.
pub fn b64_of_key(k: &[u8; 32]) -> String {
    base64::engine::general_purpose::STANDARD.encode(k)
}

/// **`installer_link.installer_pubkey` of a seed's TOML text.** Only this value
/// is read; every other field may be broken.
pub fn installer_pubkey(seed_toml: &str) -> Result<[u8; 32], String> {
    let v: toml::Value = toml::from_str(seed_toml).map_err(|e| format!("the seed is not TOML: {}", e.message()))?;
    let k = v
        .get("installer_link")
        .and_then(|l| l.get("installer_pubkey"))
        .and_then(|k| k.as_str())
        .ok_or("the seed has no `installer_link.installer_pubkey`")?;
    key_of_b64(k).map_err(|e| format!("`installer_link.installer_pubkey`: {e}"))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn the_installer_key_is_read_out_of_a_seed_that_fails_its_own_check() {
        let k = [0x42u8; 32];
        let seed = format!(
            "estate = \"gunnar\"\nkind = \"front\"\ninstaller_ca_pem = \"broken\"\n[installer_link]\ninstaller_pubkey = \"{}\"\nvm_private = \"not a key\"\n",
            b64_of_key(&k)
        );
        assert_eq!(installer_pubkey(&seed), Ok(k), "every other field may be broken");
        assert!(installer_pubkey("estate = \"x\"\n").unwrap_err().contains("installer_pubkey"));
        assert!(installer_pubkey("[installer_link]\ninstaller_pubkey = \"AAAA\"\n").unwrap_err().contains("32 bytes"));
        assert!(installer_pubkey("not = toml = at all").unwrap_err().contains("not TOML"));
    }
}