From 3e6565b2a9182f68dc8f620eadfece079f08ff7d Mon Sep 17 00:00:00 2001 From: Lee Smet Date: Fri, 19 Sep 2025 13:08:02 +0200 Subject: [PATCH] Close #664: Add subcommand to generate keys Signed-off-by: Lee Smet --- CHANGELOG.md | 2 ++ myceliumd-private/src/main.rs | 19 +++++++++++++++++++ myceliumd/src/main.rs | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e88d7d..6809911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 always disabled. - Added auto discovery of Socks5 proxies on the overlay, and the ability to proxy local Socks5 connections to a chosen (manual or automatic) remote. +- New `generate-keys` subcommand which generates the key file without running a + daemon. It can also be used to generate fresh keys, should that be needed. ### Changed diff --git a/myceliumd-private/src/main.rs b/myceliumd-private/src/main.rs index 716e2fa..e819d7d 100644 --- a/myceliumd-private/src/main.rs +++ b/myceliumd-private/src/main.rs @@ -126,6 +126,14 @@ pub enum Command { key: Option, }, + /// Generate a set of new keys for the system at the default path, or the path provided by the + /// --key-file parameter + GenerateKeys { + /// Force generating new keys, removing any existing key in the process + #[arg(long = "force")] + force: bool, + }, + /// Actions on the message subsystem Message { #[command(subcommand)] @@ -697,6 +705,16 @@ async fn main() -> Result<(), Box> { return Ok(()); } + Command::GenerateKeys { force } => { + let node_keys = get_node_keys(&key_path).await?; + if node_keys.is_none() || force { + info!(?key_path, "Generating new node keys"); + let secret_key = crypto::SecretKey::new(); + save_key_file(&secret_key, &key_path).await?; + } else { + warn!(?key_path, "Refusing to generate new keys as key file already exists, use `--force` to generate them anyway"); + } + } Command::Message { command } => match command { MessageCommand::Send { wait, @@ -829,6 +847,7 @@ where Ok(T::from(secret_bytes)) } +/// Save a key to a file at the given path. If the file already exists, it will be overwritten. async fn save_key_file(key: &crypto::SecretKey, path: &Path) -> io::Result<()> { #[cfg(target_family = "unix")] { diff --git a/myceliumd/src/main.rs b/myceliumd/src/main.rs index cadea1b..0cc8807 100644 --- a/myceliumd/src/main.rs +++ b/myceliumd/src/main.rs @@ -126,6 +126,14 @@ pub enum Command { key: Option, }, + /// Generate a set of new keys for the system at the default path, or the path provided by the + /// --key-file parameter + GenerateKeys { + /// Force generating new keys, removing any existing key in the process + #[arg(long = "force")] + force: bool, + }, + /// Actions on the message subsystem Message { #[command(subcommand)] @@ -664,6 +672,16 @@ async fn main() -> Result<(), Box> { return Ok(()); } + Command::GenerateKeys { force } => { + let node_keys = get_node_keys(&key_path).await?; + if node_keys.is_none() || force { + info!(?key_path, "Generating new node keys"); + let secret_key = crypto::SecretKey::new(); + save_key_file(&secret_key, &key_path).await?; + } else { + warn!(?key_path, "Refusing to generate new keys as key file already exists, use `--force` to generate them anyway"); + } + } Command::Message { command } => match command { MessageCommand::Send { wait, @@ -796,6 +814,7 @@ where Ok(T::from(secret_bytes)) } +/// Save a key to a file at the given path. If the file already exists, it will be overwritten. async fn save_key_file(key: &crypto::SecretKey, path: &Path) -> io::Result<()> { #[cfg(target_family = "unix")] {