2025-07-24 11:09:17 +00:00
|
|
|
use bhttp::Message;
|
2025-07-24 11:21:37 +00:00
|
|
|
use ohttp_gateway::key_manager::{CipherSuiteConfig, KeyManager, KeyManagerConfig};
|
2025-07-24 11:09:17 +00:00
|
|
|
use std::io::Cursor;
|
2025-07-22 10:57:19 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
|
use tokio;
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_key_generation() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
let stats = manager.get_stats().await;
|
|
|
|
|
assert_eq!(stats.total_keys, 1);
|
|
|
|
|
assert_eq!(stats.active_keys, 1);
|
|
|
|
|
assert!(stats.active_key_id > 0); // Should have generated a key with ID > 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_key_generation_with_seed() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let seed = vec![0u8; 32]; // 32 bytes of zeros for deterministic testing
|
|
|
|
|
|
|
|
|
|
let manager = KeyManager::new_with_seed(config, seed).await.unwrap();
|
|
|
|
|
let stats = manager.get_stats().await;
|
|
|
|
|
|
|
|
|
|
assert_eq!(stats.total_keys, 1);
|
|
|
|
|
assert_eq!(stats.active_keys, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_key_generation_with_insufficient_seed() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let short_seed = vec![0u8; 16]; // Only 16 bytes - should fail
|
|
|
|
|
|
|
|
|
|
let result = KeyManager::new_with_seed(config, short_seed).await;
|
|
|
|
|
assert!(result.is_err());
|
|
|
|
|
|
|
|
|
|
if let Err(e) = result {
|
|
|
|
|
assert!(e.to_string().contains("Seed must be at least 32 bytes"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_key_rotation() {
|
|
|
|
|
let config = KeyManagerConfig {
|
|
|
|
|
rotation_interval: Duration::from_secs(60),
|
|
|
|
|
key_retention_period: Duration::from_secs(30),
|
|
|
|
|
auto_rotation_enabled: true,
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
let initial_stats = manager.get_stats().await;
|
|
|
|
|
|
|
|
|
|
// Rotate keys
|
|
|
|
|
manager.rotate_keys().await.unwrap();
|
|
|
|
|
|
|
|
|
|
let new_stats = manager.get_stats().await;
|
|
|
|
|
assert_eq!(new_stats.total_keys, 2); // Old key + new key
|
|
|
|
|
assert_ne!(new_stats.active_key_id, initial_stats.active_key_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_get_current_server() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
let server = manager.get_current_server().await;
|
|
|
|
|
assert!(server.is_ok());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_get_server_by_id() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
let stats = manager.get_stats().await;
|
|
|
|
|
let active_id = stats.active_key_id;
|
|
|
|
|
|
|
|
|
|
// Should find the active key
|
|
|
|
|
let server = manager.get_server_by_id(active_id).await;
|
|
|
|
|
assert!(server.is_some());
|
|
|
|
|
|
|
|
|
|
// Should not find non-existent key
|
|
|
|
|
let non_existent = manager.get_server_by_id(active_id.wrapping_add(100)).await;
|
|
|
|
|
assert!(non_existent.is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_should_rotate() {
|
|
|
|
|
let config = KeyManagerConfig {
|
|
|
|
|
rotation_interval: Duration::from_millis(100), // Very short for testing
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
// Should not need rotation immediately
|
|
|
|
|
assert!(!manager.should_rotate().await);
|
|
|
|
|
|
|
|
|
|
// Wait for the rotation interval to pass
|
|
|
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
|
|
|
|
|
|
// Now should need rotation
|
|
|
|
|
assert!(manager.should_rotate().await);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_get_encoded_config() {
|
|
|
|
|
let config = KeyManagerConfig::default();
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
let encoded_config = manager.get_encoded_config().await.unwrap();
|
|
|
|
|
|
2025-11-23 20:27:24 +00:00
|
|
|
// Should have config data with 2-byte length prefix per RFC 9458
|
2025-07-24 11:21:37 +00:00
|
|
|
assert!(!encoded_config.is_empty());
|
2025-11-23 20:27:24 +00:00
|
|
|
assert!(encoded_config.len() > 2);
|
2025-07-22 10:57:19 +00:00
|
|
|
|
2025-11-23 20:27:24 +00:00
|
|
|
// Verify the length prefix is correct
|
|
|
|
|
let length_prefix = u16::from_be_bytes([encoded_config[0], encoded_config[1]]);
|
|
|
|
|
assert_eq!(length_prefix as usize, encoded_config.len() - 2);
|
|
|
|
|
|
|
|
|
|
// The encoded config should be the length-prefixed config bytes
|
2025-07-24 11:21:37 +00:00
|
|
|
// We can't easily verify the exact content without duplicating the encoding logic,
|
|
|
|
|
// but we can at least verify it's reasonable in size
|
|
|
|
|
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
2025-07-22 10:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_multiple_cipher_suites() {
|
|
|
|
|
let config = KeyManagerConfig {
|
|
|
|
|
cipher_suites: vec![
|
|
|
|
|
CipherSuiteConfig {
|
|
|
|
|
kem: "X25519_SHA256".to_string(),
|
|
|
|
|
kdf: "HKDF_SHA256".to_string(),
|
|
|
|
|
aead: "AES_128_GCM".to_string(),
|
|
|
|
|
},
|
|
|
|
|
CipherSuiteConfig {
|
|
|
|
|
kem: "X25519_SHA256".to_string(),
|
|
|
|
|
kdf: "HKDF_SHA256".to_string(),
|
|
|
|
|
aead: "CHACHA20_POLY1305".to_string(),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
let stats = manager.get_stats().await;
|
|
|
|
|
assert_eq!(stats.total_keys, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_cleanup_expired_keys() {
|
|
|
|
|
let config = KeyManagerConfig {
|
|
|
|
|
rotation_interval: Duration::from_millis(50),
|
|
|
|
|
key_retention_period: Duration::from_millis(100),
|
|
|
|
|
auto_rotation_enabled: false, // Manual control for testing
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let manager = KeyManager::new(config).await.unwrap();
|
|
|
|
|
|
|
|
|
|
// Rotate to create an old key
|
|
|
|
|
manager.rotate_keys().await.unwrap();
|
|
|
|
|
|
|
|
|
|
let stats_after_rotation = manager.get_stats().await;
|
|
|
|
|
assert_eq!(stats_after_rotation.total_keys, 2);
|
|
|
|
|
|
|
|
|
|
// Wait for keys to expire and manually trigger cleanup
|
|
|
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
|
|
|
|
|
|
// Trigger another rotation which should clean up expired keys
|
|
|
|
|
manager.rotate_keys().await.unwrap();
|
|
|
|
|
|
|
|
|
|
let final_stats = manager.get_stats().await;
|
|
|
|
|
// Should have cleaned up the expired key
|
|
|
|
|
assert!(final_stats.total_keys <= 2);
|
|
|
|
|
}
|
2025-07-24 11:09:17 +00:00
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn test_bhttp_parsing() {
|
|
|
|
|
// let data = &[
|
|
|
|
|
// 2, 3, 71, 69, 84, 5, 104, 116, 116, 112, 115, 9, 108, 111, 99, 97, 108, 104, 111, 115, 116,
|
|
|
|
|
// 4, 47, 103, 101, 116, 10, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 21, 79, 72, 84,
|
|
|
|
|
// 84, 80, 45, 84, 101, 115, 116, 45, 67, 108, 105, 101, 110, 116, 47, 49, 46, 48, 6, 97, 99,
|
|
|
|
|
// 99, 101, 112, 116, 16, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, 115,
|
|
|
|
|
// 111, 110, 0, 0,
|
|
|
|
|
// ];
|
|
|
|
|
// let mut cursor = std::io::Cursor::new(data);
|
|
|
|
|
//
|
|
|
|
|
// let m = Message::read_bhttp(&mut cursor).unwrap();
|
|
|
|
|
//
|
|
|
|
|
// println!("TEST {:?}", m);
|
|
|
|
|
|
|
|
|
|
const REQUEST: &[u8] = &[
|
|
|
|
|
2, 3, 71, 69, 84, 5, 104, 116, 116, 112, 115, 9, 108, 111, 99, 97, 108, 104, 111, 115, 116,
|
|
|
|
|
4, 47, 103, 101, 116, 10, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 21, 79, 72, 84,
|
|
|
|
|
84, 80, 45, 84, 101, 115, 116, 45, 67, 108, 105, 101, 110, 116, 47, 49, 46, 48, 6, 97, 99,
|
|
|
|
|
99, 101, 112, 116, 16, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, 115,
|
2025-07-24 11:21:37 +00:00
|
|
|
111, 110, 0, 0, 0,
|
2025-07-24 11:09:17 +00:00
|
|
|
];
|
|
|
|
|
let m = Message::read_bhttp(&mut Cursor::new(REQUEST)).unwrap();
|
|
|
|
|
assert!(m.header().get(b"accept").is_some());
|
|
|
|
|
}
|