Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ This is kind of bonkers, so here's a command-line utility that you can run to co

## Features:
>Note: "keys" + "nip5" arguments accept multiple inputs for bulk operations
- convert from bech32 (npub/nsec/note) to hex
- convert from hex to bech32 (npub/nsec/note)
- convert from bech32 (npub/nsec/note/nprofile/nevent) to hex
- convert from hex to bech32 (npub/nsec/note/nprofile/nevent)
- supports NIP-05 domain identifiers:
- calls given nip5 domain to get nostr.json containing user pubkeys (located at domain.com/.well-known/nostr.json)
- extracts and converts all pubkeys from hex to bech32 format
Expand Down Expand Up @@ -44,15 +44,17 @@ Just provide the hex-encoded key or note-id and a `--kind` argument. The `kind`s
- npub
- nsec
- note
- nprofile
- nevent

To convert from an `bech32(npub/nsec/note) to hex-encoding`, you can do
To convert from an `bech32(npub/nsec/note/nprofile/nevent) to hex-encoding`, you can do

```shell
$> key-convertr --to-hex npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6
3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d
```

To convert from an `hex-encoding to bech32 (npub/nsec/note)`, you can do
To convert from an `hex-encoding to bech32 (npub/nsec/note/nprofile/nevent)`, you can do

```shell
$> key-convertr --kind npub 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d
Expand Down Expand Up @@ -90,4 +92,4 @@ $> key-convertr --nip5 nostrplebs.com,strike.me,satoshivibes.com
---
## TODO
Optimizations:
- multi threaded "--nip5" logic (multiple domains converted in parallel; some lists will be very large i.e nostrplebs.com)
- multi threaded "--nip5" logic (multiple domains converted in parallel; some lists will be very large i.e nostrplebs.com)
44 changes: 38 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,33 @@ use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use thiserror::Error;
use tokio::task::JoinHandle;
use std::str::FromStr;

#[derive(clap::ValueEnum, Clone, Debug, Copy)]
enum Prefix {
Npub,
Nsec,
Note,
Nprofile,
Nevent,
}

#[derive(Debug, PartialEq, Eq)]
struct ParsePrefixError;

impl FromStr for Prefix {
type Err = ParsePrefixError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"npub" => Ok(Prefix::Npub),
"nsec" => Ok(Prefix::Nsec),
"note" => Ok(Prefix::Note),
"nprofile" => Ok(Prefix::Nprofile),
"nevent" => Ok(Prefix::Nevent),
_ => Err(ParsePrefixError),
}
}
}

// Display 'trait' needed for enum "to_string()"
Expand All @@ -24,6 +45,8 @@ impl std::fmt::Display for Prefix {
Prefix::Npub => write!(f, "npub"),
Prefix::Nsec => write!(f, "nsec"),
Prefix::Note => write!(f, "note"),
Prefix::Nprofile => write!(f, "nprofile"),
Prefix::Nevent => write!(f, "nevent"),
}
}
}
Expand All @@ -45,7 +68,7 @@ struct Args {
#[arg(
short,
long,
help = "the kind of entity (npub/nsec/note) being converted from hex to bech32-formatted string",
help = "the kind of entity (npub/nsec/note/nprofile/nevent) being converted from hex to bech32-formatted string",
requires = "keys"
)]
kind: Option<Prefix>,
Expand Down Expand Up @@ -86,14 +109,19 @@ async fn main() -> Result<()> {
let args = Args::parse();

if args.to_hex {
// convert bech32 npub/nsec/note to hex (accepts list of bech32's)
// convert bech32 npub/nsec/note/nprofile/nevent to hex (accepts list of bech32's)
for s in &args.keys {
let (_, data, _) = bech32::decode(s)?;
println!("{}", hex::encode(Vec::<u8>::from_base32(&data)?));
let (hrp, data, _) = bech32::decode(s)?;
let hrp = Prefix::from_str(hrp.as_str()).unwrap();
match hrp {
Prefix::Nevent |
Prefix::Nprofile => println!("{}", &hex::encode(&Vec::<u8>::from_base32(&data)?)[4..]),
_ => println!("{}", hex::encode(&Vec::<u8>::from_base32(&data)?)),
};
}
Ok(())
} else if args.kind.is_some() {
// convert hex to bech32 npub/nsec/note (accepts list of hex)
// convert hex to bech32 npub/nsec/note/nprofile/nevent (accepts list of hex)
let hrp = args.kind.unwrap();
for key in &args.keys {
let encoded = bech32_encode(hrp, key).unwrap();
Expand Down Expand Up @@ -159,9 +187,13 @@ enum KeyValidationError {
}
/// Converts a hex encoded string to bech32 format for given a Prefix (hrp)
fn bech32_encode(hrp: Prefix, hex_key: &String) -> Result<String, KeyValidationError> {
let hex_str = match hrp {
Prefix::Nevent | Prefix::Nprofile => format!("0020{hex_key}"),
_ => format!("{hex_key}"),
};
bech32::encode(
&hrp.to_string(),
hex::decode(hex_key)
hex::decode(&hex_str)
.map_err(|_| InvalidKeyDecode(hex_key.to_string()))?
.to_base32(),
Variant::Bech32,
Expand Down