Skip to content

Commit d31ab40

Browse files
committed
Merge main
2 parents 621c61d + e4eacd0 commit d31ab40

File tree

5 files changed

+122
-12
lines changed

5 files changed

+122
-12
lines changed

Diff for: Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "carbonado"
3-
version = "0.4.0"
43
edition = "2021"
4+
version = "0.5.0"
55
license = "MIT"
66
description = "An apocalypse-resistant data storage format for the truly paranoid."
77
documentation = "https://docs.rs/carbonado"
@@ -22,6 +22,8 @@ hex = "0.4.3"
2222
libsecp256k1 = { version = "0.7.1", features = ["std"] }
2323
log = "0.4.19"
2424
nom = "7.1.3"
25+
nostr = "0.28.1"
26+
nostr-sdk = "0.28.0"
2527
pretty_env_logger = "0.5.0"
2628
secp256k1 = { version = "0.29.0", features = [
2729
"global-context",

Diff for: src/error.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ pub enum CarbonadoError {
2626
#[error(transparent)]
2727
Bech32DecodeError(#[from] bech32::DecodeError),
2828

29-
/// Bech32 human readable part error
29+
/// Bech32 hrp error
3030
#[error(transparent)]
31-
InvalidHrp(#[from] bech32::primitives::hrp::Error),
31+
Bech32HrpError(#[from] bech32::primitives::hrp::Error),
3232

3333
/// snap error
3434
#[error(transparent)]
@@ -50,6 +50,14 @@ pub enum CarbonadoError {
5050
#[error(transparent)]
5151
ZfecError(#[from] zfec_rs::Error),
5252

53+
/// nostr secp256k1 error
54+
#[error(transparent)]
55+
NostrSecp256k1Error(#[from] nostr::secp256k1::Error),
56+
57+
/// nostr NIP-19 / Bech32 error
58+
#[error(transparent)]
59+
NostrNip19Error(#[from] nostr::nips::nip19::Error),
60+
5361
/// An uneven number of input bytes were provided for zfec chunks
5462
#[error("Input bytes must divide evenly over number of zfec chunks.")]
5563
UnevenZfecChunks,
@@ -109,4 +117,8 @@ pub enum CarbonadoError {
109117
/// Invalid header length calculation
110118
#[error("Invalid header length calculation")]
111119
InvalidHeaderLength,
120+
121+
/// Invalid header length calculation
122+
#[error("Incorrect public key format")]
123+
IncorrectPubKeyFormat,
112124
}

Diff for: src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ pub use decoding::extract_slice;
2727
pub use decoding::verify_slice;
2828

2929
pub use decoding::scrub;
30+
31+
pub use bao;
32+
pub use secp256k1;

Diff for: src/structs.rs

+97
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
use std::{
2+
fmt::{self, Display},
3+
str::FromStr,
4+
};
5+
6+
use nostr::{FromBech32, PublicKey};
17
use serde::{Deserialize, Serialize};
28

9+
use crate::error::CarbonadoError;
10+
311
/// Information from the encoding step, some of which is needed for decoding.
412
#[derive(Serialize, Deserialize, Clone, Debug)]
513
pub struct EncodeInfo {
@@ -38,3 +46,92 @@ pub struct EncodeInfo {
3846
/// Tuple of verifiable bytes, bao hash, and encode info struct
3947
/// i.e., Encoded(encoded_bytes, bao_hash, encode_info)
4048
pub struct Encoded(pub Vec<u8>, pub bao::Hash, pub EncodeInfo);
49+
50+
pub struct Secp256k1PubKey {
51+
pub pk: secp256k1::PublicKey,
52+
pub x_only_pk: [u8; 32],
53+
}
54+
55+
impl TryFrom<&str> for Secp256k1PubKey {
56+
type Error = CarbonadoError;
57+
58+
fn try_from(value: &str) -> Result<Self, Self::Error> {
59+
let pk = match value.get(0..2).expect("key is at least 2 characters long") {
60+
"+n" => secp256k1::PublicKey::from_x_only_public_key(
61+
secp256k1::XOnlyPublicKey::from_slice(
62+
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
63+
)?,
64+
secp256k1::Parity::Even,
65+
),
66+
"-n" => secp256k1::PublicKey::from_x_only_public_key(
67+
secp256k1::XOnlyPublicKey::from_slice(
68+
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
69+
)?,
70+
secp256k1::Parity::Odd,
71+
),
72+
"02" => secp256k1::PublicKey::from_str(value)?,
73+
"03" => secp256k1::PublicKey::from_str(value)?,
74+
_ => return Err(CarbonadoError::IncorrectPubKeyFormat),
75+
};
76+
77+
let (x_only_pk, _) = pk.x_only_public_key();
78+
let x_only_pk = x_only_pk.serialize();
79+
80+
Ok(Self { pk, x_only_pk })
81+
}
82+
}
83+
84+
impl Display for Secp256k1PubKey {
85+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86+
let Self { pk, .. } = self;
87+
88+
f.write_str(&pk.to_string())
89+
}
90+
}
91+
92+
impl AsRef<[u8; 32]> for Secp256k1PubKey {
93+
fn as_ref(&self) -> &[u8; 32] {
94+
&self.x_only_pk
95+
}
96+
}
97+
98+
impl Secp256k1PubKey {
99+
pub fn new(pk: secp256k1::PublicKey) -> Self {
100+
let (x_only_pk, _) = pk.x_only_public_key();
101+
let x_only_pk = x_only_pk.serialize();
102+
103+
Self { pk, x_only_pk }
104+
}
105+
106+
pub fn to_bytes(&self) -> Vec<u8> {
107+
let Self { pk, .. } = self;
108+
109+
pk.serialize().to_vec()
110+
}
111+
112+
pub fn into_inner(&self) -> secp256k1::PublicKey {
113+
let Self { pk, .. } = self;
114+
115+
pk.to_owned()
116+
}
117+
}
118+
119+
#[test]
120+
fn test_pubkey_decode() {
121+
let result = Secp256k1PubKey::try_from(
122+
"+npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
123+
);
124+
assert!(result.is_ok());
125+
assert_eq!(
126+
result.unwrap().to_string(),
127+
"02a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
128+
);
129+
let result = Secp256k1PubKey::try_from(
130+
"-npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
131+
);
132+
assert!(result.is_ok());
133+
assert_eq!(
134+
result.unwrap().to_string(),
135+
"03a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
136+
);
137+
}

Diff for: src/utils.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
};
66

77
use bao::{encode::Encoder, Hash};
8-
use bech32::{decode, encode_to_fmt, Bech32m, Hrp};
8+
use bech32::{decode, encode, Bech32m, Hrp};
99
use log::trace;
1010

1111
use crate::{
@@ -58,18 +58,14 @@ pub fn calc_padding_len(input_len: usize) -> (u32, u32) {
5858
}
5959

6060
/// Helper for encoding data to bech32m.
61-
pub fn bech32m_encode(hrp_str: &str, bytes: &[u8]) -> Result<String, CarbonadoError> {
62-
let hrp = Hrp::parse(hrp_str).map_err(CarbonadoError::InvalidHrp)?;
63-
let mut buf = String::new();
64-
encode_to_fmt::<Bech32m, String>(&mut buf, hrp, bytes)?;
65-
Ok(buf)
61+
pub fn bech32m_encode(hrp: &str, bytes: &[u8]) -> Result<String, CarbonadoError> {
62+
Ok(encode::<Bech32m>(Hrp::parse(hrp)?, bytes)?)
6663
}
6764

6865
/// Helper for decoding bech32-encoded data.
6966
pub fn bech32_decode(bech32_str: &str) -> Result<(String, Vec<u8>), CarbonadoError> {
70-
let (hrp, data) = decode(bech32_str).map_err(CarbonadoError::Bech32DecodeError)?;
71-
let hrp_str = hrp.to_string();
72-
Ok((hrp_str, data))
67+
let (hrp, words) = decode(bech32_str)?;
68+
Ok((hrp.to_string(), words))
7369
}
7470

7571
#[derive(Clone, Debug)]

0 commit comments

Comments
 (0)