| Crates.io | kiwavi |
| lib.rs | kiwavi |
| version | 0.1.1 |
| created_at | 2025-08-19 09:38:21.78372+00 |
| updated_at | 2025-09-05 10:01:56.403583+00 |
| description | A secure TOTP-based key derivation system using user salts |
| homepage | |
| repository | https://github.com/aibunny/kiwavi |
| max_upload_size | |
| id | 1801641 |
| size | 29,416 |
A secure TOTP-based key derivation system that generates deterministic values from user salts without storing sensitive data in plaintext.
Kiwavi is perfect for:
Kiwavi accepts various salt formats for maximum flexibility:
// 32-byte arrays from crypto.getRandomValues() - zero-copy
let prf_salt: [u8; 32] = get_from_webauthn_prf(); // Your WebAuthn PRF salt
let kiwavi = Kiwavi::from_prf_salt(prf_salt, app_config)?;
// Or any byte slice/vector
let salt_bytes: &[u8] = &your_binary_salt;
let kiwavi = Kiwavi::new(salt_bytes, app_config)?;
// Hex strings (common format) - minimal parsing overhead
let kiwavi = Kiwavi::from_hex("a1b2c3d4...", app_config)?;
// Direct Vec<u8>
let kiwavi = Kiwavi::new(your_salt_vec, app_config)?;
// String salts - require UTF-8 processing
let kiwavi = Kiwavi::new("user_salt_string", app_config)?;
Add Kiwavi to your Cargo.toml:
[dependencies]
kiwavi = "0.1.0"
use kiwavi::{Kiwavi, AppConfig};
// Create app configuration
let app_config = AppConfig::new("YourApp", "some-user@example.com");
// Initialize Kiwavi with user's unique salt
let kiwavi = Kiwavi::new("user_unique_salt_123", app_config)?;
// Generate QR code for user to scan with authenticator app
println!("Setup URL: {}", kiwavi.get_setup_qr());
// Validate TOTP and get derived value
let result = kiwavi.validate_and_derive("123456");
match result {
ValidationResult::Success(value) => {
println!("Correct! Derived value: {}", result.hex());
// Use the 32-byte value for encryption keys, etc.
}
ValidationResult::Invalid(wrong_value) => {
println!("Wrong TOTP code. Got: {}", result.hex());
// This is a different, deterministic wrong value
}
}
use kiwavi::{Kiwavi, AppConfig};
// User's WebAuthn PRF salt (from your existing system)
let webauthn_prf_salt = "user_webauthn_salt_from_db";
// Create Kiwavi backup for this user
let app_config = AppConfig::new("MyWallet", "some-user@example.com");
let backup_kiwavi = Kiwavi::new(webauthn_prf_salt, app_config)?;
// User sets up TOTP during onboarding
println!("Backup recovery setup: {}", backup_kiwavi.get_setup_qr());
// Later, when user needs recovery access:
let totp_code = "734521"; // From their authenticator app
let result = backup_kiwavi.validate_and_derive(totp_code);
if result.is_valid() {
// This derived value can be used as the WebAuthn PRF salt
let recovered_salt = result.value();
// Now decrypt private keys using this salt...
}
KiwaviThe main struct for TOTP-based key derivation.
new(user_salt: &str, app_config: AppConfig) -> Result<Self, KiwaviError>
validate_and_derive(&self, totp_code: &str) -> ValidationResult
get_setup_qr(&self) -> String
preview_derived_value(&self) -> String
AppConfigConfiguration for your application.
let config = AppConfig::new("YourApp", "some-user@example.com");
// or with custom issuer
let config = AppConfig::with_issuer("YourApp", "some-user@example.com", "MyCompany");
ValidationResultResult of TOTP validation:
Success([u8; 32]) - TOTP was correctInvalid([u8; 32]) - TOTP was wrong (contains different deterministic value)value(&self) -> [u8; 32] - Get the 32-byte valuehex(&self) -> String - Get value as uppercase hex stringis_valid(&self) -> bool - Check if TOTP was correctTraditional TOTP just validates codes. Kiwavi goes further by:
This makes it perfect for backup systems, key derivation, and recovery mechanisms where you need more than just "yes/no" validation.
Licensed under either of:
at your option.