fips_identity/
encoding.rs1use bech32::{Bech32, Hrp};
4use secp256k1::{SecretKey, XOnlyPublicKey};
5
6use super::IdentityError;
7
8const NPUB_HRP: Hrp = Hrp::parse_unchecked("npub");
10
11const NSEC_HRP: Hrp = Hrp::parse_unchecked("nsec");
13
14pub fn encode_npub(pubkey: &XOnlyPublicKey) -> String {
16 bech32::encode::<Bech32>(NPUB_HRP, &pubkey.serialize()).expect("npub encoding cannot fail")
17}
18
19pub fn decode_npub(npub: &str) -> Result<XOnlyPublicKey, IdentityError> {
21 let (hrp, data) = bech32::decode(npub)?;
22
23 if hrp != NPUB_HRP {
24 return Err(IdentityError::InvalidNpubPrefix(hrp.to_string()));
25 }
26
27 if data.len() != 32 {
28 return Err(IdentityError::InvalidNpubLength(data.len()));
29 }
30
31 let pubkey = XOnlyPublicKey::from_slice(&data)?;
32 Ok(pubkey)
33}
34
35pub fn encode_nsec(secret_key: &SecretKey) -> String {
37 bech32::encode::<Bech32>(NSEC_HRP, &secret_key.secret_bytes())
38 .expect("nsec encoding cannot fail")
39}
40
41pub fn decode_nsec(nsec: &str) -> Result<SecretKey, IdentityError> {
43 let (hrp, data) = bech32::decode(nsec)?;
44
45 if hrp != NSEC_HRP {
46 return Err(IdentityError::InvalidNsecPrefix(hrp.to_string()));
47 }
48
49 if data.len() != 32 {
50 return Err(IdentityError::InvalidNsecLength(data.len()));
51 }
52
53 let secret_key = SecretKey::from_slice(&data)?;
54 Ok(secret_key)
55}
56
57pub fn decode_secret(s: &str) -> Result<SecretKey, IdentityError> {
59 if s.starts_with("nsec1") {
60 decode_nsec(s)
61 } else {
62 let bytes = hex::decode(s)?;
63 if bytes.len() != 32 {
64 return Err(IdentityError::InvalidNsecLength(bytes.len()));
65 }
66 let secret_key = SecretKey::from_slice(&bytes)?;
67 Ok(secret_key)
68 }
69}