btc-keygen
Minimal offline Bitcoin key generator for cold storage.
What it does
Generates a Bitcoin private key and its corresponding native SegWit (Bech32) address in a single execution. Prints both to stdout, keeps no state, and exits. Designed to run on an air-gapped machine for cold storage key ceremonies.
$ btc-keygen generate
address: bc1q...
wif: K...
Every run creates a new keypair. The tool does not store secrets. If you lose the output, there is no way to recover the key.
Features
- Cryptographically secure randomness from the OS
- secp256k1 validation using Bitcoin Core's libsecp256k1
- Compressed public keys, native SegWit (Bech32) addresses
- WIF private key export
- Optional hex and public key output
- JSON output for scripting
- Secret buffers are zeroized in memory when dropped
- Zero network code, fully offline
- Automated tests including known-answer vectors from the Bitcoin wiki
- Cross-platform: Linux, macOS, Windows, BSDs
Library usage
Add to your project:
let key = generate?;
let wif = encode_wif;
let pubkey = derive_pubkey;
let address = derive_address;
println!;
println!; // exposure is explicit and copies escape here
| Function | Input | Output |
|---|---|---|
generate() |
(none) | Result<PrivateKey, Error> |
PrivateKey::from_bytes(bytes) |
[u8; 32] |
Result<PrivateKey, Error> (validated scalar) |
PrivateKey::from_hex(hex) |
&str (64 hex chars) |
Result<PrivateKey, Error> (validated scalar) |
key.to_hex() |
&PrivateKey |
SecretKeyHex (64 hex ASCII bytes) |
encode_wif(&key) |
&PrivateKey |
SecretWif (52 Base58 ASCII bytes) |
derive_pubkey(&key) |
&PrivateKey |
[u8; 33] (compressed public key) |
derive_address(&pubkey) |
&[u8; 33] |
String (Bech32 address, bc1q...) |
Secret material never leaves the library as a String. SecretWif and
SecretKeyHex zeroize on drop, redact their Debug output, and cannot be
cloned, copied, or printed with {}; read them with expose_bytes() or
expose_str(). PrivateKey zeroizes its bytes when dropped.
Erasure covers the buffers the library owns. It does not reach copies you ask
for via as_bytes(), to_secret_key(), or an expose_* method, memory the OS
moved to swap or a crash dump, or the stack libsecp256k1 uses while deriving a
public key. See what we cannot erase for the
full list. Full API docs at
docs.rs/btc-keygen.
Install (CLI)
Download a pre-built binary from the latest release, verify the SHA256 checksum, and run it.
Or build from source:
Requires Rust and a C compiler.
Usage
# Import your own 64-character hex private key instead of using OS entropy.
# Read it from stdin so the key never appears in the process arguments:
# Accepted, but avoid it: a key passed as an argument is saved to your shell
# history and is visible to `ps` while the command runs. The tool warns when
# you do this, and it cannot undo either exposure.
Note that echo $HEX | btc-keygen generate --from-hex - still records the key
in your shell history, because the shell logs the whole pipeline. Read from a
file or type the key at the prompt.
Security
This tool is designed for air-gapped cold storage key generation. See the website for a plain-language explanation, or the docs/ directory for the full threat model, security assumptions, and dependency analysis.
License
Licensed under the GNU General Public License v3.0 or later.
Versions 0.0.1–0.0.5 were released under MIT OR Apache-2.0; those releases
remain available under those terms. Version 0.1.0 onward is GPL-3.0-or-later.