Skip to content

Column-Level Encryption - Quick Start Guide

5-Minute Setup Guide for HeliosDB Column Encryption

Installation

Column-level encryption is included in HeliosDB by default. No additional installation required.

[dependencies]
heliosdb-encryption = { path = "../heliosdb-encryption" }

Quick Examples

1. Basic Column Encryption (1 minute)

use heliosdb_encryption::column::{
    ColumnEncryptionManager, ColumnConfig,
    crypto_engine::EncryptionAlgorithm,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. Create manager
    let manager = ColumnEncryptionManager::new(None, true).await?;

    // 2. Configure column
    let config = ColumnConfig {
        table_id: "users".to_string(),
        column_name: "email".to_string(),
        algorithm: EncryptionAlgorithm::Aes256Gcm,
        deterministic: false,
        enable_fpe: false,
        fpe_format: None,
    };

    // 3. Enable encryption
    manager.enable_column_encryption(config, None).await?;

    // 4. Encrypt & decrypt
    let plaintext = b"user@example.com";
    let encrypted = manager.encrypt_value("users", "email", plaintext).await?;
    let decrypted = manager.decrypt_value("users", "email", &encrypted).await?;

    assert_eq!(plaintext.as_slice(), decrypted.as_slice());
    Ok(())
}

2. SSN Encryption (Format-Preserving)

use heliosdb_encryption::column::{
    ColumnConfig, ColumnEncryptionManager,
    crypto_engine::EncryptionAlgorithm,
    fpe::DataFormat,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = ColumnEncryptionManager::new(None, true).await?;

    let config = ColumnConfig {
        table_id: "customers".to_string(),
        column_name: "ssn".to_string(),
        algorithm: EncryptionAlgorithm::Aes256Gcm,
        deterministic: false,
        enable_fpe: true,  // Enable FPE
        fpe_format: Some(DataFormat::Ssn),  // SSN format
    };

    manager.enable_column_encryption(config, None).await?;

    let ssn = b"123-45-6789";
    let encrypted = manager.encrypt_value("customers", "ssn", ssn).await?;
    let decrypted = manager.decrypt_value("customers", "ssn", &encrypted).await?;

    // Still looks like SSN after encryption!
    assert_eq!(ssn.as_slice(), decrypted.as_slice());
    Ok(())
}

3. Searchable Encryption (Deterministic)

use heliosdb_encryption::column::{
    ColumnConfig, ColumnEncryptionManager,
    crypto_engine::EncryptionAlgorithm,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = ColumnEncryptionManager::new(None, true).await?;

    let config = ColumnConfig {
        table_id: "users".to_string(),
        column_name: "user_id".to_string(),
        algorithm: EncryptionAlgorithm::Aes256Gcm,
        deterministic: true,  // Enable deterministic
        enable_fpe: false,
        fpe_format: None,
    };

    manager.enable_column_encryption(config, None).await?;

    // Same plaintext = same ciphertext (allows indexing)
    let user_id = b"user12345";
    let enc1 = manager.encrypt_value("users", "user_id", user_id).await?;
    let enc2 = manager.encrypt_value("users", "user_id", user_id).await?;

    assert_eq!(enc1.encrypted.ciphertext, enc2.encrypted.ciphertext);
    Ok(())
}

4. Batch Operations

use heliosdb_encryption::column::{
    ColumnConfig, ColumnEncryptionManager,
    crypto_engine::EncryptionAlgorithm,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = ColumnEncryptionManager::new(None, true).await?;

    let config = ColumnConfig {
        table_id: "logs".to_string(),
        column_name: "message".to_string(),
        algorithm: EncryptionAlgorithm::Aes256Gcm,
        deterministic: false,
        enable_fpe: false,
        fpe_format: None,
    };

    manager.enable_column_encryption(config, None).await?;

    // Encrypt multiple values at once
    let messages = vec![
        b"log1".as_slice(),
        b"log2".as_slice(),
        b"log3".as_slice(),
    ];

    let encrypted = manager.batch_encrypt("logs", "message", &messages).await?;
    let decrypted = manager.batch_decrypt("logs", "message", &encrypted).await?;

    Ok(())
}

5. Key Rotation

use heliosdb_encryption::column::{
    ColumnConfig, ColumnEncryptionManager,
    crypto_engine::EncryptionAlgorithm,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = ColumnEncryptionManager::new(None, true).await?;

    let config = ColumnConfig {
        table_id: "accounts".to_string(),
        column_name: "balance".to_string(),
        algorithm: EncryptionAlgorithm::Aes256Gcm,
        deterministic: false,
        enable_fpe: false,
        fpe_format: None,
    };

    manager.enable_column_encryption(config, None).await?;

    // Encrypt with version 1
    let data = b"1000.00";
    let v1_encrypted = manager.encrypt_value("accounts", "balance", data).await?;

    // Rotate to version 2 (zero downtime!)
    let new_version = manager.rotate_column_key("accounts", "balance").await?;
    println!("Rotated to version: {}", new_version);

    // Can still decrypt v1 data
    let v1_decrypted = manager.decrypt_value("accounts", "balance", &v1_encrypted).await?;
    assert_eq!(data, v1_decrypted.as_slice());

    // New encryptions use v2
    let v2_encrypted = manager.encrypt_value("accounts", "balance", data).await?;

    Ok(())
}

