use crate::error::Result;
use tracing::{debug, trace};
pub fn parse_signature(signature_bytes: &[u8]) -> Result<SignatureInfo> {
trace!("Parsing {} bytes of signature data", signature_bytes.len());
if signature_bytes.len() < 20 {
return Err(crate::error::Error::Asn1Error(
"Signature too short".to_string(),
));
}
let tlv = asn1::parse_single::<asn1::Tlv>(signature_bytes)
.map_err(|e| crate::error::Error::Asn1Error(format!("Failed to parse ASN.1: {e:?}")))?;
let tag = tlv.tag();
let len = tlv.data().len();
trace!("ASN.1 tag: {tag:?}, length: {len}");
let mut algorithm = "Unknown".to_string();
let mut signer_count = 0;
let mut certificate_count = 0;
let data = tlv.data();
if data.len() > 20 {
if data[0] == 0x06 && data[1] == 0x09 {
let oid_bytes = &data[2..11];
if oid_bytes == [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02] {
debug!("Found PKCS#7 signedData OID");
if let Some(sha256_pos) = find_pattern(
data,
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01],
) {
algorithm = "SHA-256".to_string();
debug!("Found SHA-256 algorithm at position {}", sha256_pos);
}
let mut pos = 0;
while pos < data.len() - 4 {
if data[pos] == 0x30 && data[pos + 1] == 0x82 {
let len = ((data[pos + 2] as usize) << 8) | (data[pos + 3] as usize);
if len > 300 && len < 2000 {
certificate_count += 1;
}
pos += 4 + len;
} else {
pos += 1;
}
}
signer_count = 1; }
}
}
let signature_info = SignatureInfo {
format: "PKCS#7/CMS".to_string(),
size: signature_bytes.len(),
algorithm,
signer_count,
certificate_count,
};
debug!("Parsed signature: {:?}", signature_info);
Ok(signature_info)
}
fn find_pattern(data: &[u8], pattern: &[u8]) -> Option<usize> {
data.windows(pattern.len())
.position(|window| window == pattern)
}
#[derive(Debug, Clone)]
pub struct SignatureInfo {
pub format: String,
pub size: usize,
pub algorithm: String,
pub signer_count: usize,
pub certificate_count: usize,
}