#![allow(clippy::print_stdout)]
#![allow(clippy::unwrap_used)]
use enclaveapp_core::traits::{EnclaveEncryptor, EnclaveKeyManager};
use enclaveapp_core::types::{AccessPolicy, KeyType};
use enclaveapp_test_software::SoftwareEncryptor;
fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive(tracing::Level::INFO.into()),
)
.init();
let mock_mode = std::env::var("ENCLAVE_MOCK").as_deref() == Ok("1");
if mock_mode {
run_with_mock()
} else {
run_with_hardware()
}
}
fn run_with_mock() -> Result<(), Box<dyn std::error::Error>> {
println!("[mock] Using software backend (no hardware required)");
let tmp = tempfile::TempDir::new()?;
let enc = SoftwareEncryptor::with_keys_dir("example-encryption", tmp.path().to_path_buf());
let pubkey = enc.generate("example-enc-key", KeyType::Encryption, AccessPolicy::None)?;
println!(
"[mock] Generated key. Public key ({} bytes): {}...",
pubkey.len(),
bytes_to_hex(&pubkey[..8])
);
let plaintext = b"my secret credential";
let ciphertext = enc.encrypt("example-enc-key", plaintext)?;
println!(
"[mock] Encrypted {} bytes → {} bytes ciphertext.",
plaintext.len(),
ciphertext.len()
);
assert_eq!(ciphertext[0], 0x01, "ECIES version byte must be 0x01");
assert_eq!(
ciphertext[1], 0x04,
"Ephemeral pubkey must start with 0x04 (uncompressed)"
);
let expected_len = 1 + 65 + 12 + plaintext.len() + 16;
assert_eq!(
ciphertext.len(),
expected_len,
"Ciphertext length mismatch: expected {expected_len}, got {}",
ciphertext.len()
);
println!("[mock] Ciphertext format validated (ECIES wire format correct).");
let decrypted = enc.decrypt("example-enc-key", &ciphertext)?;
assert_eq!(
decrypted.as_slice(),
plaintext,
"Decrypt/encrypt roundtrip mismatch"
);
println!(
"[mock] Decrypt roundtrip verified: {:?}",
std::str::from_utf8(&decrypted)?
);
let keys = enc.list_keys()?;
assert_eq!(keys.len(), 1, "expected 1 key, found {}", keys.len());
println!("[mock] list_keys() -> {:?}", keys);
let ct2 = enc.encrypt("example-enc-key", plaintext)?;
assert_ne!(
ciphertext, ct2,
"Each encryption must produce different ciphertext"
);
println!("[mock] Fresh encryption produces different ciphertext (ephemeral ECDH key).");
enc.delete_key("example-enc-key")?;
println!("[mock] Deleted key.");
let exists = enc.key_exists("example-enc-key")?;
assert!(!exists, "key should not exist after deletion");
println!("[mock] key_exists() after deletion -> {exists}");
println!("[mock] Encryption example complete.");
Ok(())
}
fn run_with_hardware() -> Result<(), Box<dyn std::error::Error>> {
use hardware_enclave::{create_encryptor, AccessPolicy, EnclaveConfig};
println!("[hardware] Using platform HSM backend.");
let config = EnclaveConfig::new("enclave-example", "example-enc-key");
let enc = create_encryptor(&config)?;
if enc.key_exists("example-enc-key")? {
println!("[hardware] Removing leftover key from previous run.");
enc.delete_key("example-enc-key")?;
}
let pubkey = enc.generate_key("example-enc-key", AccessPolicy::None)?;
println!(
"[hardware] Generated key. Public key ({} bytes): {}...",
pubkey.len(),
bytes_to_hex(&pubkey[..8])
);
let plaintext = b"my secret credential";
let ciphertext = enc.encrypt("example-enc-key", plaintext)?;
println!(
"[hardware] Encrypted {} bytes → {} bytes ciphertext.",
plaintext.len(),
ciphertext.len()
);
assert_eq!(ciphertext[0], 0x01, "ECIES version byte must be 0x01");
println!("[hardware] Ciphertext format validated.");
let decrypted = enc.decrypt("example-enc-key", &ciphertext)?;
assert_eq!(decrypted.as_slice(), plaintext);
println!("[hardware] Decrypt roundtrip verified.");
let keys = enc.list_keys()?;
println!("[hardware] list_keys() -> {} key(s)", keys.len());
enc.delete_key("example-enc-key")?;
println!("[hardware] Deleted key.");
assert!(!enc.key_exists("example-enc-key")?);
println!("[hardware] Encryption example complete.");
Ok(())
}
fn bytes_to_hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}