1use secp256k1::{Keypair, PublicKey, SecretKey, XOnlyPublicKey};
4use std::fmt;
5
6use super::auth::{AuthResponse, auth_challenge_digest};
7use super::encoding::{decode_secret, encode_npub};
8use super::{FipsAddress, IdentityError, NodeAddr, sha256};
9
10pub struct Identity {
15 keypair: Keypair,
16 node_addr: NodeAddr,
17 address: FipsAddress,
18}
19
20impl Identity {
21 pub fn generate() -> Self {
23 let mut secret_bytes = [0u8; 32];
24 rand::Rng::fill_bytes(&mut rand::rng(), &mut secret_bytes);
25 let secret_key =
26 SecretKey::from_slice(&secret_bytes).expect("32 random bytes is a valid secret key");
27 Self::from_secret_key(secret_key)
28 }
29
30 pub fn from_keypair(keypair: Keypair) -> Self {
32 let (pubkey, _parity) = keypair.x_only_public_key();
33 let node_addr = NodeAddr::from_pubkey(&pubkey);
34 let address = FipsAddress::from_node_addr(&node_addr);
35 Self {
36 keypair,
37 node_addr,
38 address,
39 }
40 }
41
42 pub fn from_secret_key(secret_key: SecretKey) -> Self {
44 let keypair = Keypair::from_secret_key(&super::SECP, &secret_key);
45 Self::from_keypair(keypair)
46 }
47
48 pub fn from_secret_bytes(bytes: &[u8; 32]) -> Result<Self, IdentityError> {
50 let secret_key = SecretKey::from_slice(bytes)?;
51 Ok(Self::from_secret_key(secret_key))
52 }
53
54 pub fn from_secret_str(s: &str) -> Result<Self, IdentityError> {
56 let secret_key = decode_secret(s)?;
57 Ok(Self::from_secret_key(secret_key))
58 }
59
60 pub fn keypair(&self) -> Keypair {
64 self.keypair
65 }
66
67 pub fn pubkey(&self) -> XOnlyPublicKey {
69 self.keypair.x_only_public_key().0
70 }
71
72 pub fn pubkey_full(&self) -> PublicKey {
74 self.keypair.public_key()
75 }
76
77 pub fn npub(&self) -> String {
79 encode_npub(&self.pubkey())
80 }
81
82 pub fn node_addr(&self) -> &NodeAddr {
84 &self.node_addr
85 }
86
87 pub fn address(&self) -> &FipsAddress {
89 &self.address
90 }
91
92 pub fn sign(&self, data: &[u8]) -> secp256k1::schnorr::Signature {
94 let digest = sha256(data);
95 super::SECP.sign_schnorr(&digest, &self.keypair)
96 }
97
98 pub fn sign_challenge(&self, challenge: &[u8; 32], timestamp: u64) -> AuthResponse {
102 let digest = auth_challenge_digest(challenge, timestamp);
103 let signature = super::SECP.sign_schnorr(&digest, &self.keypair);
104 AuthResponse {
105 pubkey: self.pubkey(),
106 timestamp,
107 signature,
108 }
109 }
110}
111
112impl fmt::Debug for Identity {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 f.debug_struct("Identity")
115 .field("node_addr", &self.node_addr)
116 .field("address", &self.address)
117 .finish_non_exhaustive()
118 }
119}