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())
|
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>> {
|
pub async fn get_encoded_config(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
||||||
let keys = self.keys.read().await;
|
let keys = self.keys.read().await;
|
||||||
let active_id = self.active_key_id.read().await;
|
let active_id = self.active_key_id.read().await;
|
||||||
|
|
@ -216,7 +216,9 @@ impl KeyManager {
|
||||||
.config
|
.config
|
||||||
.encode()?;
|
.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);
|
out.extend_from_slice(&cfg_bytes);
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use hyper::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use ohttp_gateway::{key_manager::KeyManager, key_manager::KeyManagerConfig};
|
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();
|
let cache_control = response.get_header("Cache-Control").unwrap();
|
||||||
validate_cache_control_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.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]
|
#[tokio::test]
|
||||||
|
|
|
||||||
|
|
@ -162,15 +162,19 @@ async fn test_config_serialization_format() {
|
||||||
|
|
||||||
let encoded_config = manager.get_encoded_config().await.unwrap();
|
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.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
|
// Verify it contains reasonable OHTTP key configuration data
|
||||||
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
||||||
|
|
||||||
// The config should be the raw encoded configuration
|
// The config should be the length-prefixed encoded configuration
|
||||||
let config_data = &encoded_config;
|
let config_data = &encoded_config[2..]; // Skip the length prefix
|
||||||
assert!(!config_data.is_empty());
|
assert!(!config_data.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,11 +112,15 @@ async fn test_get_encoded_config() {
|
||||||
|
|
||||||
let encoded_config = manager.get_encoded_config().await.unwrap();
|
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.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,
|
// We can't easily verify the exact content without duplicating the encoding logic,
|
||||||
// but we can at least verify it's reasonable in size
|
// but we can at least verify it's reasonable in size
|
||||||
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
assert!(encoded_config.len() < 1000); // Reasonable upper bound
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue