Skip to main content

fips_identity/
lib.rs

1//! FIPS Identity System
2//!
3//! Node identity based on Nostr keypairs (secp256k1). The node_addr is derived
4//! from the public key via SHA-256, and the FIPS address uses an IPv6-compatible
5//! format with the 0xfd prefix.
6
7mod address;
8mod auth;
9mod encoding;
10mod local;
11mod node_addr;
12mod peer;
13
14use sha2::{Digest, Sha256};
15use thiserror::Error;
16
17pub use address::FipsAddress;
18pub use auth::{AuthChallenge, AuthResponse};
19pub use encoding::{decode_npub, decode_nsec, decode_secret, encode_npub, encode_nsec};
20pub use local::Identity;
21pub use node_addr::NodeAddr;
22pub use peer::PeerIdentity;
23
24/// FIPS address prefix (IPv6 ULA range).
25pub const FIPS_ADDRESS_PREFIX: u8 = 0xfd;
26
27/// Errors that can occur in identity operations.
28#[derive(Debug, Error)]
29pub enum IdentityError {
30    #[error("invalid secret key: {0}")]
31    InvalidSecretKey(#[from] secp256k1::Error),
32
33    #[error("signature verification failed")]
34    SignatureVerificationFailed,
35
36    #[error("invalid node_addr length: expected 16, got {0}")]
37    InvalidNodeAddrLength(usize),
38
39    #[error("invalid address length: expected 16, got {0}")]
40    InvalidAddressLength(usize),
41
42    #[error("invalid address prefix: expected 0xfd, got 0x{0:02x}")]
43    InvalidAddressPrefix(u8),
44
45    #[error("bech32 encoding error: {0}")]
46    Bech32Encode(#[from] bech32::EncodeError),
47
48    #[error("bech32 decoding error: {0}")]
49    Bech32Decode(#[from] bech32::DecodeError),
50
51    #[error("invalid npub: expected 'npub' prefix, got '{0}'")]
52    InvalidNpubPrefix(String),
53
54    #[error("invalid npub: expected 32 bytes, got {0}")]
55    InvalidNpubLength(usize),
56
57    #[error("invalid nsec: expected 'nsec' prefix, got '{0}'")]
58    InvalidNsecPrefix(String),
59
60    #[error("invalid nsec: expected 32 bytes, got {0}")]
61    InvalidNsecLength(usize),
62
63    #[error("invalid hex encoding: {0}")]
64    InvalidHex(#[from] hex::FromHexError),
65}
66
67/// Compute SHA-256 hash of data.
68fn sha256(data: &[u8]) -> [u8; 32] {
69    let mut hasher = Sha256::new();
70    hasher.update(data);
71    let result = hasher.finalize();
72    let mut hash = [0u8; 32];
73    hash.copy_from_slice(&result);
74    hash
75}
76
77/// Encode bytes as lowercase hex string.
78fn hex_encode(bytes: &[u8]) -> String {
79    bytes.iter().map(|b| format!("{:02x}", b)).collect()
80}
81
82#[cfg(test)]
83mod tests;