Re-Add length bytes to keys endpoint
This commit is contained in:
parent
8a68df9e54
commit
367ff8b10e
5 changed files with 89 additions and 12 deletions
63
examples/verify_key_format.rs
Normal file
63
examples/verify_key_format.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use ohttp_gateway::key_manager::{KeyManager, KeyManagerConfig};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a key manager with default configuration
|
||||
let config = KeyManagerConfig::default();
|
||||
let manager = KeyManager::new(config).await?;
|
||||
|
||||
// Get the encoded configuration
|
||||
let encoded_config = manager.get_encoded_config().await?;
|
||||
|
||||
println!("Key configuration format verification:");
|
||||
println!("=====================================");
|
||||
|
||||
// Check that we have at least 2 bytes for the length prefix
|
||||
if encoded_config.len() < 2 {
|
||||
println!("❌ ERROR: Configuration too short (< 2 bytes)");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Extract the length prefix (first 2 bytes in network byte order)
|
||||
let length_prefix = u16::from_be_bytes([encoded_config[0], encoded_config[1]]);
|
||||
let actual_config_length = encoded_config.len() - 2; // Total length minus 2-byte prefix
|
||||
|
||||
println!(
|
||||
"Total encoded config length: {} bytes",
|
||||
encoded_config.len()
|
||||
);
|
||||
println!("Length prefix value: {} bytes", length_prefix);
|
||||
println!("Actual config data length: {} bytes", actual_config_length);
|
||||
|
||||
// Verify the length prefix matches the actual config data length
|
||||
if length_prefix as usize == actual_config_length {
|
||||
println!("✅ SUCCESS: Length prefix matches actual config data length");
|
||||
println!("✅ SUCCESS: Key configuration format is RFC 9458 compliant");
|
||||
} else {
|
||||
println!(
|
||||
"❌ ERROR: Length prefix ({}) doesn't match actual config data length ({})",
|
||||
length_prefix, actual_config_length
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Display the first few bytes of the configuration for inspection
|
||||
println!("\nFirst 16 bytes of encoded configuration (hex):");
|
||||
let display_bytes = std::cmp::min(16, encoded_config.len());
|
||||
for (i, byte) in encoded_config[..display_bytes].iter().enumerate() {
|
||||
if i == 2 {
|
||||
print!(" | "); // Separator between length prefix and config data
|
||||
} else if i > 2 && (i - 2) % 4 == 0 {
|
||||
print!(" ");
|
||||
}
|
||||
print!("{:02x}", byte);
|
||||
}
|
||||
println!();
|
||||
println!(" ^^ ^^");
|
||||
println!(" Length prefix");
|
||||
println!(" (2 bytes, big-endian)");
|
||||
|
||||
println!("\nFormat verification complete!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ impl KeyManager {
|
|||
keys.get(&key_id).map(|info| info.server.clone())
|
||||
}
|
||||
|
||||
/// Get encoded config for backward compatibility
|
||||
/// Get encoded config with length prefix per RFC 9458 Section 3.2
|
||||
pub async fn get_encoded_config(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||
let keys = self.keys.read().await;
|
||||
let active_id = self.active_key_id.read().await;
|
||||
|
|
@ -216,7 +216,9 @@ impl KeyManager {
|
|||
.config
|
||||
.encode()?;
|
||||
|
||||
let mut out = Vec::with_capacity(cfg_bytes.len());
|
||||
let mut out = Vec::with_capacity(2 + cfg_bytes.len());
|
||||
// Add 2-byte length prefix in network byte order per RFC 9458
|
||||
out.extend_from_slice(&(cfg_bytes.len() as u16).to_be_bytes());
|
||||
out.extend_from_slice(&cfg_bytes);
|
||||
Ok(out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use hyper::StatusCode;
|
||||
use axum::http::StatusCode;
|
||||
use rand::Rng;
|
||||
|
||||
use ohttp_gateway::{key_manager::KeyManager, key_manager::KeyManagerConfig};
|
||||
|
|
@ -90,9 +90,13 @@ async fn test_config_handler() {
|
|||
let cache_control = response.get_header("Cache-Control").unwrap();
|
||||
validate_cache_control_header(cache_control).unwrap();
|
||||
|
||||
// Check body is not empty and has expected structure
|
||||
// Check body is not empty and has expected structure with 2-byte length prefix
|
||||
assert!(!response.body.is_empty());
|
||||
assert!(response.body.len() >= 4); // At least length prefix + some config data
|
||||
assert!(response.body.len() >= 4); // At least 2-byte length prefix + some config data
|
||||
|
||||
// Verify the length prefix is correct per RFC 9458
|
||||
let length_prefix = u16::from_be_bytes([response.body[0], response.body[1]]);
|
||||
assert_eq!(length_prefix as usize, response.body.len() - 2);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
|||
|
|
@ -162,15 +162,19 @@ async fn test_config_serialization_format() {
|
|||
|
||||
let encoded_config = manager.get_encoded_config().await.unwrap();
|
||||
|
||||
// Verify we have config data (no length prefix anymore)
|
||||
// Verify we have config data with 2-byte length prefix per RFC 9458
|
||||
assert!(!encoded_config.is_empty());
|
||||
assert!(encoded_config.len() > 10);
|
||||
assert!(encoded_config.len() > 12); // At least 2 bytes for length + some config data
|
||||
|
||||
// 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);
|
||||
|
||||
// Verify it contains reasonable OHTTP key configuration data
|
||||
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
||||
|
||||
// The config should be the raw encoded configuration
|
||||
let config_data = &encoded_config;
|
||||
// The config should be the length-prefixed encoded configuration
|
||||
let config_data = &encoded_config[2..]; // Skip the length prefix
|
||||
assert!(!config_data.is_empty());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,11 +112,15 @@ async fn test_get_encoded_config() {
|
|||
|
||||
let encoded_config = manager.get_encoded_config().await.unwrap();
|
||||
|
||||
// Should have some config data (no length prefix anymore)
|
||||
// Should have config data with 2-byte length prefix per RFC 9458
|
||||
assert!(!encoded_config.is_empty());
|
||||
assert!(encoded_config.len() > 0);
|
||||
assert!(encoded_config.len() > 2);
|
||||
|
||||
// The encoded config should be the raw config bytes without length prefix
|
||||
// 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
|
||||
// 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue