signer-primitives 1.0.0

Unified signing trait and types for multi-chain transaction signers.
Documentation

Signer

Crates.io Docs.rs CI License Rust

Modular, no_std-compatible Rust toolkit for multi-chain transaction signing — 12 chains, zero hand-written cryptography.

Signer provides thin, secure wrappers around battle-tested cryptographic libraries (k256 for secp256k1 ECDSA and BIP-340 Schnorr, ed25519-dalek for Ed25519), exposing a unified Sign trait across Bitcoin, Ethereum, Solana, Cosmos, Tron, Sui, TON, Filecoin, Spark, XRP Ledger, Aptos, and Nostr. All library crates compile under no_std + alloc and zeroize sensitive material on drop.

Quick Start

Install the CLI

Shell (macOS / Linux):

curl -fsSL https://sh.qntx.fun/signer | sh

PowerShell (Windows):

irm https://sh.qntx.fun/signer/ps | iex

Or via Cargo:

cargo install signer-cli

CLI Usage

# Ethereum — EIP-191 personal_sign
signer evm sign-message -k "0x4c0883a6..." -m "Hello, Ethereum!"

# Bitcoin — message signing
signer btc sign-message -k "4c0883a6..." -m "Hello, Bitcoin!"

# Solana — Ed25519
signer svm sign -k "9d61b19d..." -m "Hello, Solana!"

# Sui — BLAKE2b intent signing
signer sui sign-tx -k "9d61b19d..." -t "0000..."

# Nostr — BIP-340 Schnorr, accepts hex or NIP-19 nsec
signer nostr sign-hash -k "nsec10allq0g..." -x "5e6ea04f..."
signer nostr address  -k "7f7ff03d..."   # prints npub1… and x-only pubkey

# Show address / public key
signer evm address -k "0x4c0883a6..."

# JSON output (for scripts / agents)
signer --json evm sign-message -k "0x4c0883a6..." -m "test"

Library Usage

Every chain exposes the same inherent surface (sign_hash / sign_message / sign_transaction / verify / public_key_hex / address). The unified [SignOutput] enum carries chain-native wire formats with pattern-match accessors — no use signer_primitives::Sign required for everyday work.

use signer_evm::Signer;

let signer = Signer::from_hex("4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318")?;
let out = signer.sign_message(b"hello")?;   // SignOutput::Ecdsa { .., v: 27 | 28 }

println!("Address:   {}", signer.address());
println!("Signature: {}", out.to_hex());     // 65-byte r || s || v, hex-encoded
if let Some(v) = out.v() { println!("v: {v}"); }
use signer_svm::Signer;

let signer = Signer::random();
let out = signer.sign_message(b"hello solana")?;     // SignOutput::Ed25519([u8; 64])
signer.verify(b"hello solana", &out.to_bytes())?;    // inherent verify, &[u8] everywhere

println!("Address: {}", signer.address());

Kobe HD Wallet Integration

Enable the kobe feature to construct signers from kobe 1.0 derived keys:

use kobe::Wallet;
use kobe_evm::Deriver;
use signer_evm::Signer;

let wallet = Wallet::from_mnemonic("abandon abandon ... about", None)?;
let account = Deriver::new(&wallet).derive(0)?;
let signer  = Signer::from_derived(&account)?;
println!("Address: {}", signer.address());

For chains with newtype-wrapped accounts (Bitcoin / Solana), pass the chain-specific account directly:

// Bitcoin: kobe_btc::BtcAccount wraps DerivedAccount + WIF / address type
let account = kobe_btc::Deriver::new(&wallet, kobe_btc::Network::Mainnet)?.derive(0)?;
let signer  = signer_btc::Signer::from_derived(&account)?;

Design

  • 12 chains — Ethereum, Bitcoin, Solana, Cosmos, Tron, Sui, TON, Filecoin, Spark, XRP Ledger, Aptos, Nostr
  • Zero hand-rolled crypto — secp256k1 ECDSA & BIP-340 Schnorr via k256, Ed25519 via ed25519-dalek
  • Type-safe digestssign_hash takes &[u8; 32]; ragged byte slices are rejected at compile time
  • Discriminated SignOutput — enum variants (Ecdsa, EcdsaDer, Ed25519, Ed25519WithPubkey, Schnorr) carry chain-native wire formats; no Option juggling
  • Inherent API parity — every chain Signer exposes canonical sign_hash / sign_message / sign_transaction / verify / public_key_hex directly, with the Sign trait delegating on top
  • no_std + alloc — All library crates compile without std; embedded / WASM ready
  • Security hardenedZeroizeOnDrop, Debug redacted ([REDACTED]), Clone removed, Send + Sync
  • Kobe integration — Optional HD wallet bridging via kobe feature flag
  • CSPRNG — Random generation via OS-provided entropy (getrandom)
  • KAT-verified — Deterministic test vectors (RFC 8032, known secp256k1 keys) for all chains
  • Strict linting — Clippy pedantic + nursery + correctness (deny), zero warnings

Crates

See crates/README.md for the full crate table, dependency graph, and feature flag reference.

Security

This library has not been independently audited. Use at your own risk.

  • Private keys wrapped in ZeroizeOnDrop — zeroed from memory on drop
  • Debug impl outputs [REDACTED] — no key material leaked to logs
  • Clone intentionally removed — prevents uncontrolled key copies
  • Random generation uses OS-provided CSPRNG via getrandom
  • Sign trait requires Send + Sync — safe for concurrent use
  • No key material is logged or persisted

License

Licensed under either of:

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.


A QNTX open-source project.

Code is law. We write both.