Skip to main content

kobe_primitives/
lib.rs

1//! Kobe core primitives — the foundation of every chain crate.
2//!
3//! This crate owns the type system shared by every `kobe-<chain>` crate:
4//! the [`Wallet`] entry point, the [`Derive`] / [`DeriveExt`] traits, the
5//! typed [`DerivedPublicKey`] enum, the unified [`DeriveError`], and the
6//! BIP-32 / SLIP-10 / Camouflage primitives that chain crates compose.
7//!
8//! # Module map
9//!
10//! ```text
11//!                        Wallet                (mnemonic + 64-byte BIP-39 seed)
12//!                    ┌─────┴─────┐
13//!    derive_secp256k1│           │  derive_ed25519
14//!                    ▼           ▼
15//!    bip32::DerivedSecp256k1Key     slip10::DerivedEd25519Key
16//!                    │           │
17//!    used by BTC / EVM /         │  used by Solana / Sui /
18//!     Cosmos / Tron / Spark /    │  Aptos / TON
19//!     Fil / XRPL / Nostr         │
20//!                    └─────┬─────┘
21//!                          ▼
22//!                   DerivedAccount  ─◄── every chain wraps this
23//!                   (path + sk + pk + address)
24//! ```
25//!
26//! [`camouflage`] is an orthogonal utility (entropy-layer XOR encryption
27//! that turns one BIP-39 mnemonic into another) gated behind its own feature.
28//!
29//! # Zeroize policy
30//!
31//! Every sensitive byte string is wiped when dropped:
32//!
33//! - [`Wallet`] — zeroizes the mnemonic and the 64-byte seed.
34//! - [`DerivedAccount::private_key_bytes`] / [`private_key_hex`][`DerivedAccount::private_key_hex`]
35//!   — hand out `&Zeroizing<…>` or `Zeroizing<…>` copies.
36//! - [`bip32::DerivedSecp256k1Key`] / [`slip10::DerivedEd25519Key`] —
37//!   zeroize their signing key material, chain code, and every byte view.
38//! - [`camouflage::encrypt`] / [`camouflage::decrypt`] — return `Zeroizing<String>`.
39//!
40//! Public keys and on-chain addresses are **not** zeroized: by design they
41//! carry no secret material.
42//!
43//! # `no_std` surface
44//!
45//! | Feature           | Needs `alloc` | Purpose                                |
46//! | ----------------- | :-----------: | -------------------------------------- |
47//! | `std`  (default)  |       ✔       | `std::error::Error`, OS RNG            |
48//! | `alloc`           |       ✔       | [`Wallet`], [`DerivedAccount`], [`mnemonic`] |
49//! | `bip32`           |       ✔       | [`bip32::DerivedSecp256k1Key`]         |
50//! | `slip10`          |       ✔       | [`slip10::DerivedEd25519Key`]          |
51//! | `encoding`        |       ✔       | [`encoding`] (`hash160` / `Base58Check`) |
52//! | `camouflage`      |       ✔       | [`camouflage`] (PBKDF2 XOR helpers)    |
53//! | `raw-seed`        |       ✔\*     | [`Wallet::seed`] escape hatch (off by default) |
54//! | `rand` / `rand_core` |     ✔       | [`Wallet::generate`]                   |
55//! | `test-vectors`    |       ✗       | Re-export of canonical BIP-39 fixtures |
56//!
57//! \*`raw-seed` needs `alloc` (via the `Wallet` type) but adds no extra crates.
58//!
59//! Only [`DeriveError`] and [`test_vectors`] compile in pure `no_std`
60//! without `alloc`. Everything else requires at least `alloc`.
61//!
62//! # Quick tour
63//!
64//! ```no_run
65//! use kobe_primitives::Wallet;
66//!
67//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
68//! // 1. Build a wallet from a BIP-39 mnemonic:
69//! let wallet = Wallet::from_mnemonic(
70//!     "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
71//!     None,
72//! )?;
73//!
74//! // 2. Derive secp256k1 / Ed25519 keys at BIP-32 / SLIP-10 paths
75//! //    (enable the `bip32` / `slip10` features):
76//! # #[cfg(feature = "bip32")]
77//! assert_eq!(wallet.derive_secp256k1("m/44'/60'/0'/0/0")?.compressed_pubkey().len(), 33);
78//! # #[cfg(feature = "slip10")]
79//! assert_eq!(wallet.derive_ed25519("m/44'/501'/0'/0'")?.public_key_bytes().len(), 32);
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! For chain-specific derivation (Bitcoin addresses, Ethereum checksummed
85//! addresses, Solana keypairs, etc.), reach for the matching chain crate
86//! (`kobe-btc`, `kobe-evm`, `kobe-svm`, …) via the [`kobe`] umbrella crate.
87//!
88//! [`kobe`]: https://docs.rs/kobe
89
90#![cfg_attr(not(feature = "std"), no_std)]
91// `proptest` is a workspace dev-dependency used only by the integration
92// tests under `tests/`. Library-test compilation triggers rustc's
93// `unused_crate_dependencies` lint; suppress it for test builds only so
94// production compilation still enforces the lint.
95#![cfg_attr(
96    test,
97    allow(
98        unused_crate_dependencies,
99        reason = "proptest is only referenced by the tests/ integration binary"
100    )
101)]
102
103#[cfg(feature = "alloc")]
104extern crate alloc;
105
106#[cfg(feature = "alloc")]
107mod derive;
108mod error;
109#[cfg(feature = "alloc")]
110mod style;
111#[cfg(feature = "alloc")]
112mod wallet;
113
114#[cfg(feature = "bip32")]
115pub mod bip32;
116#[cfg(feature = "camouflage")]
117pub mod camouflage;
118#[cfg(feature = "encoding")]
119pub mod encoding;
120#[cfg(feature = "alloc")]
121pub mod mnemonic;
122#[cfg(feature = "slip10")]
123pub mod slip10;
124
125pub use bip39::Language;
126#[cfg(feature = "rand_core")]
127pub use bip39::rand_core;
128#[cfg(feature = "alloc")]
129pub use derive::{
130    Derive, DeriveExt, DerivedAccount, DerivedPublicKey, PublicKeyKind, derive_range,
131};
132pub use error::DeriveError;
133#[cfg(feature = "alloc")]
134pub use style::{DerivationStyle, ParseDerivationStyleError};
135#[cfg(feature = "alloc")]
136pub use wallet::Wallet;
137
138/// Convenient Result alias.
139pub type Result<T> = core::result::Result<T, DeriveError>;
140
141/// Well-known BIP-39 / SLIP-10 test vectors, exposed for downstream test suites.
142///
143/// Gated on the `test-vectors` feature so they do **not** ship with the
144/// default binary/`lib` build. The module contains only `&'static str`
145/// constants and is available in `no_std + no_alloc` environments.
146#[cfg(feature = "test-vectors")]
147pub mod test_vectors {
148    /// All-zero 128-bit entropy — yields the canonical BIP-39 test mnemonic
149    /// (`"abandon abandon … about"`). Cross-verified against the BIP-39
150    /// reference implementations and `iancoleman.io/bip39`.
151    pub const MNEMONIC_ABANDON: &str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
152
153    /// 64-byte BIP-39 seed derived from [`MNEMONIC_ABANDON`] with an empty
154    /// passphrase, lowercase hex.
155    pub const SEED_HEX_ABANDON: &str = "5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4";
156}