btcaddr 0.1.0

Bitcoin address generation
Documentation

Bitcoin Address Generator (btcaddr)

A secure, type-safe, and high-performance Rust library for Bitcoin address generation.

Crates.io Documentation License: MIT Rust

Overview

btcaddr provides a clean, well-documented implementation of Bitcoin address generation following the BIP32 (Hierarchical Deterministic Wallets) specification. It emphasizes security, type safety, and zero-cost abstractions for performance-critical applications like vanity address generation.

Features

  • Cryptographically Secure Entropy Generation: Uses OS-provided CSPRNG for secure randomness
  • BIP32-Compliant Seed Derivation: HMAC-SHA512-based deterministic key derivation
  • Bitcoin Address Generation: Support for P2PKH addresses (mainnet and testnet)
  • Type-Safe Address Handling: Compile-time guarantees prevent mixing address types
  • Memory Safety: Automatic zeroization of sensitive data using the zeroize crate
  • Zero-Cost Abstractions: High performance through Rust's type system and inlining
  • Comprehensive Documentation: Every function thoroughly documented with examples

Security Guarantees

This library is designed with security as the primary concern:

  • Cryptographically Secure Random Number Generation: All entropy is sourced from OsRng, which uses platform-specific secure random sources (/dev/urandom on Linux, getrandom() syscall, etc.)
  • Memory Zeroization: Sensitive data (Entropy, Seed) is automatically zeroed when dropped, preventing sensitive data from lingering in memory
  • No Copy Trait for Secrets: Prevents untracked duplication of sensitive key material
  • Constant-Time Cryptographic Operations: Uses industry-standard cryptographic libraries (SHA-256, RIPEMD-160, HMAC) with timing attack resistance
  • BIP32 Standard Compliance: Follows Bitcoin Improvement Proposal 32 for deterministic key derivation

Installation

Add btcaddr to your Cargo.toml:

[dependencies]
btcaddr = "0.1.0"

Or use cargo add:

cargo add btcaddr

Quick Start

Generate a Bitcoin Address

use btcaddr::address::public_key_ext::PublicKeyExt;
use btcaddr::seed::Seed;
use secp256k1::{Secp256k1, PublicKey};

// Generate a BIP32 seed directly (combines entropy generation and derivation)
let seed = Seed::generate()
    .expect("Failed to generate seed");

// Extract master secret key (first 32 bytes of HMAC-derived seed)
let secret_key = seed.secret_key()
    .expect("Failed to derive secret key");

// Generate public key from secret key
let secp = Secp256k1::new();
let public_key = PublicKey::from_secret_key(&secp, &secret_key);

// Create Bitcoin address (P2PKH format on mainnet)
let address = public_key.to_p2pkh_address(btcaddr::network::Network::Mainnet);

// Display the address
println!("Bitcoin address: {}", address);
// Output example: "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"

Alternative: Two-Step Generation

If you need more control over the entropy generation, you can use the two-step approach:

use btcaddr::address::public_key_ext::PublicKeyExt;
use btcaddr::seed::Seed;
use secp256k1::{Secp256k1, PublicKey};

// Step 1: Create cryptographically secure entropy
let entropy = btcaddr::entropy::Entropy::new()
    .expect("Failed to generate entropy");

// Step 2: Derive BIP32 seed from entropy
let seed = Seed::from(entropy);

// Extract master secret key and continue as above
let secret_key = seed.secret_key()
    .expect("Failed to derive secret key");

let secp = Secp256k1::new();
let public_key = PublicKey::from_secret_key(&secp, &secret_key);
let address = public_key.to_p2pkh_address(btcaddr::network::Network::Mainnet);

println!("Bitcoin address: {}", address);

Generate Addresses for Different Networks

use btcaddr::address::public_key_ext::PublicKeyExt;
use btcaddr::seed::Seed;
use secp256k1::{Secp256k1, PublicKey};

// Generate seed once
let seed = Seed::generate().unwrap();

let secp = Secp256k1::new();
let secret_key = seed.secret_key().unwrap();
let public_key = PublicKey::from_secret_key(&secp, &secret_key);

