Add keypair & update pubkey

Keypair & FullKeypair match structs in damus ios

Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
kernelkind
2024-05-07 19:57:40 -04:00
committed by William Casarin
parent b8177459ab
commit e04c8821d5
4 changed files with 119 additions and 2 deletions

View File

@@ -8,8 +8,10 @@ pub enum Error {
Empty,
DecodeFailed,
HexDecodeFailed,
InvalidBech32,
InvalidByteSize,
InvalidSignature,
InvalidPublicKey,
// Secp(secp256k1::Error),
Json(serde_json::Error),
Generic(String),
@@ -23,6 +25,7 @@ impl std::cmp::PartialEq for Error {
(Error::HexDecodeFailed, Error::HexDecodeFailed) => true,
(Error::InvalidSignature, Error::InvalidSignature) => true,
(Error::InvalidByteSize, Error::InvalidByteSize) => true,
(Error::InvalidPublicKey, Error::InvalidPublicKey) => true,
// This is slightly wrong but whatevs
(Error::Json(..), Error::Json(..)) => true,
(Error::Generic(left), Error::Generic(right)) => left == right,
@@ -40,6 +43,8 @@ impl fmt::Display for Error {
Self::InvalidSignature => write!(f, "invalid signature"),
Self::HexDecodeFailed => write!(f, "hex decoding failed"),
Self::InvalidByteSize => write!(f, "invalid byte size"),
Self::InvalidBech32 => write!(f, "invalid bech32 string"),
Self::InvalidPublicKey => write!(f, "invalid public key"),
//Self::Secp(e) => write!(f, "{e}"),
Self::Json(e) => write!(f, "{e}"),
Self::Generic(e) => write!(f, "{e}"),

73
enostr/src/keypair.rs Normal file
View File

@@ -0,0 +1,73 @@
use crate::Pubkey;
use crate::SecretKey;
#[derive(Debug, Eq, PartialEq)]
pub struct Keypair {
pub pubkey: Pubkey,
pub secret_key: Option<SecretKey>,
}
impl Keypair {
pub fn new(secret_key: SecretKey) -> Self {
let cloned_secret_key = secret_key.clone();
let nostr_keys = nostr::Keys::new(secret_key);
Keypair {
pubkey: Pubkey::new(&nostr_keys.public_key().to_bytes()),
secret_key: Some(cloned_secret_key),
}
}
pub fn only_pubkey(pubkey: Pubkey) -> Self {
Keypair {
pubkey,
secret_key: None,
}
}
pub fn to_full(self) -> Option<FullKeypair> {
if let Some(secret_key) = self.secret_key {
Some(FullKeypair {
pubkey: self.pubkey,
secret_key,
})
} else {
None
}
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct FullKeypair {
pub pubkey: Pubkey,
pub secret_key: SecretKey,
}
impl FullKeypair {
pub fn new(pubkey: Pubkey, secret_key: SecretKey) -> Self {
FullKeypair { pubkey, secret_key }
}
}
impl std::fmt::Display for Keypair {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Keypair:\n\tpublic: {}\n\tsecret: {}",
self.pubkey,
match self.secret_key {
Some(_) => "Some(<hidden>)",
None => "None",
}
)
}
}
impl std::fmt::Display for FullKeypair {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Keypair:\n\tpublic: {}\n\tsecret: {}",
self.pubkey, "<hidden>"
)
}
}

View File

@@ -2,6 +2,7 @@ mod client;
mod error;
mod event;
mod filter;
mod keypair;
mod profile;
mod pubkey;
mod relay;
@@ -11,6 +12,8 @@ pub use error::Error;
pub use event::{Event, EventId};
pub use ewebsock;
pub use filter::Filter;
pub use keypair::{FullKeypair, Keypair};
pub use nostr::SecretKey;
pub use profile::Profile;
pub use pubkey::Pubkey;
pub use relay::message::{RelayEvent, RelayMessage};

View File

@@ -1,14 +1,15 @@
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::Error;
use hex;
use log::debug;
//use nostr::key::XOnlyPublicKey;
use nostr::bech32::Hrp;
use std::fmt;
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Pubkey([u8; 32]);
static HRP_NPUB: Hrp = Hrp::parse_unchecked("npub");
impl Pubkey {
pub fn new(data: &[u8; 32]) -> Self {
Self(*data)
@@ -25,6 +26,41 @@ impl Pubkey {
pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
Ok(Pubkey(hex::decode(hex_str)?.as_slice().try_into()?))
}
pub fn try_from_hex_str_with_verify(hex_str: &str) -> Result<Self, Error> {
let vec: Vec<u8> = hex::decode(hex_str)?;
if vec.len() != 32 {
Err(Error::HexDecodeFailed)
} else {
let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&vec) {
Ok(r) => Ok(r),
Err(_) => Err(Error::InvalidPublicKey),
}?;
Ok(Pubkey(vec.try_into().unwrap()))
}
}
pub fn try_from_bech32_string(s: &str, verify: bool) -> Result<Self, Error> {
let data = match nostr::bech32::decode(s) {
Ok(res) => Ok(res),
Err(_) => Err(Error::InvalidBech32),
}?;
if data.0 != HRP_NPUB {
Err(Error::InvalidBech32)
} else if data.1.len() != 32 {
Err(Error::InvalidByteSize)
} else {
if verify {
let _ = match nostr::secp256k1::XOnlyPublicKey::from_slice(&data.1) {
Ok(r) => Ok(r),
Err(_) => Err(Error::InvalidPublicKey),
}?;
}
Ok(Pubkey(data.1.try_into().unwrap()))
}
}
}
impl fmt::Display for Pubkey {