| Crates.io | btcaddr |
| lib.rs | btcaddr |
| version | 0.1.0 |
| created_at | 2025-11-23 12:49:37.080057+00 |
| updated_at | 2025-11-23 12:49:37.080057+00 |
| description | Bitcoin address generation |
| homepage | |
| repository | https://codeberg.org/cnfy/btcaddr |
| max_upload_size | |
| id | 1946490 |
| size | 184,322 |
A secure, type-safe, and high-performance Rust library for Bitcoin address generation.
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.
zeroize crateThis library is designed with security as the primary concern:
OsRng, which uses platform-specific secure random sources (/dev/urandom on Linux, getrandom() syscall, etc.)Entropy, Seed) is automatically zeroed when dropped, preventing sensitive data from lingering in memoryAdd btcaddr to your Cargo.toml:
[dependencies]
btcaddr = "0.1.0"
Or use cargo add:
cargo add btcaddr
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"
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);
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'
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
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
addressBitcoin 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 enforcementPublicKeyExt: Extension trait for converting public keys to addressesseedBIP32-compliant seed derivation and key extraction.
Seed: 512-bit seed derived from entropy using HMAC-SHA512generate(): Convenience method that generates entropy and derives seed in one stepsecret_key(): Extracts master secret key (first 256 bits)chain_code(): Extracts chain code for hierarchical key derivation (last 256 bits)entropyCryptographically secure random number generation using OsRng.
Entropy: 512-bit cryptographically secure random datanetworkBitcoin network type definitions (Mainnet, Testnet). Determines address version bytes and prefixes.
P2PKH (Pay-to-Public-Key-Hash): Original Bitcoin address format
1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNaThe 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.
The library is optimized for high-performance applications like vanity address generation:
Typical performance on modern hardware (3+ GHz CPU):
This library relies on battle-tested cryptographic implementations:
This library implements or is compatible with the following BIPs:
All public types are Send + Sync when appropriate:
Entropy: Send (not Sync - interior mutability)Seed: Send + SyncAddress<T>: Send + SyncNetwork: Copy + Send + SyncThis makes the library suitable for concurrent vanity address generation and parallel key derivation.
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.
Check out the examples directory for more comprehensive examples:
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.
This project is licensed under the MIT License - see the LICENSE file for details.
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.
cargo testcargo clippy and address any warningscargo fmtThis library handles cryptographic key material. If you discover a security vulnerability, please email the maintainers directly instead of using the public issue tracker.
This library follows Bitcoin protocol specifications and builds upon the excellent work of: