From 18e8d2c8ea41ba10cb89d1f9b4137a27da4efbab Mon Sep 17 00:00:00 2001 From: John Poole Date: Thu, 12 Feb 2026 10:53:31 -0800 Subject: [PATCH] Compiles, needs some extra tweaking --- .gitignore | 3 ++ CMakeLists.txt | 68 +++++++++++++++++++++++++ tools/CMakeLists.txt | 1 + tools/keygen/CMakeLists.txt | 22 +++++++++ tools/keygen/main.cpp | 99 +++++++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 tools/CMakeLists.txt create mode 100644 tools/keygen/CMakeLists.txt create mode 100644 tools/keygen/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3e1732b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/build/ +/provisioning/ +/*.log diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..26fb0f4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,68 @@ +cmake_minimum_required(VERSION 3.16) +project(microReticulumTbeam LANGUAGES C CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# -------------------------------------------------------------------- +# Portability shims +# +# microReticulum's CMake currently links against "msgpackc-cxx" and "MsgPack" +# as if they were system libraries, which breaks on machines that don't have +# those exact libs installed. +# +# Define shim targets so CMake treats them as targets (no "-l..."). +# If/when you want a real msgpack-cxx dependency, replace the shim with +# FetchContent/find_package and link to that instead. +# -------------------------------------------------------------------- +if(NOT TARGET msgpackc-cxx) + add_library(msgpackc-cxx INTERFACE) +endif() + +if(NOT TARGET MsgPack) + add_library(MsgPack INTERFACE) +endif() + + +# Pull in the microReticulum submodule build +add_subdirectory(external/microReticulum) + +# Provide DebugLog.h for microReticulum's MsgPack dependency +#set(DEBUGLOG_DIR ${CMAKE_SOURCE_DIR}/external/DebugLog) + +#if(TARGET ReticulumShared) +# target_include_directories(ReticulumShared PUBLIC ${DEBUGLOG_DIR}) +#endif() + +#if(TARGET ReticulumStatic) +# target_include_directories(ReticulumStatic PUBLIC ${DEBUGLOG_DIR}) +#endif() + +set(DEBUGLOG_DIR ${CMAKE_SOURCE_DIR}/external/DebugLog) +set(ARX_TYPETRAITS_DIR ${CMAKE_SOURCE_DIR}/external/ArxTypeTraits) +set(ARX_CONTAINER_DIR ${CMAKE_SOURCE_DIR}/external/ArxContainer) + +if(TARGET ReticulumShared) + target_include_directories(ReticulumShared PUBLIC + ${DEBUGLOG_DIR} + ${ARX_TYPETRAITS_DIR} + ${ARX_CONTAINER_DIR} + ) +endif() + +if(TARGET ReticulumStatic) + target_include_directories(ReticulumStatic PUBLIC + ${DEBUGLOG_DIR} + ${ARX_TYPETRAITS_DIR} + ${ARX_CONTAINER_DIR} + ) +endif() + +# We only need the static library for host-side tooling. +# The shared lib target requires system msgpack libs on some systems. +if(TARGET ReticulumShared) + set_target_properties(ReticulumShared PROPERTIES EXCLUDE_FROM_ALL YES) +endif() + +# Build our host-side tools +add_subdirectory(tools) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..a4af285 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(keygen) diff --git a/tools/keygen/CMakeLists.txt b/tools/keygen/CMakeLists.txt new file mode 100644 index 0000000..b513a15 --- /dev/null +++ b/tools/keygen/CMakeLists.txt @@ -0,0 +1,22 @@ +add_executable(rns-provision main.cpp) + +# If microReticulum exports an include directory / target, this may be unnecessary. +# Keep this here as a pragmatic fallback: +target_include_directories(rns-provision PRIVATE + ${CMAKE_SOURCE_DIR}/external/microReticulum/src +) + +# ArduinoJson is pulled by microReticulum headers; add it to this tool's include path. +target_include_directories(rns-provision PRIVATE + ${CMAKE_SOURCE_DIR}/external/microReticulum/src + + # ArduinoJson headers: + # - ArduinoJson.h lives at the repo root + # - ArduinoJson/... lives under src/ + ${CMAKE_BINARY_DIR}/_deps/arduinojson-src + ${CMAKE_BINARY_DIR}/_deps/arduinojson-src/src +) + +# Link against the microReticulum library target. +# If this target name is wrong in your submodule, change it here. +target_link_libraries(rns-provision PRIVATE ReticulumStatic) diff --git a/tools/keygen/main.cpp b/tools/keygen/main.cpp new file mode 100644 index 0000000..d593f2d --- /dev/null +++ b/tools/keygen/main.cpp @@ -0,0 +1,99 @@ +// keygen - generate microReticulum identity keypairs +// +// Example: +// ./keygen --quantity 6 --format tsv +// ./keygen -q 6 -f json +// +// $Header$ +// $Id$ + +#include +#include +#include +#include +#include + +static void usage(const char* argv0) { + std::cerr + << "Usage: " << argv0 << " --quantity N [--format tsv|json] [--public]\n" + << " -q, --quantity Number of identities to generate (required)\n" + << " -f, --format Output format: tsv (default) or json\n" + << " --public Also include public_key in output\n"; +} + +static bool is_flag(const std::string& a, const char* s) { return a == s; } + +int main(int argc, char** argv) { + try { + int quantity = -1; + std::string format = "tsv"; + bool include_public = false; + + for (int i = 1; i < argc; i++) { + std::string a(argv[i]); + + if (is_flag(a, "-h") || is_flag(a, "--help")) { + usage(argv[0]); + return 0; + } else if (is_flag(a, "-q") || is_flag(a, "--quantity")) { + if (i + 1 >= argc) throw std::runtime_error("Missing value for --quantity"); + quantity = std::stoi(argv[++i]); + } else if (is_flag(a, "-f") || is_flag(a, "--format")) { + if (i + 1 >= argc) throw std::runtime_error("Missing value for --format"); + format = argv[++i]; + } else if (is_flag(a, "--public")) { + include_public = true; + } else { + throw std::runtime_error("Unknown argument: " + a); + } + } + + if (quantity <= 0) { + usage(argv[0]); + return 2; + } + if (!(format == "tsv" || format == "json")) { + throw std::runtime_error("Invalid --format (must be tsv or json)"); + } + + if (format == "tsv") { + // header row + std::cout << "n\tid_hex\tprivate_key_hex"; + if (include_public) std::cout << "\tpublic_key_hex"; + std::cout << "\n"; + + for (int n = 1; n <= quantity; n++) { + RNS::Identity id(true); + std::cout + << n << "\t" + << id.hash().toHex() << "\t" + << id.get_private_key().toHex(); + if (include_public) std::cout << "\t" << id.get_public_key().toHex(); + std::cout << "\n"; + } + } else { + // json + std::cout << "[\n"; + for (int n = 1; n <= quantity; n++) { + RNS::Identity id(true); + + std::cout << " {\n"; + std::cout << " \"n\": " << n << ",\n"; + std::cout << " \"id\": \"" << id.hash().toHex() << "\",\n"; + std::cout << " \"private_key\": \"" << id.get_private_key().toHex() << "\""; + if (include_public) { + std::cout << ",\n \"public_key\": \"" << id.get_public_key().toHex() << "\"\n"; + } else { + std::cout << "\n"; + } + std::cout << " }" << (n == quantity ? "\n" : ",\n"); + } + std::cout << "]\n"; + } + + return 0; + } catch (const std::exception& e) { + std::cerr << "Error: " << e.what() << "\n"; + return 1; + } +}