kiwavi

Crates.iokiwavi
lib.rskiwavi
version0.1.1
created_at2025-08-19 09:38:21.78372+00
updated_at2025-09-05 10:01:56.403583+00
descriptionA secure TOTP-based key derivation system using user salts
homepage
repositoryhttps://github.com/aibunny/kiwavi
max_upload_size
id1801641
size29,416
Bunny (aibunny)

documentation

https://docs.rs/kiwavi

README

Kiwavi

A secure TOTP-based key derivation system that generates deterministic values from user salts without storing sensitive data in plaintext.

Features

  • 🔒 Secure: Never stores derived values or secrets in plaintext memory
  • 🔄 Deterministic: Same salt + app config = same derived value
  • 📱 Standard TOTP: Compatible with Google Authenticator, Authy, etc.
  • 🎯 Unique per User: Different salts produce completely different values
  • ⚡ Zero Dependencies on Storage: All values derived on-demand
  • 🛡️ Wrong Value Protection: Returns believable but wrong values for incorrect TOTP codes

Use Cases

Kiwavi is perfect for:

  • Backup key derivation for WebAuthn/passkey systems
  • Deterministic secret generation from user inputs
  • Recovery mechanisms for encrypted data
  • Multi-factor authentication where you need consistent derived values

Salt Input Guidelines

Kiwavi accepts various salt formats for maximum flexibility:

🚀 Most Efficient (Recommended)

// 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)?;

Good Performance

// 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)?;

🐌 Functional but Slower

// String salts - require UTF-8 processing
let kiwavi = Kiwavi::new("user_salt_string", app_config)?;

Quick Start

Add Kiwavi to your Cargo.toml:

[dependencies]
kiwavi = "0.1.0"

Basic Usage

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
    }
}

WebAuthn Backup Example

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...
}

API Reference

Kiwavi

The main struct for TOTP-based key derivation.

Methods

  • new(user_salt: &str, app_config: AppConfig) -> Result<Self, KiwaviError>
    • Creates new Kiwavi instance from user salt
  • validate_and_derive(&self, totp_code: &str) -> ValidationResult
    • Validates TOTP and returns derived value
  • get_setup_qr(&self) -> String
    • Returns otpauth:// URL for authenticator apps
  • preview_derived_value(&self) -> String
    • Shows what the correct derived value would be (for testing)

AppConfig

Configuration 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");

ValidationResult

Result of TOTP validation:

  • Success([u8; 32]) - TOTP was correct
  • Invalid([u8; 32]) - TOTP was wrong (contains different deterministic value)

Methods

  • value(&self) -> [u8; 32] - Get the 32-byte value
  • hex(&self) -> String - Get value as uppercase hex string
  • is_valid(&self) -> bool - Check if TOTP was correct

Security Properties

✅ What Kiwavi Protects Against

  • Memory dumps: Derived values are never stored, only computed on-demand
  • Storage attacks: No sensitive data in databases or files
  • Brute force: Wrong TOTP codes get believable but useless values
  • Rainbow tables: Each user salt produces unique value space

⚠️ What You Must Protect

  • User salts: Keep these secure and consistent per user
  • TOTP secrets: Users must secure their authenticator apps
  • App configuration: Keep your app name/issuer consistent

Why Kiwavi?

Traditional TOTP just validates codes. Kiwavi goes further by:

  1. Deriving cryptographic values from user salts
  2. Never storing the actual derived values
  3. Producing consistent results for the same user
  4. Generating different values for each user automatically
  5. Providing wrong but believable values for security

This makes it perfect for backup systems, key derivation, and recovery mechanisms where you need more than just "yes/no" validation.

License

Licensed under either of:

  • Apache License, Version 2.0
  • MIT License

at your option.

Commit count: 4

cargo fmt