Concepts

Key Management

Cloak uses a dual-key system with separate spending and viewing capabilities, plus delegated viewing keys for watch-only access.

Dual-key system

Every stealth meta-address contains two Ed25519 keypairs with distinct roles:

Spending Key (s, S)

Used to sign transactions and spend funds from stealth addresses. This key must be kept secret and should never be shared. Derived with domain separation: solana-stealth-spending-v1

Viewing Key (v, V)

Used to detect incoming payments by computing ECDH shared secrets with ephemeral keys. Can be delegated for watch-only wallets. Derived with domain separation: solana-stealth-viewing-v1

Meta-address format

The public meta-address is encoded as:

stealth1:sol:<spending_pubkey_hex>:<viewing_pubkey_hex>

The stealth1 prefix identifies the protocol version. Only the public keys are shared — private keys never leave the owner's device.

Key generation

generate.rs
rust
use cloak_sdk::StealthMetaAddress;

// Generate a new identity with cryptographically random keys
let meta = StealthMetaAddress::generate();

// Save to file (JSON format, contains private keys)
meta.save_to_file("~/.cloak/keys.json")?;

// Load from file
let meta = StealthMetaAddress::load_from_file("~/.cloak/keys.json")?;

// Get the shareable public address
let public_addr = meta.to_public_string();
println!("{}", public_addr);
// → "stealth1:sol:abc123...:def456..."

Viewing key delegation

You can export a viewing key to enable watch-only wallets. A viewing key can detect incoming payments but cannot spend funds.

viewing_key.rs
rust
use cloak_sdk::{ViewingKey, ViewingKeyScanner};

// Create a viewing key from the meta-address
let vk = ViewingKey::from_meta_address(&meta);

// Or with a label for organization
let vk = ViewingKey::from_meta_address_with_label(&meta, "accounting");

// Export for sharing
vk.save_to_file("viewing-key.json")?;
let vk_string = vk.to_string();
// → "viewkey1:..."

// Import and create a watch-only scanner
let vk = ViewingKey::from_string(&vk_string)?;
let scanner = ViewingKeyScanner::new(&vk);
// Can detect payments but CANNOT derive spending keys

Key storage

Keys are stored in JSON format:

keys.json
json
{
  "spending_key": "...",
  "viewing_key": "...",
  "spending_pubkey": "...",
  "viewing_pubkey": "..."
}

Best practices

  • Backup your keys — If you lose your spending key, funds in stealth addresses are permanently lost.
  • Set file permissions — Use chmod 600 on key files to prevent unauthorized access.
  • Use viewing keys for monitoring — Delegate viewing keys to services that need to detect payments without spending capability.
  • Never share spending keys — Only share the public meta-address or viewing keys.
  • Use the CLI for key managementcloak init, cloak export, cloak import, cloak export-view-key