keypair.rs (8149B)
1 use nostr::nips::nip19::FromBech32; 2 use nostr::nips::nip19::ToBech32; 3 use nostr::nips::nip49::EncryptedSecretKey; 4 use serde::Deserialize; 5 use serde::Serialize; 6 use tokenator::ParseError; 7 use tokenator::TokenParser; 8 use tokenator::TokenSerializable; 9 10 use crate::Pubkey; 11 use crate::SecretKey; 12 13 #[derive(Debug, Eq, PartialEq, Clone)] 14 pub struct Keypair { 15 pub pubkey: Pubkey, 16 pub secret_key: Option<SecretKey>, 17 } 18 19 pub struct KeypairUnowned<'a> { 20 pub pubkey: &'a Pubkey, 21 pub secret_key: Option<&'a SecretKey>, 22 } 23 24 impl<'a> From<&'a Keypair> for KeypairUnowned<'a> { 25 fn from(value: &'a Keypair) -> Self { 26 Self { 27 pubkey: &value.pubkey, 28 secret_key: value.secret_key.as_ref(), 29 } 30 } 31 } 32 33 impl Keypair { 34 pub fn from_secret(secret_key: SecretKey) -> Self { 35 let cloned_secret_key = secret_key.clone(); 36 let nostr_keys = nostr::Keys::new(secret_key); 37 Keypair { 38 pubkey: Pubkey::new(nostr_keys.public_key().to_bytes()), 39 secret_key: Some(cloned_secret_key), 40 } 41 } 42 43 pub fn new(pubkey: Pubkey, secret_key: Option<SecretKey>) -> Self { 44 Keypair { pubkey, secret_key } 45 } 46 47 pub fn only_pubkey(pubkey: Pubkey) -> Self { 48 Keypair { 49 pubkey, 50 secret_key: None, 51 } 52 } 53 54 pub fn to_full(&self) -> Option<FilledKeypair<'_>> { 55 self.secret_key.as_ref().map(|secret_key| FilledKeypair { 56 pubkey: &self.pubkey, 57 secret_key, 58 }) 59 } 60 } 61 62 #[derive(Debug, Eq, PartialEq, Clone)] 63 pub struct FullKeypair { 64 pub pubkey: Pubkey, 65 pub secret_key: SecretKey, 66 } 67 68 #[derive(Debug, Eq, PartialEq, Clone, Copy)] 69 pub struct FilledKeypair<'a> { 70 pub pubkey: &'a Pubkey, 71 pub secret_key: &'a SecretKey, 72 } 73 74 impl<'a> FilledKeypair<'a> { 75 pub fn new(pubkey: &'a Pubkey, secret_key: &'a SecretKey) -> Self { 76 FilledKeypair { pubkey, secret_key } 77 } 78 79 pub fn to_full(&self) -> FullKeypair { 80 FullKeypair { 81 pubkey: self.pubkey.to_owned(), 82 secret_key: self.secret_key.to_owned(), 83 } 84 } 85 } 86 87 impl<'a> From<&'a FilledKeypair<'a>> for KeypairUnowned<'a> { 88 fn from(value: &'a FilledKeypair<'a>) -> Self { 89 Self { 90 pubkey: value.pubkey, 91 secret_key: Some(value.secret_key), 92 } 93 } 94 } 95 96 impl FullKeypair { 97 pub fn new(pubkey: Pubkey, secret_key: SecretKey) -> Self { 98 FullKeypair { pubkey, secret_key } 99 } 100 101 pub fn to_filled(&self) -> FilledKeypair<'_> { 102 FilledKeypair::new(&self.pubkey, &self.secret_key) 103 } 104 105 pub fn generate() -> Self { 106 let mut rng = nostr::secp256k1::rand::rngs::OsRng; 107 let (secret_key, _) = &nostr::SECP256K1.generate_keypair(&mut rng); 108 let (xopk, _) = secret_key.x_only_public_key(&nostr::SECP256K1); 109 let secret_key = nostr::SecretKey::from(*secret_key); 110 FullKeypair { 111 pubkey: Pubkey::new(xopk.serialize()), 112 secret_key, 113 } 114 } 115 116 pub fn to_keypair(self) -> Keypair { 117 Keypair { 118 pubkey: self.pubkey, 119 secret_key: Some(self.secret_key), 120 } 121 } 122 } 123 124 impl std::fmt::Display for Keypair { 125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 126 write!( 127 f, 128 "Keypair:\n\tpublic: {}\n\tsecret: {}", 129 self.pubkey, 130 match self.secret_key { 131 Some(_) => "Some(<hidden>)", 132 None => "None", 133 } 134 ) 135 } 136 } 137 138 impl std::fmt::Display for FullKeypair { 139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 140 write!(f, "Keypair:\n\tpublic: {}\n\tsecret: <hidden>", self.pubkey) 141 } 142 } 143 144 #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] 145 pub struct SerializableKeypair { 146 pub pubkey: Pubkey, 147 pub encrypted_secret_key: Option<EncryptedSecretKey>, 148 } 149 150 impl SerializableKeypair { 151 pub fn from_keypair(kp: &Keypair, pass: &str, log_n: u8) -> Self { 152 Self { 153 pubkey: kp.pubkey, 154 encrypted_secret_key: kp.secret_key.clone().and_then(|s| { 155 EncryptedSecretKey::new(&s, pass, log_n, nostr::nips::nip49::KeySecurity::Weak).ok() 156 }), 157 } 158 } 159 160 pub fn to_keypair(&self, pass: &str) -> Keypair { 161 Keypair::new( 162 self.pubkey, 163 self.encrypted_secret_key 164 .and_then(|e| e.to_secret_key(pass).ok()), 165 ) 166 } 167 } 168 169 impl TokenSerializable for Pubkey { 170 fn parse_from_tokens<'a>(parser: &mut TokenParser<'a>) -> Result<Self, ParseError<'a>> { 171 parser.parse_token(PUBKEY_TOKEN)?; 172 let raw = parser.pull_token()?; 173 let pubkey = 174 Pubkey::try_from_bech32_string(raw, true).map_err(|_| ParseError::DecodeFailed)?; 175 Ok(pubkey) 176 } 177 178 fn serialize_tokens(&self, writer: &mut tokenator::TokenWriter) { 179 writer.write_token(PUBKEY_TOKEN); 180 181 let Some(bech) = self.npub() else { 182 tracing::error!("Could not convert pubkey to bech: {}", self.hex()); 183 return; 184 }; 185 186 writer.write_token(&bech); 187 } 188 } 189 190 impl TokenSerializable for Keypair { 191 fn parse_from_tokens<'a>(parser: &mut TokenParser<'a>) -> Result<Self, ParseError<'a>> { 192 TokenParser::alt( 193 parser, 194 &[ 195 |p| Ok(Keypair::only_pubkey(Pubkey::parse_from_tokens(p)?)), 196 |p| Ok(Keypair::from_secret(parse_seckey(p)?)), 197 ], 198 ) 199 } 200 201 fn serialize_tokens(&self, writer: &mut tokenator::TokenWriter) { 202 if let Some(seckey) = &self.secret_key { 203 writer.write_token(ESECKEY_TOKEN); 204 let maybe_eseckey = EncryptedSecretKey::new( 205 seckey, 206 ESECKEY_PASS, 207 7, 208 nostr::nips::nip49::KeySecurity::Unknown, 209 ); 210 211 let Ok(eseckey) = maybe_eseckey else { 212 tracing::error!("Could not convert seckey to EncryptedSecretKey"); 213 return; 214 }; 215 let Ok(serialized) = eseckey.to_bech32() else { 216 tracing::error!("Could not serialize ncryptsec"); 217 return; 218 }; 219 220 writer.write_token(&serialized); 221 } else { 222 self.pubkey.serialize_tokens(writer); 223 } 224 } 225 } 226 227 const ESECKEY_TOKEN: &str = "eseckey"; 228 const ESECKEY_PASS: &str = "notedeck"; 229 const PUBKEY_TOKEN: &str = "pubkey"; 230 231 fn parse_seckey<'a>(parser: &mut TokenParser<'a>) -> Result<SecretKey, ParseError<'a>> { 232 parser.parse_token(ESECKEY_TOKEN)?; 233 234 let raw = parser.pull_token()?; 235 236 let eseckey = EncryptedSecretKey::from_bech32(raw).map_err(|_| ParseError::DecodeFailed)?; 237 238 let seckey = eseckey 239 .to_secret_key(ESECKEY_PASS) 240 .map_err(|_| ParseError::DecodeFailed)?; 241 242 Ok(seckey) 243 } 244 245 #[cfg(test)] 246 mod tests { 247 248 use tokenator::{TokenParser, TokenSerializable, TokenWriter}; 249 250 use super::{FullKeypair, Keypair}; 251 252 #[test] 253 fn test_token_eseckey_serialize_deserialize() { 254 let kp = FullKeypair::generate(); 255 256 let mut writer = TokenWriter::new("\t"); 257 kp.clone().to_keypair().serialize_tokens(&mut writer); 258 259 let serialized = writer.str(); 260 261 let data = &serialized.split("\t").collect::<Vec<&str>>(); 262 263 let mut parser = TokenParser::new(data); 264 let m_new_kp = Keypair::parse_from_tokens(&mut parser); 265 assert!(m_new_kp.is_ok()); 266 267 let new_kp = m_new_kp.unwrap(); 268 269 assert_eq!(kp, new_kp.to_full().unwrap().to_full()); 270 } 271 272 #[test] 273 fn test_token_pubkey_serialize_deserialize() { 274 let kp = Keypair::only_pubkey(FullKeypair::generate().pubkey); 275 276 let mut writer = TokenWriter::new("\t"); 277 kp.clone().serialize_tokens(&mut writer); 278 279 let serialized = writer.str(); 280 281 let data = &serialized.split("\t").collect::<Vec<&str>>(); 282 283 let mut parser = TokenParser::new(data); 284 let m_new_kp = Keypair::parse_from_tokens(&mut parser); 285 assert!(m_new_kp.is_ok()); 286 287 let new_kp = m_new_kp.unwrap(); 288 289 assert_eq!(kp, new_kp); 290 } 291 }