use std::fmt;
use std::net::IpAddr;
#[cfg(feature = "aws-lc-rs")]
use aws_lc_rs as crypto_provider;
use crypto_provider::rand::SystemRandom;
use crypto_provider::signature::{
ECDSA_P256_SHA256_ASN1_SIGNING, ECDSA_P384_SHA384_ASN1_SIGNING, EcdsaKeyPair, Ed25519KeyPair,
};
use rcgen::{
CertificateParams, CustomExtension, KeyPair as RcgenKeyPair, PKCS_ECDSA_P256_SHA256,
PKCS_ECDSA_P384_SHA384, PKCS_ED25519, PKCS_RSA_SHA256,
};
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
use ring as crypto_provider;
use rustls::pki_types::PrivatePkcs8KeyDer;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
pub(crate) fn ecdsa_from_pkcs8(
alg: &'static crypto_provider::signature::EcdsaSigningAlgorithm,
pkcs8: &[u8],
) -> std::result::Result<EcdsaKeyPair, crypto_provider::error::KeyRejected> {
#[cfg(feature = "aws-lc-rs")]
{
EcdsaKeyPair::from_pkcs8(alg, pkcs8)
}
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
{
let rng = SystemRandom::new();
EcdsaKeyPair::from_pkcs8(alg, pkcs8, &rng)
}
}
use crate::error::{CryptoError, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
pub enum KeyType {
#[default]
EcdsaP256,
EcdsaP384,
EcdsaP521,
Rsa2048,
Rsa4096,
Rsa8192,
Ed25519,
}
impl fmt::Display for KeyType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::EcdsaP256 => write!(f, "p256"),
Self::EcdsaP384 => write!(f, "p384"),
Self::EcdsaP521 => write!(f, "p521"),
Self::Rsa2048 => write!(f, "rsa2048"),
Self::Rsa4096 => write!(f, "rsa4096"),
Self::Rsa8192 => write!(f, "rsa8192"),
Self::Ed25519 => write!(f, "ed25519"),
}
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct PrivateKey {
key_type: KeyType,
#[serde(with = "base64_serde")]
pkcs8_der: Vec<u8>,
}
impl fmt::Debug for PrivateKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PrivateKey")
.field("key_type", &self.key_type)
.field("pkcs8_der_len", &self.pkcs8_der.len())
.finish()
}
}
impl PrivateKey {
pub fn key_type(&self) -> KeyType {
self.key_type
}
pub fn pkcs8_der(&self) -> &[u8] {
&self.pkcs8_der
}
pub fn from_pkcs8_der(key_type: KeyType, der: Vec<u8>) -> Self {
Self {
key_type,
pkcs8_der: der,
}
}
fn to_rcgen_key_pair(&self) -> Result<RcgenKeyPair> {
let pkcs8 = PrivatePkcs8KeyDer::from(self.pkcs8_der.clone());
match self.key_type {
KeyType::EcdsaP256 => {
RcgenKeyPair::from_pkcs8_der_and_sign_algo(&pkcs8, &PKCS_ECDSA_P256_SHA256)
}
KeyType::EcdsaP384 => {
RcgenKeyPair::from_pkcs8_der_and_sign_algo(&pkcs8, &PKCS_ECDSA_P384_SHA384)
}
KeyType::EcdsaP521 => {
RcgenKeyPair::try_from(&pkcs8)
}
KeyType::Ed25519 => RcgenKeyPair::from_pkcs8_der_and_sign_algo(&pkcs8, &PKCS_ED25519),
KeyType::Rsa2048 | KeyType::Rsa4096 | KeyType::Rsa8192 => {
RcgenKeyPair::from_pkcs8_der_and_sign_algo(&pkcs8, &PKCS_RSA_SHA256)
}
}
.map_err(|e| CryptoError::InvalidKey(format!("failed to build rcgen key pair: {e}")).into())
}
}
mod base64_serde {
use base64::prelude::*;
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S: Serializer>(
bytes: &Vec<u8>,
ser: S,
) -> std::result::Result<S::Ok, S::Error> {
ser.serialize_str(&BASE64_STANDARD.encode(bytes))
}
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> std::result::Result<Vec<u8>, D::Error> {
let s = String::deserialize(de)?;
BASE64_STANDARD.decode(&s).map_err(serde::de::Error::custom)
}
}
pub fn generate_private_key(key_type: KeyType) -> Result<PrivateKey> {
let rng = SystemRandom::new();
let pkcs8_der = match key_type {
KeyType::EcdsaP256 => {
let doc = EcdsaKeyPair::generate_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, &rng)
.map_err(|e| CryptoError::KeyGeneration(format!("ECDSA P-256: {e}")))?;
doc.as_ref().to_vec()
}
KeyType::EcdsaP384 => {
let doc = EcdsaKeyPair::generate_pkcs8(&ECDSA_P384_SHA384_ASN1_SIGNING, &rng)
.map_err(|e| CryptoError::KeyGeneration(format!("ECDSA P-384: {e}")))?;
doc.as_ref().to_vec()
}
KeyType::EcdsaP521 => generate_p521_pkcs8()?,
KeyType::Ed25519 => {
let doc = Ed25519KeyPair::generate_pkcs8(&rng)
.map_err(|e| CryptoError::KeyGeneration(format!("Ed25519: {e}")))?;
doc.as_ref().to_vec()
}
KeyType::Rsa2048 => generate_rsa_pkcs8(2048)?,
KeyType::Rsa4096 => generate_rsa_pkcs8(4096)?,
KeyType::Rsa8192 => generate_rsa_pkcs8(8192)?,
};
Ok(PrivateKey {
key_type,
pkcs8_der,
})
}
fn generate_rsa_pkcs8(bits: usize) -> Result<Vec<u8>> {
use rsa::RsaPrivateKey;
use rsa::pkcs8::EncodePrivateKey;
let mut rng = rsa::rand_core::OsRng;
let key = RsaPrivateKey::new(&mut rng, bits)
.map_err(|e| CryptoError::KeyGeneration(format!("RSA-{bits}: {e}")))?;
let doc = key
.to_pkcs8_der()
.map_err(|e| CryptoError::KeyGeneration(format!("RSA-{bits} PKCS#8 encode: {e}")))?;
Ok(doc.as_bytes().to_vec())
}
fn generate_p521_pkcs8() -> Result<Vec<u8>> {
use elliptic_curve::pkcs8::EncodePrivateKey;
use p521::ecdsa::SigningKey;
let signing_key = SigningKey::random(&mut elliptic_curve::rand_core::OsRng);
let secret_key = signing_key.as_nonzero_scalar();
let sk = p521::SecretKey::from(secret_key);
let doc = sk
.to_pkcs8_der()
.map_err(|e| CryptoError::KeyGeneration(format!("ECDSA P-521 PKCS#8 encode: {e}")))?;
Ok(doc.as_bytes().to_vec())
}
fn pem_tag_for(key_type: KeyType) -> &'static str {
match key_type {
KeyType::EcdsaP256 | KeyType::EcdsaP384 | KeyType::EcdsaP521 => "EC PRIVATE KEY",
KeyType::Rsa2048 | KeyType::Rsa4096 | KeyType::Rsa8192 => "RSA PRIVATE KEY",
KeyType::Ed25519 => "PRIVATE KEY",
}
}
pub fn encode_private_key_pem(key: &PrivateKey) -> Result<String> {
let tag = pem_tag_for(key.key_type);
let der_bytes = match key.key_type {
KeyType::EcdsaP256 | KeyType::EcdsaP384 | KeyType::EcdsaP521 => {
extract_ec_private_key_from_pkcs8(&key.pkcs8_der)
.unwrap_or_else(|| key.pkcs8_der.clone())
}
KeyType::Rsa2048 | KeyType::Rsa4096 | KeyType::Rsa8192 => {
extract_rsa_private_key_from_pkcs8(&key.pkcs8_der)
.unwrap_or_else(|| key.pkcs8_der.clone())
}
KeyType::Ed25519 => {
key.pkcs8_der.clone()
}
};
let pem_obj = ::pem::Pem::new(tag, der_bytes);
Ok(::pem::encode(&pem_obj))
}
fn extract_ec_private_key_from_pkcs8(pkcs8: &[u8]) -> Option<Vec<u8>> {
let (_, parsed) = x509_parser::der_parser::parse_der(pkcs8).ok()?;
let seq = parsed.as_sequence().ok()?;
if seq.len() < 3 {
return None;
}
let octet = seq[2].as_slice().ok()?;
Some(octet.to_vec())
}
fn extract_rsa_private_key_from_pkcs8(pkcs8: &[u8]) -> Option<Vec<u8>> {
let (_, parsed) = x509_parser::der_parser::parse_der(pkcs8).ok()?;
let seq = parsed.as_sequence().ok()?;
if seq.len() < 3 {
return None;
}
let octet = seq[2].as_slice().ok()?;
Some(octet.to_vec())
}
pub fn decode_private_key_pem(pem_data: &str) -> Result<PrivateKey> {
let parsed = ::pem::parse(pem_data)
.map_err(|e| CryptoError::PemDecode(format!("failed to parse PEM: {e}")))?;
let tag = parsed.tag().to_owned();
let der = parsed.into_contents();
if !tag.ends_with("PRIVATE KEY") {
return Err(CryptoError::PemDecode(format!("unknown PEM header: {tag}")).into());
}
match tag.as_str() {
"EC PRIVATE KEY" => decode_ec_private_key(&der),
"RSA PRIVATE KEY" => decode_rsa_private_key(&der),
"PRIVATE KEY" | "ED25519 PRIVATE KEY" => decode_pkcs8_private_key(&der),
_ => {
decode_pkcs8_private_key(&der)
}
}
}
fn decode_ec_private_key(sec1_der: &[u8]) -> Result<PrivateKey> {
let key_type = detect_ec_curve_from_sec1(sec1_der);
let pkcs8_der = wrap_ec_sec1_in_pkcs8(sec1_der, key_type)?;
validate_ec_key(&pkcs8_der, key_type)?;
Ok(PrivateKey {
key_type,
pkcs8_der,
})
}
fn detect_ec_curve_from_sec1(sec1_der: &[u8]) -> KeyType {
if let Ok((_, parsed)) = x509_parser::der_parser::parse_der(sec1_der)
&& let Ok(seq) = parsed.as_sequence()
{
if seq.len() > 1
&& let Ok(privkey_bytes) = seq[1].as_slice()
{
return match privkey_bytes.len() {
32 => KeyType::EcdsaP256,
48 => KeyType::EcdsaP384,
66 => KeyType::EcdsaP521,
_ => KeyType::EcdsaP256, };
}
}
KeyType::EcdsaP256
}
const OID_EC_PUBLIC_KEY: &[u8] = &[0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01];
const OID_P256: &[u8] = &[0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
const OID_P384: &[u8] = &[0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22];
const OID_P521: &[u8] = &[0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23];
fn wrap_ec_sec1_in_pkcs8(sec1_der: &[u8], key_type: KeyType) -> Result<Vec<u8>> {
let curve_oid = match key_type {
KeyType::EcdsaP256 => OID_P256,
KeyType::EcdsaP384 => OID_P384,
KeyType::EcdsaP521 => OID_P521,
_ => {
return Err(
CryptoError::PemDecode("cannot wrap non-EC key as EC PKCS#8".into()).into(),
);
}
};
let mut algo_seq_content = Vec::new();
algo_seq_content.extend_from_slice(OID_EC_PUBLIC_KEY);
algo_seq_content.extend_from_slice(curve_oid);
let algo_seq = der_wrap(0x30, &algo_seq_content);
let version = der_wrap(0x02, &[0x00]); let octet_string = der_wrap(0x04, sec1_der);
let mut outer_content = Vec::new();
outer_content.extend_from_slice(&version);
outer_content.extend_from_slice(&algo_seq);
outer_content.extend_from_slice(&octet_string);
let pkcs8 = der_wrap(0x30, &outer_content);
Ok(pkcs8)
}
fn der_wrap(tag: u8, content: &[u8]) -> Vec<u8> {
let mut out = vec![tag];
let len = content.len();
if len < 0x80 {
out.push(len as u8);
} else if len < 0x100 {
out.push(0x81);
out.push(len as u8);
} else if len < 0x10000 {
out.push(0x82);
out.push((len >> 8) as u8);
out.push(len as u8);
} else {
out.push(0x83);
out.push((len >> 16) as u8);
out.push((len >> 8) as u8);
out.push(len as u8);
}
out.extend_from_slice(content);
out
}
fn validate_ec_key(pkcs8_der: &[u8], key_type: KeyType) -> Result<()> {
match key_type {
KeyType::EcdsaP256 => {
ecdsa_from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8_der)
.map_err(|e| CryptoError::InvalidKey(format!("P-256 validation failed: {e}")))?;
}
KeyType::EcdsaP384 => {
ecdsa_from_pkcs8(&ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8_der)
.map_err(|e| CryptoError::InvalidKey(format!("P-384 validation failed: {e}")))?;
}
KeyType::EcdsaP521 => {
use elliptic_curve::pkcs8::DecodePrivateKey;
p521::SecretKey::from_pkcs8_der(pkcs8_der)
.map_err(|e| CryptoError::InvalidKey(format!("P-521 validation failed: {e}")))?;
}
_ => {}
}
Ok(())
}
fn decode_rsa_private_key(pkcs1_der: &[u8]) -> Result<PrivateKey> {
use rsa::RsaPrivateKey;
use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::pkcs8::EncodePrivateKey;
use rsa::traits::PublicKeyParts;
let rsa_key = RsaPrivateKey::from_pkcs1_der(pkcs1_der)
.map_err(|e| CryptoError::PemDecode(format!("invalid PKCS#1 RSA key: {e}")))?;
let bits = rsa_key.n().bits();
let key_type = if bits <= 2048 {
KeyType::Rsa2048
} else if bits <= 4096 {
KeyType::Rsa4096
} else {
KeyType::Rsa8192
};
let pkcs8_doc = rsa_key
.to_pkcs8_der()
.map_err(|e| CryptoError::PemDecode(format!("RSA to PKCS#8 conversion: {e}")))?;
Ok(PrivateKey {
key_type,
pkcs8_der: pkcs8_doc.as_bytes().to_vec(),
})
}
fn decode_pkcs8_private_key(pkcs8_der: &[u8]) -> Result<PrivateKey> {
if ecdsa_from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING, pkcs8_der).is_ok() {
return Ok(PrivateKey {
key_type: KeyType::EcdsaP256,
pkcs8_der: pkcs8_der.to_vec(),
});
}
if ecdsa_from_pkcs8(&ECDSA_P384_SHA384_ASN1_SIGNING, pkcs8_der).is_ok() {
return Ok(PrivateKey {
key_type: KeyType::EcdsaP384,
pkcs8_der: pkcs8_der.to_vec(),
});
}
{
use elliptic_curve::pkcs8::DecodePrivateKey;
if p521::SecretKey::from_pkcs8_der(pkcs8_der).is_ok() {
return Ok(PrivateKey {
key_type: KeyType::EcdsaP521,
pkcs8_der: pkcs8_der.to_vec(),
});
}
}
if Ed25519KeyPair::from_pkcs8(pkcs8_der).is_ok() {
return Ok(PrivateKey {
key_type: KeyType::Ed25519,
pkcs8_der: pkcs8_der.to_vec(),
});
}
{
use rsa::RsaPrivateKey;
use rsa::pkcs8::DecodePrivateKey;
use rsa::traits::PublicKeyParts;
if let Ok(rsa_key) = RsaPrivateKey::from_pkcs8_der(pkcs8_der) {
let bits = rsa_key.n().bits();
let key_type = if bits <= 2048 {
KeyType::Rsa2048
} else if bits <= 4096 {
KeyType::Rsa4096
} else {
KeyType::Rsa8192
};
return Ok(PrivateKey {
key_type,
pkcs8_der: pkcs8_der.to_vec(),
});
}
}
Err(CryptoError::PemDecode("unknown or unsupported private key type in PKCS#8".into()).into())
}
pub fn encode_certificate_pem(der: &[u8]) -> String {
let pem_obj = ::pem::Pem::new("CERTIFICATE", der.to_vec());
::pem::encode(&pem_obj)
}
pub fn parse_certs_from_pem_bundle(pem_data: &str) -> Result<Vec<Vec<u8>>> {
let pems: Vec<::pem::Pem> = ::pem::parse_many(pem_data)
.map_err(|e| CryptoError::InvalidCertificate(format!("failed to parse PEM bundle: {e}")))?;
let certs: Vec<Vec<u8>> = pems
.into_iter()
.filter(|p| p.tag() == "CERTIFICATE")
.map(|p| p.into_contents())
.collect();
if certs.is_empty() {
return Err(
CryptoError::InvalidCertificate("no certificates found in bundle".into()).into(),
);
}
Ok(certs)
}
pub fn hash_key(key: &PrivateKey) -> String {
let mut hasher = Sha256::new();
hasher.update(&key.pkcs8_der);
let digest = hasher.finalize();
hex_encode(&digest)
}
fn hex_encode(bytes: &[u8]) -> String {
let mut s = String::with_capacity(bytes.len() * 2);
for b in bytes {
s.push_str(&format!("{b:02x}"));
}
s
}
pub fn fast_hash(data: &[u8]) -> u32 {
let mut hash: u32 = 2166136261; for &byte in data {
hash ^= byte as u32;
hash = hash.wrapping_mul(16777619); }
hash
}
pub fn generate_csr(key: &PrivateKey, domains: &[String], must_staple: bool) -> Result<Vec<u8>> {
if domains.is_empty() {
return Err(
CryptoError::Signing("at least one domain is required for a CSR".into()).into(),
);
}
let key_pair = key.to_rcgen_key_pair()?;
let mut params = CertificateParams::default();
params
.distinguished_name
.push(rcgen::DnType::CommonName, domains[0].clone());
for domain in domains {
if let Ok(ip) = domain.parse::<IpAddr>() {
params.subject_alt_names.push(rcgen::SanType::IpAddress(ip));
} else if let Some(email) = domain.strip_prefix("mailto:") {
params.subject_alt_names.push(rcgen::SanType::Rfc822Name(
email.to_string().try_into().map_err(|e: rcgen::Error| {
CryptoError::Signing(format!("invalid email SAN '{email}': {e}"))
})?,
));
} else if domain.starts_with("http:") || domain.starts_with("https:") {
params
.subject_alt_names
.push(rcgen::SanType::URI(domain.clone().try_into().map_err(
|e: rcgen::Error| {
CryptoError::Signing(format!("invalid URI SAN '{domain}': {e}"))
},
)?));
} else {
params.subject_alt_names.push(rcgen::SanType::DnsName(
domain.clone().try_into().map_err(|e: rcgen::Error| {
CryptoError::Signing(format!("invalid DNS name '{domain}': {e}"))
})?,
));
}
}
if must_staple {
let oid = vec![1, 3, 6, 1, 5, 5, 7, 1, 24];
let value = vec![0x30, 0x03, 0x02, 0x01, 0x05];
let ext = CustomExtension::from_oid_content(&oid, value);
params.custom_extensions.push(ext);
}
let csr = params
.serialize_request(&key_pair)
.map_err(|e| CryptoError::Signing(format!("CSR serialization failed: {e}")))?;
Ok(csr.der().to_vec())
}
#[derive(Debug, Clone)]
pub struct StandardKeyGenerator {
pub key_type: KeyType,
}
impl Default for StandardKeyGenerator {
fn default() -> Self {
Self {
key_type: KeyType::EcdsaP256,
}
}
}
impl StandardKeyGenerator {
pub fn new(key_type: KeyType) -> Self {
Self { key_type }
}
pub fn generate_key(&self) -> Result<PrivateKey> {
generate_private_key(self.key_type)
}
}
pub fn normalize_domain(domain: &str) -> Result<String> {
idna::domain_to_ascii(domain)
.map_err(|_| CryptoError::Signing(format!("IDNA conversion failed for '{domain}'")).into())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generate_and_roundtrip_ecdsa_p256() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
assert_eq!(key.key_type(), KeyType::EcdsaP256);
let pem_str = encode_private_key_pem(&key).unwrap();
assert!(pem_str.contains("EC PRIVATE KEY"));
let decoded = decode_private_key_pem(&pem_str).unwrap();
assert_eq!(decoded.key_type(), KeyType::EcdsaP256);
}
#[test]
fn test_generate_and_roundtrip_ecdsa_p384() {
let key = generate_private_key(KeyType::EcdsaP384).unwrap();
assert_eq!(key.key_type(), KeyType::EcdsaP384);
let pem_str = encode_private_key_pem(&key).unwrap();
assert!(pem_str.contains("EC PRIVATE KEY"));
let decoded = decode_private_key_pem(&pem_str).unwrap();
assert_eq!(decoded.key_type(), KeyType::EcdsaP384);
}
#[test]
fn test_generate_and_roundtrip_ed25519() {
let key = generate_private_key(KeyType::Ed25519).unwrap();
assert_eq!(key.key_type(), KeyType::Ed25519);
let pem_str = encode_private_key_pem(&key).unwrap();
assert!(pem_str.contains("PRIVATE KEY"));
let decoded = decode_private_key_pem(&pem_str).unwrap();
assert_eq!(decoded.key_type(), KeyType::Ed25519);
}
#[test]
fn test_generate_and_roundtrip_rsa2048() {
let key = generate_private_key(KeyType::Rsa2048).unwrap();
assert_eq!(key.key_type(), KeyType::Rsa2048);
let pem_str = encode_private_key_pem(&key).unwrap();
assert!(pem_str.contains("RSA PRIVATE KEY"));
let decoded = decode_private_key_pem(&pem_str).unwrap();
assert_eq!(decoded.key_type(), KeyType::Rsa2048);
}
#[test]
fn test_hash_key_deterministic() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let h1 = hash_key(&key);
let h2 = hash_key(&key);
assert_eq!(h1, h2);
assert_eq!(h1.len(), 64); }
#[test]
fn test_encode_certificate_pem() {
let fake_der = b"not-a-real-cert";
let pem_str = encode_certificate_pem(fake_der);
assert!(pem_str.contains("CERTIFICATE"));
}
#[test]
fn test_csr_generation_ecdsa_p256() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let domains = vec!["example.com".to_string(), "www.example.com".to_string()];
let csr_der = generate_csr(&key, &domains, false).unwrap();
assert!(!csr_der.is_empty());
}
#[test]
fn test_csr_generation_with_ip() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let domains = vec!["example.com".to_string(), "192.168.1.1".to_string()];
let csr_der = generate_csr(&key, &domains, false).unwrap();
assert!(!csr_der.is_empty());
}
#[test]
fn test_csr_empty_domains_fails() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let result = generate_csr(&key, &[], false);
assert!(result.is_err());
}
#[test]
fn test_csr_with_must_staple() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let domains = vec!["example.com".to_string()];
let csr_der = generate_csr(&key, &domains, true).unwrap();
assert!(!csr_der.is_empty());
}
#[test]
fn test_standard_key_generator_default() {
let keygen = StandardKeyGenerator::default();
assert_eq!(keygen.key_type, KeyType::EcdsaP256);
let key = keygen.generate_key().unwrap();
assert_eq!(key.key_type(), KeyType::EcdsaP256);
}
#[test]
fn test_key_type_display() {
assert_eq!(KeyType::EcdsaP256.to_string(), "p256");
assert_eq!(KeyType::EcdsaP384.to_string(), "p384");
assert_eq!(KeyType::EcdsaP521.to_string(), "p521");
assert_eq!(KeyType::Rsa2048.to_string(), "rsa2048");
assert_eq!(KeyType::Rsa4096.to_string(), "rsa4096");
assert_eq!(KeyType::Rsa8192.to_string(), "rsa8192");
assert_eq!(KeyType::Ed25519.to_string(), "ed25519");
}
#[test]
fn test_key_type_default() {
assert_eq!(KeyType::default(), KeyType::EcdsaP256);
}
#[test]
fn test_private_key_serialization() {
let key = generate_private_key(KeyType::EcdsaP256).unwrap();
let json = serde_json::to_string(&key).unwrap();
let deserialized: PrivateKey = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.key_type(), key.key_type());
assert_eq!(deserialized.pkcs8_der(), key.pkcs8_der());
}
#[test]
fn test_decode_invalid_pem() {
let result = decode_private_key_pem("not valid pem data");
assert!(result.is_err());
}
#[test]
fn test_parse_certs_empty_bundle() {
let result =
parse_certs_from_pem_bundle("-----BEGIN SOMETHING-----\n-----END SOMETHING-----\n");
assert!(result.is_err());
}
}