#[cfg(feature = "x509-parser")]
use crate::{DistinguishedName, SanType};
#[cfg(feature = "pem")]
use pem::Pem;
use std::hash::Hash;
use crate::{Certificate, CertificateParams, PublicKeyData, RcgenError, SignatureAlgorithm};
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PublicKey {
raw: Vec<u8>,
alg: &'static SignatureAlgorithm,
}
impl PublicKeyData for PublicKey {
fn alg(&self) -> &SignatureAlgorithm {
self.alg
}
fn raw_bytes(&self) -> &[u8] {
&self.raw
}
}
pub struct CertificateSigningRequest {
pub params: CertificateParams,
pub public_key: PublicKey,
}
impl CertificateSigningRequest {
#[cfg(all(feature = "pem", feature = "x509-parser"))]
pub fn from_pem(pem_str: &str) -> Result<Self, RcgenError> {
let csr = pem::parse(pem_str).or(Err(RcgenError::CouldNotParseCertificationRequest))?;
Self::from_der(csr.contents())
}
#[cfg(feature = "x509-parser")]
pub fn from_der(csr: &[u8]) -> Result<Self, RcgenError> {
use x509_parser::prelude::FromDer;
let csr = x509_parser::certification_request::X509CertificationRequest::from_der(csr)
.map_err(|_| RcgenError::CouldNotParseCertificationRequest)?
.1;
csr.verify_signature()
.map_err(|_| RcgenError::RingUnspecified)?;
let alg_oid = csr
.signature_algorithm
.algorithm
.iter()
.ok_or(RcgenError::CouldNotParseCertificationRequest)?
.collect::<Vec<_>>();
let alg = SignatureAlgorithm::from_oid(&alg_oid)?;
let info = &csr.certification_request_info;
let mut params = CertificateParams::default();
params.alg = alg;
params.distinguished_name = DistinguishedName::from_name(&info.subject)?;
let raw = info.subject_pki.subject_public_key.data.to_vec();
if let Some(extensions) = csr.requested_extensions() {
for ext in extensions {
match ext {
x509_parser::extensions::ParsedExtension::SubjectAlternativeName(san) => {
for name in &san.general_names {
params
.subject_alt_names
.push(SanType::try_from_general(name)?);
}
},
_ => return Err(RcgenError::UnsupportedExtension),
}
}
}
Ok(Self {
params,
public_key: PublicKey { alg, raw },
})
}
pub fn serialize_der_with_signer(&self, ca: &Certificate) -> Result<Vec<u8>, RcgenError> {
self.params.serialize_der_with_signer(&self.public_key, ca)
}
#[cfg(feature = "pem")]
pub fn serialize_pem_with_signer(&self, ca: &Certificate) -> Result<String, RcgenError> {
let contents = self
.params
.serialize_der_with_signer(&self.public_key, ca)?;
let p = Pem::new("CERTIFICATE", contents);
Ok(pem::encode_config(&p, crate::ENCODE_CONFIG))
}
}