Multi-chain transaction signer built on mature cryptography libraries — zero hand-rolled crypto, and a batteries-included CLI.
signer provides thin wrappers around battle-tested signing libraries (alloy for EVM, bitcoin for BTC, ed25519-dalek for Solana), exposing a unified API while delegating all cryptographic operations to upstream crates. All signers Deref to their underlying types for full API access, and private keys are zeroed on drop. Optional kobe integration enables seamless HD wallet bridging.
| Crate | Description | |
|---|---|---|
signer |
Umbrella crate — re-exports all chain signers | |
signer-btc |
Bitcoin — ECDSA, Schnorr, PSBT, BIP-137 message signing | |
signer-evm |
Ethereum / EVM — EIP-191, EIP-712, transaction signing | |
signer-svm |
Solana / SVM — Ed25519 signing | |
signer-cli |
CLI tool — sign, verify, and inspect keys across all supported chains |
Shell (macOS / Linux):
curl -fsSL https://sh.qntx.fun/signer | shPowerShell (Windows):
irm https://sh.qntx.fun/signer/ps | iexOr via Cargo:
cargo install signer-cliuse signer_evm::{Signer, SignerSync};
let signer = Signer::random();
let signature = signer.sign_message_sync(b"hello")?;
println!("Address: {}", signer.address());
println!("Signature: {signature}");use signer_btc::{Signer, Network};
let signer = Signer::random(Network::Bitcoin);
let signature = signer.sign_message("Hello, Bitcoin!")?;
let address = signer.p2wpkh_address(Network::Bitcoin);
let valid = Signer::verify_message("Hello, Bitcoin!", &signature, &address, Network::Bitcoin)?;
println!("Address: {address}");
println!("Valid: {valid}");use signer_svm::Signer;
use ed25519_dalek::Signer as _;
let signer = Signer::random();
let sig = signer.sign(b"hello solana");
signer.verify(b"hello solana", &sig)?;
println!("Address: {}", signer.address());use signer::{evm, btc, svm};
let eth_signer = evm::Signer::random();
let btc_signer = btc::Signer::random(btc::Network::Bitcoin);
let sol_signer = svm::Signer::random();Enable the kobe feature to construct signers from kobe derived keys:
use kobe::Wallet;
use kobe_evm::Deriver;
use signer_evm::Signer;
let wallet = Wallet::from_mnemonic("abandon abandon ... about", None)?;
let deriver = Deriver::new(&wallet);
let derived = deriver.derive(0)?;
let signer = Signer::from_derived(&derived)?;
println!("Address: {}", signer.address());The CLI uses --json for machine-readable output — ideal for agent and script consumption.
signer [--json] <chain> <subcommand> [options]
| Chain | Primary | Aliases |
|---|---|---|
| Bitcoin | btc |
bitcoin |
| Ethereum | evm |
eth, ethereum |
| Solana | svm |
sol, solana |
# BIP-137 message signing (default: Native SegWit)
signer btc sign-message --key "L1a..." --message "Hello, Bitcoin!"
# Sign with specific address type
signer btc sign-message --key "L1a..." --message "test" --address-type legacy
# Verify a signed message
signer btc verify-message --signature "H..." --message "Hello" --address "bc1q..."
# Raw ECDSA / Schnorr hash signing
signer btc sign-ecdsa --key "L1a..." --hash "abcdef..."
signer btc sign-schnorr --key "L1a..." --hash "abcdef..."
# Sign a PSBT (base64 in → base64 out)
signer btc sign-psbt --key "L1a..." --psbt "cHNidP8B..."
# Show all address types for a key
signer btc address --key "L1a..."# EIP-191 personal_sign
signer evm sign-message --key "0xabc..." --message "Hello, Ethereum!"
# Raw hash signing
signer evm sign-hash --key "0xabc..." --hash "0xdef..."
# Sign a raw unsigned transaction (hex-encoded EIP-2718 bytes)
signer evm sign-transaction --key "0xabc..." --tx "0x02f8..."
# Verify a signed message
signer evm verify-message --signature "0x..." --message "Hello" --address "0x..."
# Show address and public key
signer evm address --key "0xabc..."# Ed25519 signing
signer svm sign --key "deadbeef..." --message "Hello, Solana!"
# Sign hex-encoded bytes (e.g., serialized transaction)
signer svm sign --key "deadbeef..." --message "0a0b0c..." --hex
# Verify a signature
signer svm verify --signature "abcdef..." --message "Hello" --pubkey "Base58Address..."
# Show address and public key
signer svm address --key "deadbeef..."Pass --json before the chain subcommand. All output (including errors) becomes a single JSON object on stdout with no ANSI colors.
signer --json btc sign-message --key "L1a..." --message "test"{
"chain": "bitcoin",
"operation": "BIP-137 message",
"address": "bc1q...",
"signature": "H...",
"message": "test"
}Errors in JSON mode return exit code 1 with {"error": "..."}.
- Zero hand-rolled crypto — All signing delegated to audited upstream libraries
- Thin wrappers —
Derefto underlying types (PrivateKey,PrivateKeySigner,SigningKey) for full API access - Memory safety — Private keys zeroed on drop (
ZeroizeOnDrop/non_secure_erase) - Multi-chain — EVM, Bitcoin, Solana from one workspace
- Kobe integration — Optional HD wallet bridging via feature flag
- CSPRNG — Random generation via OS-provided entropy (
getrandom) - Linting —
pedantic+nursery+correctness(deny) — strict Clippy across workspace - Edition — Rust 2024
| Method | Standard |
|---|---|
sign_hash_sync / sign_hash |
Raw 32-byte hash |
sign_message_sync / sign_message |
EIP-191 personal_sign |
sign_typed_data_sync / sign_typed_data |
EIP-712 (via alloy) |
sign_transaction_sync / sign_transaction |
All EVM transaction types |
| Method | Standard |
|---|---|
sign_ecdsa |
secp256k1 ECDSA |
sign_schnorr |
BIP-340 Schnorr (Taproot) |
sign_message / sign_message_with_type |
BIP-137 (P2PKH, P2SH-P2WPKH, P2WPKH) |
verify_message |
BIP-137 verification |
sign_psbt |
PSBT (with Bip32Derivation support) |
p2wpkh_address / p2tr_address / ... |
All address types (P2WPKH, P2TR, P2SH-P2WPKH, P2PKH) |
| Method | Standard |
|---|---|
sign (via Deref) |
Ed25519 signature |
verify |
Ed25519 verification |
sign_transaction_message |
Solana transaction signing |
keypair_base58 |
Phantom / Backpack / Solflare format |
| Crate | Feature | Description |
|---|---|---|
signer |
btc |
Enable Bitcoin signer (default) |
signer |
evm |
Enable EVM signer (default) |
signer |
svm |
Enable Solana signer (default) |
signer |
kobe |
Enable kobe HD wallet bridging for all chains |
signer-* |
kobe |
Enable kobe bridging for a specific chain |
This library has not been independently audited. Use at your own risk.
- All cryptographic operations are delegated to upstream libraries
- Private keys are zeroed from memory on drop (EVM/SVM via
ZeroizeOnDrop, BTC vianon_secure_erase) - Review the security advisories of upstream dependencies
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.