use crate::error::{Error, Result};
use std::fs;
use std::path::Path;
pub struct KeyLoader;
impl KeyLoader {
pub fn load(input: &str) -> Result<String> {
let trimmed = input.trim();
if trimmed.starts_with("-----BEGIN") {
Self::validate_pem(trimmed)?;
return Ok(trimmed.to_string());
}
Self::load_from_file(input)
}
pub fn load_from_file(path: &str) -> Result<String> {
let key_path = Path::new(path);
if !key_path.exists() {
return Err(Error::KeyError(format!(
"Private key file not found: {path}"
)));
}
let content = fs::read_to_string(key_path)
.map_err(|e| Error::KeyError(format!("Failed to read private key file: {e}")))?;
Self::validate_pem(&content)?;
Ok(content)
}
fn validate_pem(content: &str) -> Result<()> {
if !content.contains("-----BEGIN") || !content.contains("-----END") {
return Err(Error::KeyError("Not a valid PEM format".to_string()));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_load_valid_pem_file() {
let mut temp_file = NamedTempFile::new().unwrap();
let pem_content =
"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA...\n-----END RSA PRIVATE KEY-----\n";
temp_file.write_all(pem_content.as_bytes()).unwrap();
let result = KeyLoader::load_from_file(temp_file.path().to_str().unwrap());
assert!(result.is_ok());
assert_eq!(result.unwrap(), pem_content);
}
#[test]
fn test_load_nonexistent_file() {
let result = KeyLoader::load_from_file("/nonexistent/path/to/key.pem");
assert!(result.is_err());
match result.unwrap_err() {
Error::KeyError(msg) => assert!(msg.contains("not found")),
_ => panic!("Expected KeyError"),
}
}
#[test]
fn test_validate_pem_valid() {
let valid_pem = "-----BEGIN RSA PRIVATE KEY-----\ntest\n-----END RSA PRIVATE KEY-----";
assert!(KeyLoader::validate_pem(valid_pem).is_ok());
}
#[test]
fn test_validate_pem_missing_begin() {
let invalid_pem = "some content\n-----END RSA PRIVATE KEY-----";
let result = KeyLoader::validate_pem(invalid_pem);
assert!(result.is_err());
match result.unwrap_err() {
Error::KeyError(msg) => assert!(msg.contains("valid PEM")),
_ => panic!("Expected KeyError"),
}
}
#[test]
fn test_validate_pem_missing_end() {
let invalid_pem = "-----BEGIN RSA PRIVATE KEY-----\nsome content";
let result = KeyLoader::validate_pem(invalid_pem);
assert!(result.is_err());
match result.unwrap_err() {
Error::KeyError(msg) => assert!(msg.contains("valid PEM")),
_ => panic!("Expected KeyError"),
}
}
#[test]
fn test_validate_pem_empty() {
let result = KeyLoader::validate_pem("");
assert!(result.is_err());
}
}