openadp-ocrypt

Crates.ioopenadp-ocrypt
lib.rsopenadp-ocrypt
version0.1.3
created_at2025-06-29 04:50:50.740742+00
updated_at2025-07-01 09:52:38.141714+00
descriptionRust SDK for OpenADP - Distributed secret sharing and advanced data protection
homepagehttps://openadp.org
repositoryhttps://github.com/openadp/openadp
max_upload_size
id1730347
size293,582
Bill (waywardgeek)

documentation

https://docs.rs/openadp-ocrypt

README

OpenADP Rust SDK

A complete Rust implementation of the OpenADP (Open Advanced Data Protection) distributed secret sharing system, designed to protect against nation-state attacks.

Features

  • Ed25519 elliptic curve operations with point compression/decompression
  • Shamir secret sharing with threshold recovery
  • Noise-NK protocol for secure server communication
  • JSON-RPC 2.0 API with multi-server support
  • Cross-language compatibility with Go and Python implementations
  • High-level key generation API for file encryption
  • Simple ocrypt API for password hashing replacement
  • Automatic server discovery from registry
  • Load balancing across multiple servers
  • Guess limiting and rate limiting protection
  • Two-phase commit backup refresh

Installation

Add this to your Cargo.toml:

[dependencies]
openadp-ocrypt = "0.1.0"
tokio = { version = "1.0", features = ["full"] }

Quick Start

High-Level Key Generation API

use openadp_ocrypt::{generate_encryption_key, recover_encryption_key, get_servers};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get live servers from registry
    let servers = get_servers("").await?;
    
    // Generate encryption key with distributed backup
    let result = generate_encryption_key(
        "document.pdf",
        "secure_password",
        "user@example.com",
        10, // max_guesses
        0,  // expiration (0 = never)
        servers,
    ).await?;
    
    if let Some(key) = result.encryption_key {
        println!("Generated {}-byte encryption key", key.len());
        
        // Later: recover the key
        let recovered = recover_encryption_key(
            "document.pdf",
            "secure_password", 
            "user@example.com",
            result.server_infos.unwrap(),
            result.threshold.unwrap(),
            result.auth_codes.unwrap(),
        ).await?;
        
        if let Some(recovered_key) = recovered.encryption_key {
            assert_eq!(key, recovered_key);
            println!("Successfully recovered key!");
        }
    }
    
    Ok(())
}

Simple Ocrypt API (Password Hashing Replacement)

Replace bcrypt, scrypt, Argon2, or PBKDF2 with distributed threshold cryptography:

use openadp_ocrypt::{register, recover};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Protect a Stripe API key (example - not a real key)
    let api_key = b"sk_live_EXAMPLE_NOT_REAL_KEY_FOR_DEMO_PURPOSES_ONLY_123456789";
    
    // Register with distributed protection
    let metadata = register(
        "payment_service",    // user_id
        "ecommerce_platform", // app_id
        api_key,              // long_term_secret
        "admin_pin_2024",     // pin
        5,                    // max_guesses
        "",                   // servers_url (empty = default registry)
    ).await?;
    
    // Store metadata with user record in database
    println!("Store metadata ({} bytes) with user record", metadata.len());
    
    // Later: recover the API key with automatic backup refresh
    let (recovered_key, remaining_guesses, updated_metadata) = recover(
        &metadata,
        "admin_pin_2024",
        "",
    ).await?;
    
    assert_eq!(api_key, recovered_key.as_slice());
    println!("Recovered API key! Remaining guesses: {}", remaining_guesses);
    
    // Update database if backup was refreshed
    if updated_metadata != metadata {
        println!("Update database with refreshed metadata");
    }
    
    Ok(())
}

Core Components

Cryptographic Operations

use openadp_ocrypt::{hash_to_point, point_compress, derive_enc_key};

// Hash-to-point function H(uid, did, bid, pin)
let point = hash_to_point(
    b"user@example.com",
    b"device123", 
    b"backup456",
    b"pin"
)?;

// Compress point to 32 bytes
let compressed = point_compress(&point)?;

// Derive encryption key from point
let key = derive_enc_key(&point)?;

Client Communication

use openadp_ocrypt::{OpenADPClient, EncryptedOpenADPClient, ServerInfo};

// Basic client (no encryption)
let client = OpenADPClient::new("https://server.openadp.org:8443".to_string(), 30);
client.ping().await?;

// Encrypted client with Noise-NK
let public_key = Some(parse_server_public_key("ed25519:..."))?;
let mut encrypted_client = EncryptedOpenADPClient::new(
    "https://secure.openadp.org:8443".to_string(),
    public_key,
    30
);

// Get server information
let info = encrypted_client.get_server_info().await?;
println!("Server version: {}", info.server_version);

Server Discovery

use openadp_ocrypt::{get_servers, discover_servers};

// Get servers from default registry
let servers = get_servers("").await?;

// Use custom registry
let servers = get_servers("https://custom.registry.com/servers.json").await?;

// Discover with fallback
let servers = discover_servers("").await?; // Falls back to hardcoded servers

