mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-10 08:37:02 +00:00
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
84 lines
2.2 KiB
Rust
84 lines
2.2 KiB
Rust
//! FIPS Identity System
|
|
//!
|
|
//! Node identity based on Nostr keypairs (secp256k1). The node_addr is derived
|
|
//! from the public key via SHA-256, and the FIPS address uses an IPv6-compatible
|
|
//! format with the 0xfd prefix.
|
|
|
|
mod address;
|
|
mod auth;
|
|
mod encoding;
|
|
mod local;
|
|
mod node_addr;
|
|
mod peer;
|
|
|
|
use sha2::{Digest, Sha256};
|
|
use thiserror::Error;
|
|
|
|
pub use address::FipsAddress;
|
|
pub use auth::{AuthChallenge, AuthResponse};
|
|
pub use encoding::{decode_npub, decode_nsec, decode_secret, encode_npub, encode_nsec};
|
|
pub use local::Identity;
|
|
pub use node_addr::NodeAddr;
|
|
pub use peer::PeerIdentity;
|
|
|
|
/// FIPS address prefix (IPv6 ULA range).
|
|
pub const FIPS_ADDRESS_PREFIX: u8 = 0xfd;
|
|
|
|
/// Errors that can occur in identity operations.
|
|
#[derive(Debug, Error)]
|
|
pub enum IdentityError {
|
|
#[error("invalid secret key: {0}")]
|
|
InvalidSecretKey(#[from] secp256k1::Error),
|
|
|
|
#[error("signature verification failed")]
|
|
SignatureVerificationFailed,
|
|
|
|
#[error("invalid node_addr length: expected 16, got {0}")]
|
|
InvalidNodeAddrLength(usize),
|
|
|
|
#[error("invalid address length: expected 16, got {0}")]
|
|
InvalidAddressLength(usize),
|
|
|
|
#[error("invalid address prefix: expected 0xfd, got 0x{0:02x}")]
|
|
InvalidAddressPrefix(u8),
|
|
|
|
#[error("bech32 encoding error: {0}")]
|
|
Bech32Encode(#[from] bech32::EncodeError),
|
|
|
|
#[error("bech32 decoding error: {0}")]
|
|
Bech32Decode(#[from] bech32::DecodeError),
|
|
|
|
#[error("invalid npub: expected 'npub' prefix, got '{0}'")]
|
|
InvalidNpubPrefix(String),
|
|
|
|
#[error("invalid npub: expected 32 bytes, got {0}")]
|
|
InvalidNpubLength(usize),
|
|
|
|
#[error("invalid nsec: expected 'nsec' prefix, got '{0}'")]
|
|
InvalidNsecPrefix(String),
|
|
|
|
#[error("invalid nsec: expected 32 bytes, got {0}")]
|
|
InvalidNsecLength(usize),
|
|
|
|
#[error("invalid hex encoding: {0}")]
|
|
InvalidHex(#[from] hex::FromHexError),
|
|
}
|
|
|
|
/// Compute SHA-256 hash of data.
|
|
fn sha256(data: &[u8]) -> [u8; 32] {
|
|
let mut hasher = Sha256::new();
|
|
hasher.update(data);
|
|
let result = hasher.finalize();
|
|
let mut hash = [0u8; 32];
|
|
hash.copy_from_slice(&result);
|
|
hash
|
|
}
|
|
|
|
/// Encode bytes as lowercase hex string.
|
|
fn hex_encode(bytes: &[u8]) -> String {
|
|
bytes.iter().map(|b| format!("{:02x}", b)).collect()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests;
|