Skip to main content

parse_certificate/
parse_certificate.rs

1//! Example: Parsing X.509 certificate structure
2//!
3//! This example demonstrates how to parse the basic structure of an
4//! X.509 certificate using Synta. It shows how to navigate through
5//! the certificate's ASN.1 structure.
6//!
7//! Note: This is a basic structural parser, not a full X.509 validator.
8//! For production use, consider using a dedicated X.509 library.
9//!
10//! Run with: cargo run --example parse_certificate
11
12use std::str::FromStr;
13use synta::{BitStringRef, Decoder, Element, Encoding, ObjectIdentifier, Sequence};
14
15fn main() {
16    println!("=== X.509 Certificate Structure Parser ===\n");
17
18    // A minimal self-signed certificate (DER-encoded)
19    // This is a simplified example certificate
20    let cert_data = create_example_certificate();
21
22    println!("Certificate size: {} bytes", cert_data.len());
23    println!(
24        "First 32 bytes: {:02X?}...\n",
25        &cert_data[..32.min(cert_data.len())]
26    );
27
28    // Parse the certificate
29    match parse_certificate(&cert_data) {
30        Ok(()) => println!("\nCertificate parsed successfully!"),
31        Err(e) => println!("\nError parsing certificate: {:?}", e),
32    }
33}
34
35fn parse_certificate(data: &[u8]) -> synta::Result<()> {
36    // X.509 Certificate structure:
37    // Certificate ::= SEQUENCE {
38    //     tbsCertificate       TBSCertificate,
39    //     signatureAlgorithm   AlgorithmIdentifier,
40    //     signatureValue       BIT STRING
41    // }
42
43    let mut decoder = Decoder::new(data, Encoding::Der);
44    let cert: Sequence = decoder.decode()?;
45    let cert_elements = cert.into_elements()?;
46
47    println!(
48        "Certificate is a SEQUENCE with {} elements",
49        cert_elements.len()
50    );
51
52    if cert_elements.len() < 3 {
53        println!("Warning: Expected at least 3 elements (tbsCertificate, signatureAlgorithm, signatureValue)");
54        return Ok(());
55    }
56
57    // Parse TBSCertificate
58    if let Element::Sequence(tbs) = &cert_elements[0] {
59        println!("\n1. TBSCertificate (To-Be-Signed Certificate):");
60        let tbs_els = tbs.clone().into_elements()?;
61        println!("   {} elements", tbs_els.len());
62        parse_tbs_certificate(&tbs_els);
63    }
64
65    // Parse SignatureAlgorithm
66    if let Element::Sequence(sig_alg) = &cert_elements[1] {
67        println!("\n2. Signature Algorithm:");
68        parse_algorithm_identifier(sig_alg);
69    }
70
71    // Parse SignatureValue
72    match &cert_elements[2] {
73        Element::BitString(sig) => {
74            println!("\n3. Signature Value:");
75            println!(
76                "   {} bytes (unused bits: {})",
77                sig.as_bytes().len(),
78                sig.unused_bits()
79            );
80        }
81        _ => println!("\n3. Signature Value: Unexpected type"),
82    }
83
84    Ok(())
85}
86
87fn parse_tbs_certificate(tbs_elements: &[Element<'_>]) {
88    // TBSCertificate has many fields, we'll show a few
89    for (i, element) in tbs_elements.iter().enumerate() {
90        match element {
91            Element::Integer(version) if i == 0 => {
92                // Version is usually [0] EXPLICIT
93                println!("   - Version/Field {}: {:?} bytes", i, version.as_bytes());
94            }
95            Element::Integer(serial) => {
96                println!("   - Serial Number: {} bytes", serial.as_bytes().len());
97            }
98            Element::Sequence(seq) => {
99                let len = seq.iter().count();
100                println!("   - SEQUENCE at position {}: {} elements", i, len);
101            }
102            _ => {}
103        }
104    }
105}
106
107fn parse_algorithm_identifier(alg: &Sequence<'_>) {
108    // AlgorithmIdentifier ::= SEQUENCE {
109    //     algorithm    OBJECT IDENTIFIER,
110    //     parameters   ANY DEFINED BY algorithm OPTIONAL
111    // }
112
113    if let Some(Ok(Element::ObjectIdentifier(oid))) = alg.iter().next() {
114        println!("   Algorithm OID: {}", oid);
115
116        // Try to identify common algorithms
117        let oid_str = oid.to_string();
118        let name = match oid_str.as_str() {
119            "1.2.840.113549.1.1.1" => "RSA Encryption",
120            "1.2.840.113549.1.1.5" => "SHA-1 with RSA",
121            "1.2.840.113549.1.1.11" => "SHA-256 with RSA",
122            "1.2.840.10045.4.3.2" => "ECDSA with SHA-256",
123            _ => "Unknown",
124        };
125        println!("   Algorithm: {}", name);
126    }
127
128    if alg.iter().count() > 1 {
129        println!("   Has parameters: yes");
130    }
131}
132
133fn create_example_certificate() -> Vec<u8> {
134    // Create a minimal certificate-like structure for demonstration
135    // This is NOT a valid certificate, just shows the structure
136
137    use synta::Integer;
138    use synta::ToDer;
139
140    // TBSCertificate (simplified)
141    let mut tbs = Sequence::new();
142    tbs.push(Element::Integer(Integer::from(2))); // Version
143    tbs.push(Element::Integer(Integer::from(123456))); // Serial number
144
145    // Signature Algorithm
146    let mut sig_alg = Sequence::new();
147    sig_alg.push(Element::ObjectIdentifier(
148        ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(),
149    )); // SHA-256 with RSA
150
151    // Signature Value
152    let signature_data = vec![0xDE, 0xAD, 0xBE, 0xEF];
153    let signature = BitStringRef::new(&signature_data, 0).unwrap();
154
155    // Certificate
156    let mut cert = Sequence::new();
157    cert.push(Element::Sequence(tbs));
158    cert.push(Element::Sequence(sig_alg));
159    cert.push(Element::BitString(signature));
160
161    // Encode
162    cert.to_der().unwrap()
163}