// Generate addresses for different networks
let mainnet_addr = public_key.to_p2pkh_address(btcaddr::network::Network::Mainnet);
let testnet_addr = public_key.to_p2pkh_address(btcaddr::network::Network::Testnet);

println!("Mainnet: {}", mainnet_addr);  // Starts with '1'
println!("Testnet: {}", testnet_addr);  // Starts with 'm' or 'n'

Architecture

The library follows a modular architecture with clear separation of concerns:

%%{init: {'theme':'neutral', 'themeVariables': { 'fontSize':'14px'}}}%%
flowchart TD
    A["🔐 OS CSPRNG"] -->|"rand::OsRng"| B["📦 Entropy<br/>64 bytes random"]
    B -->|"HMAC-SHA512<br/>key: 'Bitcoin seed'"| C["🌱 Seed<br/>64 bytes derived"]
    C -->|"Split bytes"| D["🔑 SecretKey<br/>bytes 0..32"]
    C -->|"Split bytes"| E["⛓️ ChainCode<br/>bytes 32..64"]
    D -->|"secp256k1<br/>EC multiplication"| F["🔓 PublicKey<br/>33/65 bytes"]
    F -->|"SHA256"| G["#️⃣ SHA256 Hash<br/>32 bytes"]
    G -->|"RIPEMD160"| H["#️⃣ HASH160<br/>20 bytes"]
    H -->|"Add version byte<br/>Network: Mainnet/Testnet"| I["📋 Address Payload<br/>21 bytes"]
    I -->|"Base58Check<br/>+ 4-byte checksum"| J["✅ Bitcoin Address<br/>1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"]

    classDef entryPoint stroke:#666,stroke-width:2px
    classDef keyMaterial stroke:#666,stroke-width:2.5px
    classDef hashOp stroke:#888,stroke-width:2px
    classDef finalAddr stroke:#333,stroke-width:3px

    class A,B,C entryPoint
    class D,F keyMaterial
    class E,G,H,I hashOp
    class J finalAddr

Alternate Entry Point

You can also use the convenience method Seed::generate() which combines entropy generation and seed derivation:

%%{init: {'theme':'neutral', 'themeVariables': { 'fontSize':'14px'}}}%%
flowchart TD
    A["⚡ Seed::generate"] -->|"Internally calls<br/>Entropy::new + Seed::from"| B["🌱 Seed<br/>64 bytes"]
    B -->|"Continue flow"| C["🔑 SecretKey + ⛓️ ChainCode"]

    classDef entryPoint stroke:#666,stroke-width:2px
    classDef keyMaterial stroke:#666,stroke-width:2.5px

    class A,B entryPoint
    class C keyMaterial

Module Organization

Public Modules

address

Bitcoin address generation and representation system. Provides type-safe address handling with support for P2PKH (Pay-to-Public-Key-Hash) format.

  • Address<T>: Generic address type with compile-time format enforcement
  • PublicKeyExt: Extension trait for converting public keys to addresses
  • Base58Check encoding and checksum calculation
  • HASH160 computation (SHA256 followed by RIPEMD160)

seed

BIP32-compliant seed derivation and key extraction.

  • Seed: 512-bit seed derived from entropy using HMAC-SHA512
  • generate(): Convenience method that generates entropy and derives seed in one step
  • secret_key(): Extracts master secret key (first 256 bits)
  • chain_code(): Extracts chain code for hierarchical key derivation (last 256 bits)
  • Automatic memory zeroization for sensitive data

entropy

Cryptographically secure random number generation using OsRng.

  • Entropy: 512-bit cryptographically secure random data
  • Automatic zeroization on drop
  • CSPRNG-based random generation

network

Bitcoin network type definitions (Mainnet, Testnet). Determines address version bytes and prefixes.

Supported Address Formats

Currently Implemented

P2PKH (Pay-to-Public-Key-Hash): Original Bitcoin address format

  • Mainnet prefix: '1' (version byte 0x00)
  • Testnet prefix: 'm' or 'n' (version byte 0x6F)
  • Example: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

