use crate::error::AcmeError;
use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyType {
Ed25519,
EcdsaP256,
EcdsaP384,
EcdsaP521,
Rsa2048,
Rsa4096,
}
impl KeyType {
pub fn jwa_algorithm(&self) -> &'static str {
match self {
KeyType::Ed25519 => "EdDSA",
KeyType::EcdsaP256 => "ES256",
KeyType::EcdsaP384 => "ES384",
KeyType::EcdsaP521 => "ES512",
KeyType::Rsa2048 | KeyType::Rsa4096 => "RS256",
}
}
pub fn openssl_curve(&self) -> Option<&'static str> {
match self {
KeyType::EcdsaP256 => Some("prime256v1"),
KeyType::EcdsaP384 => Some("secp384r1"),
KeyType::EcdsaP521 => Some("secp521r1"),
_ => None,
}
}
}
impl std::fmt::Display for KeyType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KeyType::Ed25519 => write!(f, "Ed25519"),
KeyType::EcdsaP256 => write!(f, "ECDSA-P256"),
KeyType::EcdsaP384 => write!(f, "ECDSA-P384"),
KeyType::EcdsaP521 => write!(f, "ECDSA-P521"),
KeyType::Rsa2048 => write!(f, "RSA-2048"),
KeyType::Rsa4096 => write!(f, "RSA-4096"),
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct JwkPublicKey {
pub kty: String,
pub alg: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub r#use: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub n: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub e: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub crv: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub y: Option<String>,
}
pub struct KeyPairGenerator {
key_type: KeyType,
}
impl KeyPairGenerator {
pub fn new(key_type: KeyType) -> Self {
Self { key_type }
}
pub fn ed25519() -> Self {
Self::new(KeyType::Ed25519)
}
pub fn ecdsa_p256() -> Self {
Self::new(KeyType::EcdsaP256)
}
pub fn ecdsa_p384() -> Self {
Self::new(KeyType::EcdsaP384)
}
pub fn generate(&self) -> Result<rcgen::KeyPair> {
tracing::info!("Generating new {} key pair", self.key_type);
match self.key_type {
KeyType::Ed25519 => rcgen::KeyPair::generate().map_err(|e| {
tracing::error!("Failed to generate Ed25519 key: {}", e);
AcmeError::crypto(format!("Failed to generate Ed25519 key: {}", e))
}),
_ => {
tracing::error!(
"Key generation for {} is not yet implemented",
self.key_type
);
Err(AcmeError::crypto(format!(
"Key type {} generation not yet implemented",
self.key_type
)))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_type_jwa() {
assert_eq!(KeyType::Ed25519.jwa_algorithm(), "EdDSA");
assert_eq!(KeyType::EcdsaP256.jwa_algorithm(), "ES256");
assert_eq!(KeyType::Rsa2048.jwa_algorithm(), "RS256");
}
#[test]
fn test_generate_ed25519() {
let generator = KeyPairGenerator::ed25519();
let result = generator.generate();
assert!(result.is_ok(), "Ed25519 generation should work");
}
}