use std::str::FromStr;
use synta::{BitStringRef, Decoder, Element, Encoding, ObjectIdentifier, Sequence};
fn main() {
println!("=== X.509 Certificate Structure Parser ===\n");
let cert_data = create_example_certificate();
println!("Certificate size: {} bytes", cert_data.len());
println!(
"First 32 bytes: {:02X?}...\n",
&cert_data[..32.min(cert_data.len())]
);
match parse_certificate(&cert_data) {
Ok(()) => println!("\nCertificate parsed successfully!"),
Err(e) => println!("\nError parsing certificate: {:?}", e),
}
}
fn parse_certificate(data: &[u8]) -> synta::Result<()> {
let mut decoder = Decoder::new(data, Encoding::Der);
let cert: Sequence = decoder.decode()?;
let cert_elements = cert.into_elements()?;
println!(
"Certificate is a SEQUENCE with {} elements",
cert_elements.len()
);
if cert_elements.len() < 3 {
println!("Warning: Expected at least 3 elements (tbsCertificate, signatureAlgorithm, signatureValue)");
return Ok(());
}
if let Element::Sequence(tbs) = &cert_elements[0] {
println!("\n1. TBSCertificate (To-Be-Signed Certificate):");
let tbs_els = tbs.clone().into_elements()?;
println!(" {} elements", tbs_els.len());
parse_tbs_certificate(&tbs_els);
}
if let Element::Sequence(sig_alg) = &cert_elements[1] {
println!("\n2. Signature Algorithm:");
parse_algorithm_identifier(sig_alg);
}
match &cert_elements[2] {
Element::BitString(sig) => {
println!("\n3. Signature Value:");
println!(
" {} bytes (unused bits: {})",
sig.as_bytes().len(),
sig.unused_bits()
);
}
_ => println!("\n3. Signature Value: Unexpected type"),
}
Ok(())
}
fn parse_tbs_certificate(tbs_elements: &[Element<'_>]) {
for (i, element) in tbs_elements.iter().enumerate() {
match element {
Element::Integer(version) if i == 0 => {
println!(" - Version/Field {}: {:?} bytes", i, version.as_bytes());
}
Element::Integer(serial) => {
println!(" - Serial Number: {} bytes", serial.as_bytes().len());
}
Element::Sequence(seq) => {
let len = seq.iter().count();
println!(" - SEQUENCE at position {}: {} elements", i, len);
}
_ => {}
}
}
}
fn parse_algorithm_identifier(alg: &Sequence<'_>) {
if let Some(Ok(Element::ObjectIdentifier(oid))) = alg.iter().next() {
println!(" Algorithm OID: {}", oid);
let oid_str = oid.to_string();
let name = match oid_str.as_str() {
"1.2.840.113549.1.1.1" => "RSA Encryption",
"1.2.840.113549.1.1.5" => "SHA-1 with RSA",
"1.2.840.113549.1.1.11" => "SHA-256 with RSA",
"1.2.840.10045.4.3.2" => "ECDSA with SHA-256",
_ => "Unknown",
};
println!(" Algorithm: {}", name);
}
if alg.iter().count() > 1 {
println!(" Has parameters: yes");
}
}
fn create_example_certificate() -> Vec<u8> {
use synta::Integer;
use synta::ToDer;
let mut tbs = Sequence::new();
tbs.push(Element::Integer(Integer::from(2))); tbs.push(Element::Integer(Integer::from(123456)));
let mut sig_alg = Sequence::new();
sig_alg.push(Element::ObjectIdentifier(
ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(),
));
let signature_data = vec![0xDE, 0xAD, 0xBE, 0xEF];
let signature = BitStringRef::new(&signature_data, 0).unwrap();
let mut cert = Sequence::new();
cert.push(Element::Sequence(tbs));
cert.push(Element::Sequence(sig_alg));
cert.push(Element::BitString(signature));
cert.to_der().unwrap()
}