Skip to content

Commit

Permalink
Feature: generate several keys (#3)
Browse files Browse the repository at this point in the history
* Add ability to generate several keys

* Several keys are generated independently
  • Loading branch information
SilkovAlexander authored Sep 3, 2024
1 parent 4f08941 commit aa4ff1b
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 17 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "gosh_bls_lib"
version = "0.3.1"
version = "0.4.0"

[profile.profiling]
debug = 1
Expand Down Expand Up @@ -34,6 +34,8 @@ hex = "0.4.3"
rand = "0.7"
rand_chacha = "0.2"
tvm_types = { git = "https://github.com/tvmlabs/tvm-types", tag = "3.0.1" }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.117"

[[bin]]
name = "bls_keypair_gen"
70 changes: 54 additions & 16 deletions src/bin/bls_keypair_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,73 @@ use clap::Parser;
use gosh_bls_lib::bls::gen_bls_key_pair;
use gosh_bls_lib::bls::gen_bls_key_pair_based_on_key_material;
use gosh_bls_lib::bls::BLS_SECRET_KEY_LEN;
use gosh_bls_lib::serde_bls::BLSKeyPair;

const DEFAULT_FILE_STEM: &str = "bls_";
const FILE_EXTENSION: &str = ".keys.json";

#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Args {
/// Hex string with 32 bytes of key material for bls
/// Hex string with 32 bytes of key material
#[arg(short, long)]
key_material: Option<String>,
/// Number of key pairs that should be generated
#[arg(short, long, conflicts_with = "key_material")]
number: Option<u32>,
/// Output directory for generated keys (use only for generating several keys)
#[arg(short, long, conflicts_with = "path", requires = "number")]
output_dir: Option<String>,
/// Output file path (use only for generating a single key)
#[arg(short, long, conflicts_with_all = ["output_dir", "number"])]
path: Option<String>,
/// Output file stem (used to generate several files: <stem><i>.keys.json
#[arg(long, conflicts_with = "path", requires = "number")]
output_stem: Option<String>,
}

fn main() {
fn main() -> anyhow::Result<()> {
let args: Args = Args::parse();

let (public, secret) = if let Some(key_material) = args.key_material {
// Generate first key pair, that will be used as seed in case of generating several keys
let first_key = BLSKeyPair::from(if let Some(key_material) = args.key_material {
let mut secret_key = [0_u8; BLS_SECRET_KEY_LEN];
hex::decode_to_slice(key_material.trim_start_matches("0x"), &mut secret_key)
.expect("Failed to decode secret key from hex");
.map_err(|e| anyhow::format_err!("Failed to decode secret key from hex: {e}"))?;

gen_bls_key_pair_based_on_key_material(&secret_key)
.expect("Failed to generate BLS key pair")
.map_err(|e| anyhow::format_err!("Failed to generate BLS key pair: {e}"))?
} else {
gen_bls_key_pair().expect("Failed to generate BLS key pair")
};

println!(
r#"{{
"public": "{}",
"secret": "{}"
}}"#,
hex::encode(public),
hex::encode(secret)
);
gen_bls_key_pair()
.map_err(|e| anyhow::format_err!("Failed to generate BLS key pair: {e}"))?
});

if let Some(path) = args.path {
return first_key.save_to_file(path);
}
if let Some(number) = args.number {
let file_stem = args.output_stem.unwrap_or(DEFAULT_FILE_STEM.to_string());
let output_dir = args.output_dir.unwrap_or(".".to_string());
if !std::path::Path::new(&output_dir).exists() {
std::fs::create_dir_all(&output_dir)?;
}
let full_path_stem = format!("{}/{}", output_dir.trim_end_matches('/'), file_stem);

let path = format!("{}{}{}", full_path_stem, 0, FILE_EXTENSION);
first_key.save_to_file(path)?;

for i in 1..number {
let key_pair = BLSKeyPair::from(
gen_bls_key_pair()
.map_err(|e| anyhow::format_err!("Failed to generate BLS key pair: {e}"))?,
);
let path = format!("{}{}{}", full_path_stem, i, FILE_EXTENSION);
key_pair.save_to_file(path)?;
}
return Ok(());
}

println!("{}", first_key.to_string()?);

Ok(())
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod bls;
pub mod serde_bls;
45 changes: 45 additions & 0 deletions src/serde_bls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use serde::Serialize;
use std::path::Path;

use crate::bls::BLS_PUBLIC_KEY_LEN;
use crate::bls::BLS_SECRET_KEY_LEN;

pub struct BLSKeyPair {
pub public: [u8; BLS_PUBLIC_KEY_LEN],
pub secret: [u8; BLS_SECRET_KEY_LEN],
}

#[derive(Serialize)]
struct WrappedBLSKeyPair {
public: String,
secret: String,
}

impl WrappedBLSKeyPair {
pub fn new(key_pair: &BLSKeyPair) -> Self {
WrappedBLSKeyPair {
public: hex::encode(key_pair.public),
secret: hex::encode(key_pair.secret),
}
}
}

impl BLSKeyPair {
pub fn from(data: ([u8; BLS_PUBLIC_KEY_LEN], [u8; BLS_SECRET_KEY_LEN])) -> Self {
Self {
public: data.0,
secret: data.1,
}
}

pub fn to_string(&self) -> anyhow::Result<String> {
let wrapped = WrappedBLSKeyPair::new(self);
serde_json::to_string_pretty(&wrapped)
.map_err(|e| anyhow::format_err!("Failed to serialize BLSKeyPair: {e}"))
}

pub fn save_to_file(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
std::fs::write(path, self.to_string()?)
.map_err(|e| anyhow::format_err!("Failed to save BLSKetPait: {e}"))
}
}

0 comments on commit aa4ff1b

Please sign in to comment.