Future Support (Planned)

  • P2SH (Pay-to-Script-Hash): Multisig and complex scripts
  • P2WPKH (Pay-to-Witness-Public-Key-Hash): Native SegWit
  • P2WSH (Pay-to-Witness-Script-Hash): Native SegWit scripts
  • P2TR (Pay-to-Taproot): Taproot addresses with Schnorr signatures

Type Safety

The library leverages Rust's type system to provide compile-time guarantees:

use btcaddr::address::Address;
use btcaddr::address::types::{P2PKH, P2SH};

let p2pkh: Address<P2PKH> = /* ... */;
let p2sh: Address<P2SH> = /* ... */;

// Compile error: mismatched types!
// let wrong: Address<P2PKH> = p2sh;

Address type markers (P2PKH, P2SH, etc.) are zero-sized types that exist only at compile time, providing type safety with zero runtime cost.

Performance Characteristics

The library is optimized for high-performance applications like vanity address generation:

  • Zero heap allocations in the critical path (key generation → address)
  • Inline functions throughout for aggressive optimization
  • Stack-allocated fixed-size arrays for deterministic performance
  • No virtual dispatch - all polymorphism is compile-time

Typical performance on modern hardware (3+ GHz CPU):

  • HASH160 computation: ~100-300 nanoseconds
  • Address generation: ~150-500 nanoseconds
  • Base58 encoding: ~5-10 microseconds

Cryptographic Dependencies

This library relies on battle-tested cryptographic implementations:

  • secp256k1 (v0.31.1): Bitcoin's elliptic curve implementation
  • sha2 (v0.10.9): SHA-256 cryptographic hash function
  • ripemd (v0.1.3): RIPEMD-160 hash function
  • hmac (v0.12.1): HMAC (Hash-based Message Authentication Code)
  • zeroize (v1.8.2): Secure memory zeroization
  • bs58 (v0.5.1): Base58 encoding/decoding
  • rand (v0.9.2): Random number generation (using OsRng)

Bitcoin Improvement Proposals (BIPs)

This library implements or is compatible with the following BIPs:

  • BIP32: Hierarchical Deterministic Wallets
  • BIP13: Address Format for pay-to-script-hash (future)
  • BIP16: Pay to Script Hash (future)
  • BIP141: Segregated Witness (future)
  • BIP173: Base32 address format for native v0-16 witness outputs (future)

Thread Safety

All public types are Send + Sync when appropriate:

  • Entropy: Send (not Sync - interior mutability)
  • Seed: Send + Sync
  • Address<T>: Send + Sync
  • Network: Copy + Send + Sync

This makes the library suitable for concurrent vanity address generation and parallel key derivation.

Error Handling

This library uses Rust's Result type for error handling:

  • Entropy::new() returns Result<Entropy, rand::Error> (CSPRNG failure)
  • Seed::secret_key() returns Result<SecretKey, secp256k1::Error> (invalid key)

In practice, these errors are extremely rare (probability < 1 in 2^127) when using proper CSPRNG. They exist to handle edge cases and maintain API safety.

Examples

Check out the examples directory for more comprehensive examples:

  • Basic address generation
  • Batch address generation
  • Vanity address searching

Documentation

Full API documentation is available on docs.rs.

For more details on the implementation and design decisions, see the extensive inline documentation in the source code.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Guidelines

  • Follow Rust best practices and idiomatic code
  • Maintain comprehensive documentation
  • Add tests for new functionality
  • Ensure all tests pass with cargo test
  • Run cargo clippy and address any warnings
  • Format code with cargo fmt

Security

This library handles cryptographic key material. If you discover a security vulnerability, please email the maintainers directly instead of using the public issue tracker.

References

Acknowledgments

This library follows Bitcoin protocol specifications and builds upon the excellent work of:

  • The Bitcoin Core development team
  • The rust-bitcoin community
  • The secp256k1 library maintainers
  • All contributors to Bitcoin Improvement Proposals