serialize Keypair using tokenator

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-03-17 18:11:41 -04:00
parent 1e05fa551d
commit 0bd486a8f4
4 changed files with 133 additions and 0 deletions

2
Cargo.lock generated
View File

@@ -1344,6 +1344,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"thiserror 2.0.12", "thiserror 2.0.12",
"tokenator",
"tokio", "tokio",
"tracing", "tracing",
"url", "url",
@@ -2748,6 +2749,7 @@ dependencies = [
"strum_macros", "strum_macros",
"tempfile", "tempfile",
"thiserror 2.0.12", "thiserror 2.0.12",
"tokenator",
"tracing", "tracing",
"url", "url",
"uuid", "uuid",

View File

@@ -19,3 +19,4 @@ thiserror = { workspace = true }
url = { workspace = true } url = { workspace = true }
mio = { workspace = true } mio = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
tokenator = { workspace = true }

View File

@@ -1,6 +1,11 @@
use nostr::nips::nip19::FromBech32;
use nostr::nips::nip19::ToBech32;
use nostr::nips::nip49::EncryptedSecretKey; use nostr::nips::nip49::EncryptedSecretKey;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use tokenator::ParseError;
use tokenator::TokenParser;
use tokenator::TokenSerializable;
use crate::Pubkey; use crate::Pubkey;
use crate::SecretKey; use crate::SecretKey;
@@ -137,3 +142,127 @@ impl SerializableKeypair {
) )
} }
} }
impl TokenSerializable for Pubkey {
fn parse_from_tokens<'a>(parser: &mut TokenParser<'a>) -> Result<Self, ParseError<'a>> {
parser.parse_token(PUBKEY_TOKEN)?;
let raw = parser.pull_token()?;
let pubkey =
Pubkey::try_from_bech32_string(raw, true).map_err(|_| ParseError::DecodeFailed)?;
Ok(pubkey)
}
fn serialize_tokens(&self, writer: &mut tokenator::TokenWriter) {
writer.write_token(PUBKEY_TOKEN);
let Some(bech) = self.to_bech() else {
tracing::error!("Could not convert pubkey to bech: {}", self.hex());
return;
};
writer.write_token(&bech);
}
}
impl TokenSerializable for Keypair {
fn parse_from_tokens<'a>(parser: &mut TokenParser<'a>) -> Result<Self, ParseError<'a>> {
TokenParser::alt(
parser,
&[
|p| Ok(Keypair::only_pubkey(Pubkey::parse_from_tokens(p)?)),
|p| Ok(Keypair::from_secret(parse_seckey(p)?)),
],
)
}
fn serialize_tokens(&self, writer: &mut tokenator::TokenWriter) {
if let Some(seckey) = &self.secret_key {
writer.write_token(ESECKEY_TOKEN);
let maybe_eseckey = EncryptedSecretKey::new(
seckey,
ESECKEY_PASS,
7,
nostr::nips::nip49::KeySecurity::Unknown,
);
let Ok(eseckey) = maybe_eseckey else {
tracing::error!("Could not convert seckey to EncryptedSecretKey");
return;
};
let Ok(serialized) = eseckey.to_bech32() else {
tracing::error!("Could not serialize ncryptsec");
return;
};
writer.write_token(&serialized);
} else {
self.pubkey.serialize_tokens(writer);
}
}
}
const ESECKEY_TOKEN: &str = "eseckey";
const ESECKEY_PASS: &str = "notedeck";
const PUBKEY_TOKEN: &str = "pubkey";
fn parse_seckey<'a>(parser: &mut TokenParser<'a>) -> Result<SecretKey, ParseError<'a>> {
parser.parse_token(ESECKEY_TOKEN)?;
let raw = parser.pull_token()?;
let eseckey = EncryptedSecretKey::from_bech32(raw).map_err(|_| ParseError::DecodeFailed)?;
let seckey = eseckey
.to_secret_key(ESECKEY_PASS)
.map_err(|_| ParseError::DecodeFailed)?;
Ok(seckey)
}
#[cfg(test)]
mod tests {
use tokenator::{TokenParser, TokenSerializable, TokenWriter};
use super::{FullKeypair, Keypair};
#[test]
fn test_token_eseckey_serialize_deserialize() {
let kp = FullKeypair::generate();
let mut writer = TokenWriter::new("\t");
kp.clone().to_keypair().serialize_tokens(&mut writer);
let serialized = writer.str();
let data = &serialized.split("\t").collect::<Vec<&str>>();
let mut parser = TokenParser::new(data);
let m_new_kp = Keypair::parse_from_tokens(&mut parser);
assert!(m_new_kp.is_ok());
let new_kp = m_new_kp.unwrap();
assert_eq!(kp, new_kp.to_full().unwrap().to_full());
}
#[test]
fn test_token_pubkey_serialize_deserialize() {
let kp = Keypair::only_pubkey(FullKeypair::generate().pubkey);
let mut writer = TokenWriter::new("\t");
kp.clone().serialize_tokens(&mut writer);
let serialized = writer.str();
let data = &serialized.split("\t").collect::<Vec<&str>>();
let mut parser = TokenParser::new(data);
let m_new_kp = Keypair::parse_from_tokens(&mut parser);
assert!(m_new_kp.is_ok());
let new_kp = m_new_kp.unwrap();
assert_eq!(kp, new_kp);
}
}

View File

@@ -31,6 +31,7 @@ bincode = { workspace = true }
ehttp = {workspace = true } ehttp = {workspace = true }
mime_guess = { workspace = true } mime_guess = { workspace = true }
egui-winit = { workspace = true } egui-winit = { workspace = true }
tokenator = { workspace = true }
[dev-dependencies] [dev-dependencies]
tempfile = { workspace = true } tempfile = { workspace = true }