mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Module reorganization, identity test coverage, design doc corrections
Module reorganization: - Split identity.rs (930 lines) into identity/ directory module: mod.rs, node_addr.rs, address.rs, peer.rs, local.rs, auth.rs, encoding.rs, tests.rs — following established bloom/, tree/, noise/ pattern - Group TUN, DNS, and ICMPv6 into upper/ module as the IPv6 adaptation layer: move tun.rs, icmp.rs, node/dns.rs into upper/ Identity test coverage (28 new tests, 52 total): - Encoding error paths: invalid npub/nsec length, bad hex input - NodeAddr: Debug, Display, as_slice, AsRef, Hash - FipsAddress: from_slice, From trait, Debug, Display, Eq+Hash - PeerIdentity: from_pubkey_full, pubkey_full parity paths, Debug - Identity: keypair, pubkey_full, Debug - AuthChallenge: from_bytes Design doc corrections (fips-software-architecture.md): - Identity struct: npub+nsec fields → keypair: Keypair with accessors - Node struct: TunInterface → TunState, Transport → TransportHandle, Peer → PeerSlot - Peer section: monolithic Peer → two-phase PeerSlot (PeerConnection + ActivePeer) with HandshakeState/ConnectivityState - ActivePeer: npub → identity: PeerIdentity, ancestry Vec → Option, declaration/inbound_filter wrapped in Option - BloomState: add 4 missing fields, fix update_debounce type - DiscoveredPeer: field name and type corrections
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
//! 16-byte node identifier derived from truncated SHA-256(pubkey).
|
||||
|
||||
use secp256k1::XOnlyPublicKey;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::fmt;
|
||||
|
||||
use super::{hex_encode, IdentityError};
|
||||
|
||||
/// 16-byte node identifier derived from truncated SHA-256(pubkey).
|
||||
///
|
||||
/// The node_addr is the first 16 bytes of SHA-256(pubkey), providing 128 bits
|
||||
/// of collision resistance. Hashing the public key prevents grinding attacks
|
||||
/// that exploit secp256k1's algebraic structure.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct NodeAddr([u8; 16]);
|
||||
|
||||
impl NodeAddr {
|
||||
/// Create a NodeAddr from a 16-byte array.
|
||||
pub fn from_bytes(bytes: [u8; 16]) -> Self {
|
||||
Self(bytes)
|
||||
}
|
||||
|
||||
/// Create a NodeAddr from a slice.
|
||||
pub fn from_slice(slice: &[u8]) -> Result<Self, IdentityError> {
|
||||
if slice.len() != 16 {
|
||||
return Err(IdentityError::InvalidNodeAddrLength(slice.len()));
|
||||
}
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes.copy_from_slice(slice);
|
||||
Ok(Self(bytes))
|
||||
}
|
||||
|
||||
/// Derive a NodeAddr from an x-only public key (npub).
|
||||
///
|
||||
/// Computes SHA-256(pubkey) and takes the first 16 bytes.
|
||||
pub fn from_pubkey(pubkey: &XOnlyPublicKey) -> Self {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(pubkey.serialize());
|
||||
let hash = hasher.finalize();
|
||||
let mut bytes = [0u8; 16];
|
||||
bytes.copy_from_slice(&hash[..16]);
|
||||
Self(bytes)
|
||||
}
|
||||
|
||||
/// Return the raw bytes.
|
||||
pub fn as_bytes(&self) -> &[u8; 16] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Return the bytes as a slice.
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for NodeAddr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "NodeAddr({})", hex_encode(&self.0[..8]))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for NodeAddr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", hex_encode(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for NodeAddr {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user