bitcoin_hash_toolkit 0.1.0

A toolkit for Bitcoin hashing functions
Documentation
// src/main.rs

use clap::{Parser, Subcommand};
use bitcoin_hash_toolkit::{
    sha256, ripemd160, hash160, generate_private_key, derive_public_key, derive_address
};
use hex;
use secp256k1::SecretKey;

#[derive(Parser, Debug)]
#[command(author, version, about = "Bitcoin Cryptography Toolkit", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// Hashes an input string or hex-encoded data using SHA256
    Sha256 {
        data: String,
        #[arg(short = 'x', long)]
        hex_input: bool,
    },
    /// Hashes an input string or hex-encoded data using RIPEMD160
    Ripemd160 {
        data: String,
        #[arg(short = 'x', long)]
        hex_input: bool,
    },
    /// Calculates HASH160 (SHA256 -> RIPEMD160)
    Hash160 {
        data: String,
        #[arg(short = 'x', long)]
        hex_input: bool,
    },
    /// Generates a new secp256k1 key pair and derives the Bitcoin address
    GenerateKey,
    /// Derives the Bitcoin address from a hex-encoded private key
    DeriveAddress {
        private_key_hex: String,
    },
}


// src/main.rs (continuation)

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cli = Cli::parse();

    match &cli.command {
        Commands::Sha256 { data, hex_input } => handle_hash_command(data, *hex_input, sha256, "SHA256"),
        Commands::Ripemd160 { data, hex_input } => handle_hash_command(data, *hex_input, ripemd160, "RIPEMD160"),
        Commands::Hash160 { data, hex_input } => handle_hash_command(data, *hex_input, hash160, "HASH160"),
        Commands::GenerateKey => handle_generate_key(),
        Commands::DeriveAddress { private_key_hex } => handle_derive_address(private_key_hex),
    }
}

// Utility function to handle the hashing commands
fn handle_hash_command(data: &str, hex_input: bool, hash_func: fn(&[u8]) -> Vec<u8>, name: &str) -> Result<(), Box<dyn std::error::Error>> {
    let input_bytes = if hex_input {
        hex::decode(data)?
    } else {
        data.as_bytes().to_vec()
    };
    
    let hash_result = hash_func(&input_bytes);
    println!("{}: {}", name, hex::encode(hash_result));
    Ok(())
}

fn handle_generate_key() -> Result<(), Box<dyn std::error::Error>> {
    let private_key = generate_private_key();
    let public_key = derive_public_key(&private_key);
    let address = derive_address(&public_key);

    println!("\n--- Generated Key Pair ---");
    println!("**Private Key (WIF format not implemented yet):** {}", hex::encode(private_key.secret_bytes()));
    println!("**Public Key (Compressed):** {}", hex::encode(public_key.serialize()));
    println!("**P2PKH Bitcoin Address (Mainnet):** {}", address);
    Ok(())
}

fn handle_derive_address(private_key_hex: &str) -> Result<(), Box<dyn std::error::Error>> {
    let pk_bytes = hex::decode(private_key_hex)?;
    let private_key = SecretKey::from_slice(&pk_bytes)?;
    
    let public_key = derive_public_key(&private_key);
    let address = derive_address(&public_key);

    println!("\n--- Address Derivation Result ---");
    println!("**Input Private Key:** {}", private_key_hex);
    println!("**Public Key (Compressed):** {}", hex::encode(public_key.serialize()));
    println!("**P2PKH Bitcoin Address:** {}", address);
    Ok(())
}