use std::path::Path;
use std::fs;
use anyhow::{Result, anyhow};
use tracing::info;
use ed25519_dalek::SigningKey;
use iroh_base::SecretKey;
pub fn load_or_create_key(
explicit_path: &Option<std::path::PathBuf>,
default_dir: &Path,
) -> Result<SigningKey> {
let key_path = match explicit_path {
Some(p) => p.clone(),
None => match std::env::var("TRIBLESPACE_KEY") {
Ok(s) => std::path::PathBuf::from(s),
Err(_) => default_dir.join("self.key"),
},
};
if key_path.exists() {
return load_key_from_file(&key_path);
}
let key = generate_key()?;
let hex_str = hex::encode(key.to_bytes());
fs::write(&key_path, &hex_str)
.map_err(|e| anyhow!("write key to {}: {e}", key_path.display()))?;
info!(path = %key_path.display(), "generated new node key");
Ok(key)
}
pub fn iroh_secret(key: &SigningKey) -> SecretKey {
SecretKey::from(key.to_bytes())
}
fn load_key_from_file(p: &Path) -> Result<SigningKey> {
let content = fs::read_to_string(p)
.map_err(|e| anyhow!("read key {}: {e}", p.display()))?;
let hexstr = content.trim();
if hexstr.len() != 64 || !hexstr.chars().all(|c| c.is_ascii_hexdigit()) {
anyhow::bail!("key file {} is not valid 64-char hex", p.display());
}
let bytes = hex::decode(hexstr)?;
let mut arr = [0u8; 32];
arr.copy_from_slice(&bytes);
Ok(SigningKey::from_bytes(&arr))
}
fn generate_key() -> Result<SigningKey> {
let mut seed = [0u8; 32];
getrandom::fill(&mut seed)
.map_err(|e| anyhow!("generate key: {e}"))?;
Ok(SigningKey::from_bytes(&seed))
}