use bon::Builder;
use const_oid::ObjectIdentifier;
use time::Duration;
use time::OffsetDateTime;
use x509_cert::name::RdnSequence;
use super::extensions::ToAndFromX509Extension;
pub use crate::cert::extensions::ExtendedKeyUsage;
pub use crate::cert::extensions::ExtendedKeyUsageOption;
use crate::error::CertKitError;
use crate::key::PublicKey;
#[derive(Clone, Debug, Builder)]
pub struct CertificationRequestInfo {
pub subject: DistinguishedName,
pub subject_public_key: PublicKey,
#[builder(default)]
pub usages: Vec<ExtendedKeyUsageOption>,
#[builder(default)]
pub is_ca: bool,
#[builder(default)]
pub extensions: Vec<ExtensionParam>,
}
#[derive(Clone, Debug, Builder, Default)]
pub struct DistinguishedName {
pub common_name: String,
pub country: Option<String>,
pub state: Option<String>,
pub locality: Option<String>,
pub organization: Option<String>,
pub organization_unit: Option<String>,
}
impl DistinguishedName {
pub fn as_x509_name(&self) -> x509_cert::name::DistinguishedName {
use core::str::FromStr;
let rfc4514_name = format!(
"CN={},OU={},O={},L={},ST={},C={}",
self.common_name,
self.organization_unit.clone().unwrap_or_default(),
self.organization.clone().unwrap_or_default(),
self.locality.clone().unwrap_or_default(),
self.state.clone().unwrap_or_default(),
self.country.clone().unwrap_or_default()
);
RdnSequence::from_str(&rfc4514_name).unwrap()
}
pub fn from_x509_name(x509dn: &x509_cert::name::DistinguishedName) -> Self {
let mut common_name = String::new();
for rdn in x509dn.0.iter() {
for attr in rdn.0.iter() {
if attr.oid.to_string() == "2.5.4.3" {
if let Ok(s) = attr.value.decode_as::<String>() {
common_name = s.to_string();
} else {
panic!("Common name is not a PrintableString");
}
}
}
}
DistinguishedName {
common_name,
organization_unit: None,
organization: None,
locality: None,
state: None,
country: None,
}
}
}
#[derive(Clone, Debug)]
pub struct Validity {
pub not_before: OffsetDateTime,
pub not_after: OffsetDateTime,
}
impl Validity {
pub fn for_days(days: i64) -> Self {
let now = OffsetDateTime::now_utc();
Self {
not_before: now,
not_after: now + Duration::days(days),
}
}
}
#[derive(Clone, Debug)]
pub struct ExtensionParam {
pub oid: ObjectIdentifier,
pub critical: bool,
pub value: Vec<u8>,
}
impl ExtensionParam {
pub fn from_extension<E: ToAndFromX509Extension>(extension: E, critical: bool) -> Self {
let value = extension
.to_x509_extension_value()
.unwrap_or_else(|_| vec![]);
Self {
oid: E::OID,
critical,
value,
}
}
pub fn to_extension<E: ToAndFromX509Extension>(&self) -> Result<E, CertKitError> {
E::from_x509_extension_value(&self.value)
}
}