Common Use Cases

Credit Card Encryption

let config = ColumnConfig {
    table_id: "payments".to_string(),
    column_name: "card_number".to_string(),
    algorithm: EncryptionAlgorithm::Aes256Gcm,
    deterministic: false,
    enable_fpe: true,
    fpe_format: Some(DataFormat::CreditCard),
};

Email Encryption (Preserving Domain)

let config = ColumnConfig {
    table_id: "contacts".to_string(),
    column_name: "email".to_string(),
    algorithm: EncryptionAlgorithm::Aes256Gcm,
    deterministic: false,
    enable_fpe: true,
    fpe_format: Some(DataFormat::Email),  // Preserves @domain.com
};

Phone Number Encryption

let config = ColumnConfig {
    table_id: "users".to_string(),
    column_name: "phone".to_string(),
    algorithm: EncryptionAlgorithm::ChaCha20Poly1305,
    deterministic: false,
    enable_fpe: true,
    fpe_format: Some(DataFormat::Phone),
};

Performance Tips

1. Enable Caching

use heliosdb_encryption::column::cache::CacheConfig;

let cache_config = CacheConfig {
    encrypted_cache_size: 10000,  // Increase for read-heavy
    decrypted_cache_size: 5000,
    key_cache_size: 100,
    decrypted_ttl_secs: 300,
    enable_compression: true,
    compression_threshold: 1024,
};

let manager = ColumnEncryptionManager::with_cache_config(
    None, true, cache_config
).await?;

2. Use Batch Operations

// DON'T do this (slow):
for row in rows {
    let encrypted = manager.encrypt_value(table, col, row).await?;
}

// DO this (fast):
let encrypted = manager.batch_encrypt(table, col, &rows).await?;

3. Monitor Performance

let metrics = manager.get_metrics();
println!("Avg encryption: {:.2} μs", metrics.avg_encryption_us);
println!("Cache hit rate: {:.1}%", metrics.cache_hit_rate * 100.0);

// Optimize if:
// - avg_encryption_us > 50 μs (consider caching/batching)
// - cache_hit_rate < 70% (increase cache size)

Algorithm Selection Guide

Use Case Algorithm Why
Default AES-256-GCM Hardware accelerated, fastest
ARM/Mobile ChaCha20-Poly1305 Software optimized
Searchable AES-256-GCM + deterministic Enables indexing
PII (SSN, CC) AES-256-GCM + FPE Format preservation

Monitoring

Get Metrics

let metrics = manager.get_metrics();
println!("Encryptions: {}", metrics.total_encryptions);
println!("Decryptions: {}", metrics.total_decryptions);
println!("Avg encryption time: {:.2} μs", metrics.avg_encryption_us);
println!("Bytes encrypted: {}", metrics.total_bytes_encrypted);

Check Cache

let cache_stats = manager.get_cache_stats();
println!("Hits: {}, Misses: {}", cache_stats.hits, cache_stats.misses);
println!("Hit rate: {:.1}%", cache_stats.hit_rate * 100.0);

View Audit Log

let audit = manager.get_audit_log("users", "ssn");
for event in audit {
    println!("{}: {:?} - v{}",
        event.timestamp,
        event.event_type,
        event.key_version
    );
}

Troubleshooting

Slow Performance?

// 1. Check metrics
let metrics = manager.get_metrics();
if metrics.avg_encryption_us > 50.0 {
    // Consider increasing cache size or using batch ops
}

// 2. Check cache hit rate
let cache = manager.get_cache_stats();
if cache.hit_rate < 0.7 {
    // Increase cache size
}

// 3. Check hardware acceleration
if !manager.has_hardware_acceleration() {
    // Consider ChaCha20-Poly1305 instead
}

Key Rotation Failed?

// Check audit log for errors
let audit = manager.get_audit_log(table, column);
for event in audit {
    if let Some(details) = event.details {
        println!("Error: {}", details);
    }
}

Next Steps

  1. Read full documentation: COLUMN_LEVEL_ENCRYPTION.md
  2. Review examples: tests/column_encryption_tests.rs
  3. Run benchmarks: cargo bench --bench column_encryption_bench
  4. Integrate with your application

Cheat Sheet

// Setup
let manager = ColumnEncryptionManager::new(None, true).await?;

// Basic encryption
let config = ColumnConfig { /* ... */ };
manager.enable_column_encryption(config, None).await?;
let enc = manager.encrypt_value(table, col, data).await?;
let dec = manager.decrypt_value(table, col, &enc).await?;

// Format-preserving (SSN)
enable_fpe: true, fpe_format: Some(DataFormat::Ssn)

// Searchable (indexed)
deterministic: true

// Batch operations
manager.batch_encrypt(table, col, &rows).await?;

// Key rotation
manager.rotate_column_key(table, col).await?;

// Metrics
manager.get_metrics()
manager.get_cache_stats()
manager.get_audit_log(table, col)

Need Help? See COLUMN_LEVEL_ENCRYPTION.md for comprehensive documentation.