Skip to content

Commit e04c882

Browse files
kernelkindjb55
authored andcommitted
Add keypair & update pubkey
Keypair & FullKeypair match structs in damus ios Signed-off-by: kernelkind <[email protected]> Signed-off-by: William Casarin <[email protected]>
1 parent b817745 commit e04c882

File tree

4 files changed

+119
-2
lines changed

4 files changed

+119
-2
lines changed

enostr/src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ pub enum Error {
88
Empty,
99
DecodeFailed,
1010
HexDecodeFailed,
11+
InvalidBech32,
1112
InvalidByteSize,
1213
InvalidSignature,
14+
InvalidPublicKey,
1315
// Secp(secp256k1::Error),
1416
Json(serde_json::Error),
1517
Generic(String),
@@ -23,6 +25,7 @@ impl std::cmp::PartialEq for Error {
2325
(Error::HexDecodeFailed, Error::HexDecodeFailed) => true,
2426
(Error::InvalidSignature, Error::InvalidSignature) => true,
2527
(Error::InvalidByteSize, Error::InvalidByteSize) => true,
28+
(Error::InvalidPublicKey, Error::InvalidPublicKey) => true,
2629
// This is slightly wrong but whatevs
2730
(Error::Json(..), Error::Json(..)) => true,
2831
(Error::Generic(left), Error::Generic(right)) => left == right,
@@ -40,6 +43,8 @@ impl fmt::Display for Error {
4043
Self::InvalidSignature => write!(f, "invalid signature"),
4144
Self::HexDecodeFailed => write!(f, "hex decoding failed"),
4245
Self::InvalidByteSize => write!(f, "invalid byte size"),
46+
Self::InvalidBech32 => write!(f, "invalid bech32 string"),
47+
Self::InvalidPublicKey => write!(f, "invalid public key"),
4348
//Self::Secp(e) => write!(f, "{e}"),
4449
Self::Json(e) => write!(f, "{e}"),
4550
Self::Generic(e) => write!(f, "{e}"),

enostr/src/keypair.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::Pubkey;
2+
use crate::SecretKey;
3+
4+
#[derive(Debug, Eq, PartialEq)]
5+
pub struct Keypair {
6+
pub pubkey: Pubkey,
7+
pub secret_key: Option<SecretKey>,
8+
}
9+
10+
impl Keypair {
11+
pub fn new(secret_key: SecretKey) -> Self {
12+
let cloned_secret_key = secret_key.clone();
13+
let nostr_keys = nostr::Keys::new(secret_key);
14+
Keypair {
15+
pubkey: Pubkey::new(&nostr_keys.public_key().to_bytes()),
16+
secret_key: Some(cloned_secret_key),
17+
}
18+
}
19+
20+
pub fn only_pubkey(pubkey: Pubkey) -> Self {
21+
Keypair {
22+
pubkey,
23+
secret_key: None,
24+
}
25+
}
26+
27+
pub fn to_full(self) -> Option<FullKeypair> {
28+
if let Some(secret_key) = self.secret_key {
29+
Some(FullKeypair {
30+
pubkey: self.pubkey,
31+
secret_key,
32+
})
33+
} else {
34+
None
35+
}
36+
}
37+
}
38+
39+
#[derive(Debug, Eq, PartialEq)]
40+
pub struct FullKeypair {
41+
pub pubkey: Pubkey,
42+
pub secret_key: SecretKey,
43+
}
44+
45+
impl FullKeypair {
46+
pub fn new(pubkey: Pubkey, secret_key: SecretKey) -> Self {
47+
FullKeypair { pubkey, secret_key }
48+
}
49+
}
50+
51+
impl std::fmt::Display for Keypair {
52+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53+
write!(
54+
f,
55+
"Keypair:\n\tpublic: {}\n\tsecret: {}",
56+
self.pubkey,
57+
match self.secret_key {
58+
Some(_) => "Some(<hidden>)",
59+
None => "None",
60+
}
61+
)
62+
}
63+
}
64+
65+
impl std::fmt::Display for FullKeypair {
66+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67+
write!(
68+
f,
69+
"Keypair:\n\tpublic: {}\n\tsecret: {}",
70+
self.pubkey, "<hidden>"
71+
)
72+
}
73+
}

enostr/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod client;
22
mod error;
33
mod event;
44
mod filter;
5+
mod keypair;
56
mod profile;
67
mod pubkey;
78
mod relay;
@@ -11,6 +12,8 @@ pub use error::Error;
1112
pub use event::{Event, EventId};
1213
pub use ewebsock;
1314
pub use filter::Filter;
15+
pub use keypair::{FullKeypair, Keypair};
16+
pub use nostr::SecretKey;
1417
pub use profile::Profile;
1518
pub use pubkey::Pubkey;
1619
pub use relay::message::{RelayEvent, RelayMessage};

enostr/src/pubkey.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use serde::{Deserialize, Deserializer, Serialize, Serializer};
22

33
use crate::Error;
4-
use hex;
54
use log::debug;
6-
//use nostr::key::XOnlyPublicKey;
5+
use nostr::bech32::Hrp;
76
use std::fmt;
87

98
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
109
pub struct Pubkey([u8; 32]);
1110

11+
static HRP_NPUB: Hrp = Hrp::parse_unchecked("npub");
12+
1213
impl Pubkey {
1314
pub fn new(data: &[u8; 32]) -> Self {
1415
Self(*data)
@@ -25,6 +26,41 @@ impl Pubkey {
2526
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
2627
Ok(Pubkey(hex::decode(hex_str)?.as_slice().try_into()?))
2728
}
29+
30+
pub fn try_from_hex_str_with_verify(hex_str: &str) -> Result<Self, Error> {
31+
let vec: Vec<u8> = hex::decode(hex_str)?;
32+
if vec.len() != 32 {
33+
Err(Error::HexDecodeFailed)
34+
} else {
35+
let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&vec) {
36+
Ok(r) => Ok(r),
37+
Err(_) => Err(Error::InvalidPublicKey),
38+
}?;
39+
40+
Ok(Pubkey(vec.try_into().unwrap()))
41+
}
42+
}
43+
44+
pub fn try_from_bech32_string(s: &str, verify: bool) -> Result<Self, Error> {
45+
let data = match nostr::bech32::decode(s) {
46+
Ok(res) => Ok(res),
47+
Err(_) => Err(Error::InvalidBech32),
48+
}?;
49+
50+
if data.0 != HRP_NPUB {
51+
Err(Error::InvalidBech32)
52+
} else if data.1.len() != 32 {
53+
Err(Error::InvalidByteSize)
54+
} else {
55+
if verify {
56+
let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&data.1) {
57+
Ok(r) => Ok(r),
58+
Err(_) => Err(Error::InvalidPublicKey),
59+
}?;
60+
}
61+
Ok(Pubkey(data.1.try_into().unwrap()))
62+
}
63+
}
2864
}
2965

3066
impl fmt::Display for Pubkey {

0 commit comments

Comments
 (0)