huskies: merge 728_story_cryptographic_peer_handshake_with_trusted_keys_gating

This commit is contained in:
dave
2026-04-27 19:17:05 +00:00
parent ded8c6fd66
commit aa7b26a24a
6 changed files with 640 additions and 139 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ mod write;
pub use ops::{all_ops_json, apply_remote_op, ops_since, our_vector_clock, subscribe_ops};
pub use presence::{
is_claimed_by_us, our_node_id, read_all_node_presence, release_claim, sign_challenge,
write_claim, write_node_presence,
sign_versioned_challenge, write_claim, write_node_presence,
};
pub use read::{
CrdtItemDump, CrdtStateDump, check_archived_deps_crdt, check_unmet_deps_crdt,
+16
View File
@@ -34,6 +34,22 @@ pub fn sign_challenge(challenge: &str) -> Option<(String, String)> {
Some((pubkey_hex, sig_hex))
}
/// Sign a versioned challenge `"huskies-v1:{nonce}"` for the extended WebSocket
/// mutual-auth handshake (responding node side).
///
/// The signature covers the full versioned string (not just the nonce), so an
/// attacker cannot replay a signature from a previous handshake or a different
/// protocol version.
///
/// Returns `(pubkey_hex, signature_hex)` or `None` before `init()`.
pub fn sign_versioned_challenge(nonce: &str) -> Option<(String, String)> {
let state = get_crdt()?.lock().ok()?;
let pubkey_hex = crate::node_identity::public_key_hex(&state.keypair);
let versioned = format!("huskies-v1:{nonce}");
let sig_hex = crate::node_identity::sign_challenge(&state.keypair, &versioned);
Some((pubkey_hex, sig_hex))
}
/// Write a claim on a pipeline item via CRDT.
///
/// Sets `claimed_by` to this node's ID and `claimed_at` to the current time.