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 EVM / Cosmos /     │  used by Solana / Sui /
18//!     Tron / Spark / Fil /       │  Aptos / TON
19//!     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//! | `camouflage`      |       ✔       | [`camouflage`] (PBKDF2 XOR helpers)    |
52//! | `rand` / `rand_core` |     ✔       | [`Wallet::generate`]                   |
53//! | `test-vectors`    |       ✗       | Re-export of canonical BIP-39 fixtures |
54//!
55//! Only [`DeriveError`] and [`test_vectors`] compile in pure `no_std`
56//! without `alloc`. Everything else requires at least `alloc`.
57//!
58//! # Quick tour
59//!
60//! ```no_run
61//! use kobe_primitives::Wallet;
62//!
63//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
64//! // 1. Build a wallet from a BIP-39 mnemonic:
65//! let wallet = Wallet::from_mnemonic(
66//!     "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
67//!     None,
68//! )?;
69//!
70//! // 2. Derive secp256k1 / Ed25519 keys at BIP-32 / SLIP-10 paths
71//! //    (enable the `bip32` / `slip10` features):
72//! # #[cfg(feature = "bip32")]
73//! assert_eq!(wallet.derive_secp256k1("m/44'/60'/0'/0/0")?.compressed_pubkey().len(), 33);
74//! # #[cfg(feature = "slip10")]
75//! assert_eq!(wallet.derive_ed25519("m/44'/501'/0'/0'")?.public_key_bytes().len(), 32);
76//! # Ok(())
77//! # }
78//! ```
79//!
80//! For chain-specific derivation (Bitcoin addresses, Ethereum checksummed
81//! addresses, Solana keypairs, etc.), reach for the matching chain crate
82//! (`kobe-btc`, `kobe-evm`, `kobe-svm`, …) via the [`kobe`] umbrella crate.
83//!
84//! [`kobe`]: https://docs.rs/kobe
85
86#![cfg_attr(not(feature = "std"), no_std)]
87// `proptest` is a workspace dev-dependency used only by the integration
88// tests under `tests/`. Library-test compilation triggers rustc's
89// `unused_crate_dependencies` lint; suppress it for test builds only so
90// production compilation still enforces the lint.
91#![cfg_attr(
92    test,
93    allow(
94        unused_crate_dependencies,
95        reason = "proptest is only referenced by the tests/ integration binary"
96    )
97)]
98
99#[cfg(feature = "alloc")]
100extern crate alloc;
101
102#[cfg(feature = "alloc")]
103mod derive;
104mod error;
105#[cfg(feature = "alloc")]
106mod style;
107#[cfg(feature = "alloc")]
108mod wallet;
109
110#[cfg(feature = "bip32")]
111pub mod bip32;
112#[cfg(feature = "camouflage")]
113pub mod camouflage;
114#[cfg(feature = "alloc")]
115pub mod mnemonic;
116#[cfg(feature = "slip10")]
117pub mod slip10;
118
119pub use bip39::Language;
120#[cfg(feature = "rand_core")]
121pub use bip39::rand_core;
122#[cfg(feature = "alloc")]
123pub use derive::{
124    Derive, DeriveExt, DerivedAccount, DerivedPublicKey, PublicKeyKind, derive_range,
125};
126pub use error::DeriveError;
127#[cfg(feature = "alloc")]
128pub use style::{DerivationStyle, ParseDerivationStyleError};
129#[cfg(feature = "alloc")]
130pub use wallet::Wallet;
131
132/// Convenient Result alias.
133pub type Result<T> = core::result::Result<T, DeriveError>;
134
135/// Well-known BIP-39 / SLIP-10 test vectors, exposed for downstream test suites.
136///
137/// Gated on the `test-vectors` feature so they do **not** ship with the
138/// default binary/`lib` build. The module contains only `&'static str`
139/// constants and is available in `no_std + no_alloc` environments.
140#[cfg(feature = "test-vectors")]
141pub mod test_vectors {
142    /// All-zero 128-bit entropy — yields the canonical BIP-39 test mnemonic
143    /// (`"abandon abandon … about"`). Cross-verified against the BIP-39
144    /// reference implementations and `iancoleman.io/bip39`.
145    pub const MNEMONIC_ABANDON: &str = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
146
147    /// 64-byte BIP-39 seed derived from [`MNEMONIC_ABANDON`] with an empty
148    /// passphrase, lowercase hex.
149    pub const SEED_HEX_ABANDON: &str = "5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4";
150}