pe-sign 0.1.8

pe-sign is a cross-platform tool developed in Rust, designed for parsing and verifying digital signatures in PE files. It provides a simple command-line interface that supports extracting certificates, verifying digital signatures, calculating Authenticode digests, and printing certificate information.
Documentation
use std::fmt::Display;

use der::{
    oid::{
        db::rfc5280::{ID_PE_AUTHORITY_INFO_ACCESS, ID_PE_SUBJECT_INFO_ACCESS},
        AssociatedOid, ObjectIdentifier,
    },
    Decode,
};

use crate::{
    errors::{PeSignError, PeSignErrorKind, PeSignResult},
    utils::{IndentString, VecInto},
};

use super::name::GeneralName;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AuthorityInfoAccess(pub Vec<AccessDescription>);

impl AssociatedOid for AuthorityInfoAccess {
    const OID: ObjectIdentifier = ID_PE_AUTHORITY_INFO_ACCESS;
}

impl From<x509_cert::ext::pkix::AuthorityInfoAccessSyntax> for AuthorityInfoAccess {
    fn from(value: x509_cert::ext::pkix::AuthorityInfoAccessSyntax) -> Self {
        Self(value.0.vec_into())
    }
}

impl Display for AuthorityInfoAccess {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "Authority Information Access:")?;
        write!(
            f,
            "{}",
            self.0
                .iter()
                .map(|v| v.to_string())
                .collect::<Vec<String>>()
                .join("\n")
                .indent(4)
        )
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SubjectInfoAccess(pub Vec<AccessDescription>);

impl AssociatedOid for SubjectInfoAccess {
    const OID: ObjectIdentifier = ID_PE_SUBJECT_INFO_ACCESS;
}

impl From<x509_cert::ext::pkix::SubjectInfoAccessSyntax> for SubjectInfoAccess {
    fn from(value: x509_cert::ext::pkix::SubjectInfoAccessSyntax) -> Self {
        Self(value.0.vec_into())
    }
}

impl Display for SubjectInfoAccess {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        writeln!(f, "Subject Information Access:")?;
        write!(
            f,
            "{}",
            self.0
                .iter()
                .map(|v| v.to_string())
                .collect::<Vec<String>>()
                .join("\n")
                .indent(4)
        )
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AccessDescription {
    pub access_method: String,
    pub access_location: GeneralName,
}

impl From<x509_cert::ext::pkix::AccessDescription> for AccessDescription {
    fn from(value: x509_cert::ext::pkix::AccessDescription) -> Self {
        Self {
            access_method: value.access_method.to_string(),
            access_location: value.access_location.into(),
        }
    }
}

impl Display for AccessDescription {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let access_method = match self.access_method.as_str() {
            "1.3.6.1.5.5.7.48.2" => "CA Issuers",
            "1.3.6.1.5.5.7.48.1" => "OCSP",
            "1.3.6.1.5.5.7.48.3" => "Time-Stamping",
            "1.3.6.1.5.5.7.48.5" => "CA Repository",
            vv => vv,
        };
        write!(f, "{} - {}", access_method, self.access_location)
    }
}

impl AccessDescription {
    pub fn from_der(bin: &[u8]) -> Result<Self, PeSignError> {
        type Type = x509_cert::ext::pkix::AccessDescription;

        let tt = Type::from_der(bin).map_app_err(PeSignErrorKind::InvalidCertificateExtension)?;

        Ok(Self {
            access_method: tt.access_method.to_string(),
            access_location: GeneralName::from(tt.access_location),
        })
    }
}