# 4. `parse_certificate.rs` — Parse an X.509 certificate structure
[← Example index](index.md) · [parse_certificate.rs on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/parse_certificate.rs)
Navigate an X.509 certificate's ASN.1 structure using `Decoder` and
`Element`. Extracts the TBSCertificate, issuer/subject names, serial
number, and validity period.
## Source
```rust,ignore
//! Example: Parsing X.509 certificate structure
//!
//! This example demonstrates how to parse the basic structure of an
//! X.509 certificate using Synta. It shows how to navigate through
//! the certificate's ASN.1 structure.
//!
//! Note: This is a basic structural parser, not a full X.509 validator.
//! For production use, consider using a dedicated X.509 library.
//!
//! Run with: cargo run --example parse_certificate
use std::str::FromStr;
use synta::{BitStringRef, Decoder, Element, Encoding, ObjectIdentifier, Sequence};
fn main() {
println!("=== X.509 Certificate Structure Parser ===\n");
// A minimal self-signed certificate (DER-encoded)
// This is a simplified example certificate
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())]
);
// Parse the certificate
match parse_certificate(&cert_data) {
Ok(()) => println!("\nCertificate parsed successfully!"),
Err(e) => println!("\nError parsing certificate: {:?}", e),
}
}
fn parse_certificate(data: &[u8]) -> synta::Result<()> {
// X.509 Certificate structure:
// Certificate ::= SEQUENCE {
// tbsCertificate TBSCertificate,
// signatureAlgorithm AlgorithmIdentifier,
// signatureValue BIT STRING
// }
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(());
}
// Parse TBSCertificate
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);
}
// Parse SignatureAlgorithm
if let Element::Sequence(sig_alg) = &cert_elements[1] {
println!("\n2. Signature Algorithm:");
parse_algorithm_identifier(sig_alg);
}
// Parse SignatureValue
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<'_>]) {
// TBSCertificate has many fields, we'll show a few
for (i, element) in tbs_elements.iter().enumerate() {
match element {
Element::Integer(version) if i == 0 => {
// Version is usually [0] EXPLICIT
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<'_>) {
// AlgorithmIdentifier ::= SEQUENCE {
// algorithm OBJECT IDENTIFIER,
// parameters ANY DEFINED BY algorithm OPTIONAL
// }
if let Some(Ok(Element::ObjectIdentifier(oid))) = alg.iter().next() {
println!(" Algorithm OID: {}", oid);
// Try to identify common algorithms
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> {
// Create a minimal certificate-like structure for demonstration
// This is NOT a valid certificate, just shows the structure
use synta::Encoder;
use synta::Integer;
// TBSCertificate (simplified)
let mut tbs = Sequence::new();
tbs.push(Element::Integer(Integer::from(2))); // Version
tbs.push(Element::Integer(Integer::from(123456))); // Serial number
// Signature Algorithm
let mut sig_alg = Sequence::new();
sig_alg.push(Element::ObjectIdentifier(
ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(),
)); // SHA-256 with RSA
// Signature Value
let signature_data = vec![0xDE, 0xAD, 0xBE, 0xEF];
let signature = BitStringRef::new(&signature_data, 0).unwrap();
// Certificate
let mut cert = Sequence::new();
cert.push(Element::Sequence(tbs));
cert.push(Element::Sequence(sig_alg));
cert.push(Element::BitString(signature));
// Encode
let mut encoder = Encoder::new(Encoding::Der);
encoder.encode(&cert).unwrap();
encoder.finish().unwrap()
}
```