nixfleet_cli/commands/
derive_pubkey.rs

1//! Operator helper: ed25519 private key file -> base64 public key.
2//!
3//! Folded from the former `nixfleet-derive-pubkey` binary. Subcommand
4//! form: `nixfleet derive-pubkey <path>`.
5
6use std::path::PathBuf;
7
8use anyhow::{Context, Result};
9use base64::Engine;
10// Alias required: `struct Args` below shares its name with the clap trait.
11use clap::Args as ClapArgs;
12use ed25519_dalek::{SigningKey, VerifyingKey};
13
14#[derive(ClapArgs, Debug)]
15#[command(about = "Derive base64 ed25519 pubkey from a raw private key file.")]
16pub struct Args {
17    /// Path to a private key file: 32 raw bytes, hex, or PKCS#8 PEM.
18    pub private_key_path: PathBuf,
19}
20
21pub fn run(args: Args) -> Result<()> {
22    let bytes = std::fs::read(&args.private_key_path)
23        .with_context(|| format!("read {}", args.private_key_path.display()))?;
24
25    let arr: [u8; 32] = if bytes.len() >= 32 {
26        bytes[..32]
27            .try_into()
28            .expect("slice of length 32 fits [u8; 32] - len checked above")
29    } else {
30        anyhow::bail!("expected at least 32 bytes, got {}", bytes.len());
31    };
32    let sk = SigningKey::from_bytes(&arr);
33    let vk: VerifyingKey = sk.verifying_key();
34    println!(
35        "{}",
36        base64::engine::general_purpose::STANDARD.encode(vk.to_bytes())
37    );
38    Ok(())
39}