Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptoquick committed Jun 5, 2024
2 parents 621c61d + e4eacd0 commit d31ab40
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 12 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "carbonado"
version = "0.4.0"
edition = "2021"
version = "0.5.0"
license = "MIT"
description = "An apocalypse-resistant data storage format for the truly paranoid."
documentation = "https://docs.rs/carbonado"
Expand All @@ -22,6 +22,8 @@ hex = "0.4.3"
libsecp256k1 = { version = "0.7.1", features = ["std"] }
log = "0.4.19"
nom = "7.1.3"
nostr = "0.28.1"
nostr-sdk = "0.28.0"
pretty_env_logger = "0.5.0"
secp256k1 = { version = "0.29.0", features = [
"global-context",
Expand Down
16 changes: 14 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ pub enum CarbonadoError {
#[error(transparent)]
Bech32DecodeError(#[from] bech32::DecodeError),

/// Bech32 human readable part error
/// Bech32 hrp error
#[error(transparent)]
InvalidHrp(#[from] bech32::primitives::hrp::Error),
Bech32HrpError(#[from] bech32::primitives::hrp::Error),

/// snap error
#[error(transparent)]
Expand All @@ -50,6 +50,14 @@ pub enum CarbonadoError {
#[error(transparent)]
ZfecError(#[from] zfec_rs::Error),

/// nostr secp256k1 error
#[error(transparent)]
NostrSecp256k1Error(#[from] nostr::secp256k1::Error),

/// nostr NIP-19 / Bech32 error
#[error(transparent)]
NostrNip19Error(#[from] nostr::nips::nip19::Error),

/// An uneven number of input bytes were provided for zfec chunks
#[error("Input bytes must divide evenly over number of zfec chunks.")]
UnevenZfecChunks,
Expand Down Expand Up @@ -109,4 +117,8 @@ pub enum CarbonadoError {
/// Invalid header length calculation
#[error("Invalid header length calculation")]
InvalidHeaderLength,

/// Invalid header length calculation
#[error("Incorrect public key format")]
IncorrectPubKeyFormat,
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ pub use decoding::extract_slice;
pub use decoding::verify_slice;

pub use decoding::scrub;

pub use bao;
pub use secp256k1;
97 changes: 97 additions & 0 deletions src/structs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use std::{
fmt::{self, Display},
str::FromStr,
};

use nostr::{FromBech32, PublicKey};
use serde::{Deserialize, Serialize};

use crate::error::CarbonadoError;

/// Information from the encoding step, some of which is needed for decoding.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EncodeInfo {
Expand Down Expand Up @@ -38,3 +46,92 @@ pub struct EncodeInfo {
/// Tuple of verifiable bytes, bao hash, and encode info struct
/// i.e., Encoded(encoded_bytes, bao_hash, encode_info)
pub struct Encoded(pub Vec<u8>, pub bao::Hash, pub EncodeInfo);

pub struct Secp256k1PubKey {
pub pk: secp256k1::PublicKey,
pub x_only_pk: [u8; 32],
}

impl TryFrom<&str> for Secp256k1PubKey {
type Error = CarbonadoError;

fn try_from(value: &str) -> Result<Self, Self::Error> {
let pk = match value.get(0..2).expect("key is at least 2 characters long") {
"+n" => secp256k1::PublicKey::from_x_only_public_key(
secp256k1::XOnlyPublicKey::from_slice(
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
)?,
secp256k1::Parity::Even,
),
"-n" => secp256k1::PublicKey::from_x_only_public_key(
secp256k1::XOnlyPublicKey::from_slice(
&PublicKey::from_bech32(value.get(1..).unwrap())?.to_bytes(),
)?,
secp256k1::Parity::Odd,
),
"02" => secp256k1::PublicKey::from_str(value)?,
"03" => secp256k1::PublicKey::from_str(value)?,
_ => return Err(CarbonadoError::IncorrectPubKeyFormat),
};

let (x_only_pk, _) = pk.x_only_public_key();
let x_only_pk = x_only_pk.serialize();

Ok(Self { pk, x_only_pk })
}
}

impl Display for Secp256k1PubKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { pk, .. } = self;

f.write_str(&pk.to_string())
}
}

impl AsRef<[u8; 32]> for Secp256k1PubKey {
fn as_ref(&self) -> &[u8; 32] {
&self.x_only_pk
}
}

impl Secp256k1PubKey {
pub fn new(pk: secp256k1::PublicKey) -> Self {
let (x_only_pk, _) = pk.x_only_public_key();
let x_only_pk = x_only_pk.serialize();

Self { pk, x_only_pk }
}

pub fn to_bytes(&self) -> Vec<u8> {
let Self { pk, .. } = self;

pk.serialize().to_vec()
}

pub fn into_inner(&self) -> secp256k1::PublicKey {
let Self { pk, .. } = self;

pk.to_owned()
}
}

#[test]
fn test_pubkey_decode() {
let result = Secp256k1PubKey::try_from(
"+npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"02a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
);
let result = Secp256k1PubKey::try_from(
"-npub14rnkcwkw0q5lnmjye7ffxvy7yxscyjl3u4mrr5qxsks76zctmz3qvuftjz",
);
assert!(result.is_ok());
assert_eq!(
result.unwrap().to_string(),
"03a8e76c3ace7829f9ee44cf9293309e21a1824bf1e57631d00685a1ed0b0bd8a2"
);
}
14 changes: 5 additions & 9 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use bao::{encode::Encoder, Hash};
use bech32::{decode, encode_to_fmt, Bech32m, Hrp};
use bech32::{decode, encode, Bech32m, Hrp};
use log::trace;

use crate::{
Expand Down Expand Up @@ -58,18 +58,14 @@ pub fn calc_padding_len(input_len: usize) -> (u32, u32) {
}

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

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

#[derive(Clone, Debug)]
Expand Down

0 comments on commit d31ab40

Please sign in to comment.