Use Cases

1. API Key Protection

Replace database storage of API keys with distributed protection:

// Instead of storing API keys in database:
// database.store("user123", "stripe_key", "sk_live_...");

// Use OpenADP distributed protection:
let metadata = register("user123", "stripe", api_key, user_pin, 5, "").await?;
database.store("user123", "stripe_metadata", &metadata);

// Recovery:
let metadata = database.get("user123", "stripe_metadata");
let (api_key, _, updated_metadata) = recover(&metadata, user_pin, "").await?;

2. File Encryption

Generate encryption keys with distributed backup:

let servers = get_servers("").await?;
let result = generate_encryption_key(
    "financial_report.pdf",
    "user_password",
    "alice@company.com", 
    10, 0, servers
).await?;

// Use key for AES-256-GCM file encryption
let key = result.encryption_key.unwrap();
encrypt_file("financial_report.pdf", &key)?;

3. Private Key Protection

Protect Ed25519/RSA private keys:

let private_key = generate_ed25519_key();
let metadata = register(
    "alice@company.com",
    "document_signing",
    &private_key.to_bytes(),
    "secure_pin",
    10,
    ""
).await?;

// Later: recover for signing
let (recovered_key, _, _) = recover(&metadata, "secure_pin", "").await?;
let signing_key = SigningKey::from_bytes(&recovered_key)?;

4. Database Encryption

Protect database master keys:

let master_key = generate_random_key();
let metadata = register(
    "database_service",
    "production_db",
    &master_key,
    "db_admin_pin",
    3, // Strict limit for production
    ""
).await?;

// Store metadata in secure configuration
config.set("db_master_key_metadata", metadata);

Architecture

Distributed Secret Sharing

  1. Secret Generation: Random 256-bit secret s
  2. Point Computation: U = H(uid, did, bid, pin)
  3. Shamir Sharing: Split s into n shares with t threshold
  4. Server Registration: Store shares (i, s_i, U) on distributed servers
  5. Key Derivation: Final key = derive_key(s * U)

Threshold Recovery

  1. Point Computation: U = H(uid, did, bid, pin)
  2. Share Recovery: Retrieve t shares from servers
  3. Secret Reconstruction: Lagrange interpolation to recover s
  4. Key Derivation: Compute final key from s * U

Security Properties

  • Nation-state resistant: Requires compromise of t-of-n servers
  • Guess limiting: Wrong PIN attempts tracked across all servers
  • Forward security: Backup refresh changes all server state
  • No single point of failure: Distributed across multiple jurisdictions

Error Handling

use openadp_ocrypt::{OpenADPError, Result};

match register("user", "app", secret, "pin", 10, "").await {
    Ok(metadata) => println!("Success!"),
    Err(OpenADPError::Network(e)) => println!("Network error: {}", e),
    Err(OpenADPError::NoServers) => println!("No servers available"),
    Err(OpenADPError::InvalidInput(msg)) => println!("Invalid input: {}", msg),
    Err(OpenADPError::Authentication(msg)) => println!("Auth failed: {}", msg),
    Err(e) => println!("Other error: {}", e),
}

Testing

Run the test suite:

cargo test

Run examples:

# Basic usage
cargo run --example basic_usage

# API key protection
cargo run --example api_key_protection

# Full OpenADP demo
cargo run --example full_openadp_demo

Cross-Language Compatibility

The Rust SDK is fully compatible with:

  • Go SDK: ../ocrypt (separate git repository)
  • Python SDK: ../python/openadp/
  • JavaScript SDK: ../javascript/openadp/

All implementations use the same:

  • Cryptographic primitives (Ed25519, SHA-256, HKDF)
  • JSON-RPC 2.0 protocol
  • Server registry format
  • Metadata structure

Production Deployment

Server Configuration

// Use custom server registry for production
let servers = get_servers("https://your-registry.com/servers.json").await?;

// Or specify servers directly
let servers = vec![
    ServerInfo {
        url: "https://server1.your-domain.com:8443".to_string(),
        public_key: "ed25519:...".to_string(),
        country: "US".to_string(),
    },
    // ... more servers
];

Security Considerations

  1. Server Selection: Use servers in different jurisdictions
  2. Threshold Setting: Recommend t = ⌊n/2⌋ + 1 for n servers
  3. Guess Limits: Use low limits (3-10) for production secrets
  4. Backup Refresh: Implement automatic refresh on recovery
  5. Key Rotation: Periodically re-register secrets with new backup IDs

Monitoring

// Monitor server health
for server in &servers {
    match client.ping().await {
        Ok(_) => println!("✅ {} is healthy", server.url),
        Err(e) => println!("❌ {} is down: {}", server.url, e),
    }
}

// Check remaining guesses
let (_, remaining, _) = recover(&metadata, pin, "").await?;
if remaining < 3 {
    alert!("Low remaining guesses: {}", remaining);
}

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: cargo test
  5. Submit a pull request

License

Licensed under either of:

at your option.

Security

For security issues, please email security@openadp.org instead of using the issue tracker.

Commit count: 0

cargo fmt