use crate::key::derivation::Hkdf;
use crate::{Algorithm, KeyManager};
#[test]
fn test_key_lifecycle() {
let manager = KeyManager::new().unwrap();
let key_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
manager.suspend_key(&key_id).unwrap();
manager.resume_key(&key_id).unwrap();
manager.destroy_key(&key_id).unwrap();
assert!(manager.get_key(&key_id).is_err());
}
#[test]
fn test_key_derivation_hkdf() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
let derived1 = Hkdf::derive(&master_key, b"", b"context1", Algorithm::AES256GCM).unwrap();
let derived2 = Hkdf::derive(&master_key, b"", b"context2", Algorithm::AES256GCM).unwrap();
assert_ne!(
derived1.secret_bytes().unwrap().as_bytes(),
derived2.secret_bytes().unwrap().as_bytes()
);
let derived1_again = Hkdf::derive(&master_key, b"", b"context1", Algorithm::AES256GCM).unwrap();
assert_eq!(
derived1.secret_bytes().unwrap().as_bytes(),
derived1_again.secret_bytes().unwrap().as_bytes()
);
}
#[test]
fn test_key_derivation_with_salt() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
let derived1 = Hkdf::derive(&master_key, b"salt1", b"context", Algorithm::AES256GCM).unwrap();
let derived2 = Hkdf::derive(&master_key, b"salt2", b"context", Algorithm::AES256GCM).unwrap();
assert_ne!(
derived1.secret_bytes().unwrap().as_bytes(),
derived2.secret_bytes().unwrap().as_bytes()
);
}
#[test]
fn test_key_derivation_different_algorithms() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::ECDSAP384).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
println!("Master key is_valid: {}", master_key.is_valid());
let salt = b"test-salt-for-derivation";
let derived_aes256 = Hkdf::derive(
&master_key,
salt,
b"aes256-derivation",
Algorithm::AES256GCM,
)
.unwrap();
assert_eq!(derived_aes256.secret_bytes().unwrap().as_bytes().len(), 32);
assert!(derived_aes256.is_valid());
let derived_sm4 =
Hkdf::derive(&master_key, salt, b"sm4-derivation", Algorithm::SM4GCM).unwrap();
assert_eq!(derived_sm4.secret_bytes().unwrap().as_bytes().len(), 16);
assert!(derived_sm4.is_valid());
let derived_aes128 = Hkdf::derive(
&master_key,
salt,
b"aes128-derivation",
Algorithm::AES128GCM,
)
.unwrap();
assert_eq!(derived_aes128.secret_bytes().unwrap().as_bytes().len(), 16);
assert!(derived_aes128.is_valid());
let derived_aes192 = Hkdf::derive(
&master_key,
salt,
b"aes192-derivation",
Algorithm::AES192GCM,
)
.unwrap();
assert_eq!(derived_aes192.secret_bytes().unwrap().as_bytes().len(), 24);
assert!(derived_aes192.is_valid());
assert_ne!(
derived_aes256.secret_bytes().unwrap().as_bytes(),
derived_aes128.secret_bytes().unwrap().as_bytes()
);
assert_ne!(
derived_aes256.secret_bytes().unwrap().as_bytes(),
derived_aes192.secret_bytes().unwrap().as_bytes()
);
assert_ne!(
derived_aes128.secret_bytes().unwrap().as_bytes(),
derived_sm4.secret_bytes().unwrap().as_bytes()
);
}
#[test]
fn test_key_derivation_deterministic() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
let mut derived_keys = Vec::with_capacity(5);
for _ in 0..5 {
let derived = Hkdf::derive(
&master_key,
b"test_salt",
b"test_context",
Algorithm::AES256GCM,
)
.unwrap();
derived_keys.push(derived.secret_bytes().unwrap().as_bytes().to_vec());
}
for i in 1..derived_keys.len() {
assert_eq!(derived_keys[0], derived_keys[i]);
}
}
#[test]
fn test_key_derivation_edge_cases() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
let derived_empty_salt =
Hkdf::derive(&master_key, b"", b"context", Algorithm::AES256GCM).unwrap();
assert!(!derived_empty_salt
.secret_bytes()
.unwrap()
.as_bytes()
.is_empty());
let derived_empty_context =
Hkdf::derive(&master_key, b"salt", b"", Algorithm::AES256GCM).unwrap();
assert!(!derived_empty_context
.secret_bytes()
.unwrap()
.as_bytes()
.is_empty());
let long_context = vec![b'A'; 1000];
let derived_long_context =
Hkdf::derive(&master_key, b"salt", &long_context, Algorithm::AES256GCM).unwrap();
assert!(!derived_long_context
.secret_bytes()
.unwrap()
.as_bytes()
.is_empty());
assert_ne!(
derived_empty_salt.secret_bytes().unwrap().as_bytes(),
derived_empty_context.secret_bytes().unwrap().as_bytes()
);
}
#[test]
fn test_key_derivation_security_properties() {
let manager = KeyManager::new().unwrap();
let master_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let master_key = manager.get_key(&master_id).unwrap();
let derived1 = Hkdf::derive(&master_key, b"salt", b"context1", Algorithm::AES256GCM).unwrap();
let derived2 = Hkdf::derive(&master_key, b"salt", b"context2", Algorithm::AES256GCM).unwrap();
let derived1_bytes = derived1.secret_bytes().unwrap().as_bytes();
let derived2_bytes = derived2.secret_bytes().unwrap().as_bytes();
assert_ne!(derived1_bytes, derived2_bytes);
let mut differences = 0;
for i in 0..derived1_bytes.len().min(derived2_bytes.len()) {
if derived1_bytes[i] != derived2_bytes[i] {
differences += 1;
}
}
let difference_ratio = differences as f64 / derived1_bytes.len() as f64;
assert!(
difference_ratio > 0.75,
"Key derivation should have strong avalanche effect"
);
}
#[test]
fn test_key_expiration() {
let manager = KeyManager::new().unwrap();
let key_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
let expires_at = chrono::Utc::now() + chrono::Duration::hours(1);
manager.set_key_expiration(&key_id, expires_at).unwrap();
let key = manager.get_key(&key_id).unwrap();
assert!(!key.is_expired());
let expires_at = chrono::Utc::now() - chrono::Duration::hours(1);
manager.set_key_expiration(&key_id, expires_at).unwrap();
let key = manager.get_key(&key_id).unwrap();
assert!(key.is_expired());
assert!(!key.is_valid());
}
#[test]
fn test_key_usage_limit() {
let manager = KeyManager::new().unwrap();
let key_id = manager.generate_key(Algorithm::AES256GCM).unwrap();
manager.set_key_max_usage(&key_id, Some(3)).unwrap();
let mut key = manager.get_key(&key_id).unwrap();
for _ in 0..3 {
assert!(key.increment_usage().is_ok());
}
assert!(key.increment_usage().is_err());
assert!(key.is_usage_exceeded());
}