use pem::Pem;
use pkcs8::der::EncodePem;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_repr::Deserialize_repr;
use serde_with::{
DeserializeAs, SerializeAs,
base64::{Base64, Standard},
formats::Padded,
serde_as,
};
use x509_cert::Certificate;
fn serialize_x509_csr<S>(
input: &x509_cert::request::CertReq,
ser: S,
) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
let encoded = input
.to_pem(pkcs8::LineEnding::LF)
.map_err(serde::ser::Error::custom)?;
Base64::<Standard, Padded>::serialize_as(&encoded, ser)
}
fn deserialize_inner_detached_sct<'de, D>(de: D) -> std::result::Result<InnerDetachedSCT, D::Error>
where
D: Deserializer<'de>,
{
let buf: Vec<u8> = Base64::<Standard, Padded>::deserialize_as(de)?;
serde_json::from_slice(&buf).map_err(serde::de::Error::custom)
}
fn deserialize_inner_detached_sct_signature<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
let buf: Vec<u8> = Base64::<Standard, Padded>::deserialize_as(de)?;
let signature_size = u16::from_be_bytes(buf[2..4].try_into().expect("unexpected length"));
let signature = buf[4..].to_vec();
if signature_size as usize != signature.len() {
return Err(serde::de::Error::custom("signature size mismatch"));
}
Ok(signature)
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateSigningCertificateRequest {
#[serde(serialize_with = "serialize_x509_csr")]
pub certificate_signing_request: x509_cert::request::CertReq,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SigningCertificate {
SignedCertificateDetachedSct(SigningCertificateDetachedSCT),
SignedCertificateEmbeddedSct(SigningCertificateEmbeddedSCT),
}
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SigningCertificateDetachedSCT {
pub chain: CertificateChain,
#[serde(deserialize_with = "deserialize_inner_detached_sct")]
pub signed_certificate_timestamp: InnerDetachedSCT,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SigningCertificateEmbeddedSCT {
pub chain: CertificateChain,
}
#[derive(Deserialize, Debug, Clone)]
pub struct CertificateChain {
pub certificates: Vec<Pem>,
}
#[serde_as]
#[derive(Deserialize, Debug, Clone)]
pub struct InnerDetachedSCT {
pub sct_version: SCTVersion,
#[serde_as(as = "Base64")]
pub id: [u8; 32],
pub timestamp: u64,
#[serde(deserialize_with = "deserialize_inner_detached_sct_signature")]
pub signature: Vec<u8>,
#[serde_as(as = "Base64")]
pub extensions: Vec<u8>,
}
#[derive(Deserialize_repr, PartialEq, Debug, Clone)]
#[repr(u8)]
pub enum SCTVersion {
V1 = 0,
}
pub struct CertificateResponse {
pub cert: Certificate,
pub chain: Vec<Certificate>,
pub detached_sct: Option<SigningCertificateDetachedSCT>,
}