|
|
@@ -3,13 +3,19 @@
|
|
|
//! Persisted v3 onion key: load-or-create at
|
|
|
//! `<data-dir>/onion.key`, same 0600 file / 0700 parent discipline as the
|
|
|
//! daemon's `net.key` handling (audit R1 F-02, mirroring `net.rs
|
|
|
-//! load_or_create_key` and `perms.rs`). The file is hex(seed || pub) — a
|
|
|
-//! 64-byte blob accepted verbatim by `ADD_ONION ED25519-V3:`, minting the
|
|
|
-//! standard address of the seed's public key (verified live against tor
|
|
|
-//! 0.4.9.13, see tests/live_tor.rs; tor's own PrivateKey EXPORT blob is
|
|
|
-//! laid out differently, but import semantics are deterministic).
|
|
|
+//! load_or_create_key` and `perms.rs`). The file is hex of 64 bytes, handed
|
|
|
+//! verbatim to `ADD_ONION ED25519-V3:`.
|
|
|
//!
|
|
|
-//! The keypair public half is derived at creation with ed25519-dalek (the
|
|
|
+//! Tor reads ONLY `key[0..32]`: verbatim as the ed25519 secret scalar (no
|
|
|
+//! hashing, no clamping) and derives the service id from `key[0..32]*B`.
|
|
|
+//! `key[32..64]` is never read — it is ed25519-dalek's public key of the
|
|
|
+//! random seed, kept as material, and is NOT the address's public key.
|
|
|
+//! Verified against tor 0.4.9.13 on 2026-10-29 by re-deriving a live
|
|
|
+//! bootnode id from its persisted file; tor's own PrivateKey EXPORT is laid
|
|
|
+//! out differently again, so these blobs are not symmetric — the first 32
|
|
|
+//! bytes alone decide the address (and are what a backup must preserve).
|
|
|
+//!
|
|
|
+//! The stored public half is derived at creation with ed25519-dalek (the
|
|
|
//! only vendored curve implementation; already locked via libp2p identity).
|
|
|
//! getrandom 0.2 seeds it.
|
|
|
|
|
|
@@ -107,7 +113,7 @@ pub fn load_or_create_onion_key(path: &std::path::Path) -> Result<OnionKey, TorE
|
|
|
let key: [u8; 64] = bytes.try_into().map_err(|v: Vec<u8>| {
|
|
|
invalid(
|
|
|
path,
|
|
|
- format!("onion key must be 64 bytes (seed || pub), got {}", v.len()),
|
|
|
+ format!("onion key must be 64 bytes (scalar + pub), got {}", v.len()),
|
|
|
)
|
|
|
})?;
|
|
|
moos_log::mlog_info!("tor", "onion key loaded path={}", path.display());
|