synta 0.2.2

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
//! Generate an INVALID test certificate for testing ASN.1 parsing
//!
//! This generates a certificate with a structurally valid ASN.1 encoding
//! but with a cryptographically invalid public key and signature.
//! It is useful for testing that ASN.1 parsers can handle edge cases.
//!
//! The output files are invalid_test_certificate.{pem,der}
//!
//! For valid test certificates, use OpenSSL:
//!   openssl req -x509 -newkey rsa:2048 -nodes \
//!     -keyout test_key.pem -out test_certificate.pem \
//!     -days 365 -subj "/CN=Test CA"
//!
//! Run with: cargo run --example generate_test_cert

use std::str::FromStr;
use synta::{BitStringRef, Decoder, Element, Encoding, Integer, ObjectIdentifier, Sequence, ToDer};
use synta_certificate::NameBuilder;

fn main() {
    // Build a valid certificate structure programmatically
    // TBSCertificate (simplified)
    let mut tbs = Sequence::new();

    // Version [0] EXPLICIT INTEGER 2 (v3)
    let version_tag = synta::Tag::context_specific_constructed(0);
    let version_element = Box::new(Element::Integer(Integer::from(2)));
    tbs.push(Element::Tagged(version_tag, version_element));

    // Serial number
    tbs.push(Element::Integer(Integer::from(1)));

    // Signature algorithm
    let mut sig_alg = Sequence::new();
    sig_alg.push(Element::ObjectIdentifier(
        ObjectIdentifier::from_str("1.2.840.113549.1.1.11").unwrap(),
    ));
    tbs.push(Element::Sequence(sig_alg.clone()));

    // Issuer (minimal) — built with NameBuilder
    let issuer_bytes = NameBuilder::new().common_name("Test CA").build().unwrap();
    let mut issuer_dec = Decoder::new(&issuer_bytes, Encoding::Der);
    let issuer_element: Element = issuer_dec.decode().unwrap();
    tbs.push(issuer_element.clone());

    // Validity
    let mut validity = Sequence::new();
    validity.push(Element::UtcTime(
        synta::UtcTime::new(2023, 1, 1, 0, 0, 0).unwrap(),
    ));
    validity.push(Element::UtcTime(
        synta::UtcTime::new(2024, 1, 1, 0, 0, 0).unwrap(),
    ));
    tbs.push(Element::Sequence(validity));

    // Subject (same as issuer)
    tbs.push(issuer_element);

    // SubjectPublicKeyInfo
    let mut spki = Sequence::new();
    let mut spki_alg = Sequence::new();
    let spki_key_data = vec![0x30, 0x09, 0x02, 0x02, 0x00, 0xFF, 0x02, 0x01, 0x03];
    spki_alg.push(Element::ObjectIdentifier(
        ObjectIdentifier::from_str("1.2.840.113549.1.1.1").unwrap(),
    ));
    spki.push(Element::Sequence(spki_alg));
    spki.push(Element::BitString(
        BitStringRef::new(&spki_key_data, 0).unwrap(),
    ));
    tbs.push(Element::Sequence(spki));

    // Build full certificate
    let mut cert = Sequence::new();
    let sig_data = vec![
        0x30, 0x06, // SEQUENCE, length 6
        0x02, 0x01, 0x42, // INTEGER 66
        0x02, 0x01, 0x43, // INTEGER 67
    ];
    cert.push(Element::Sequence(tbs));
    cert.push(Element::Sequence(sig_alg));
    cert.push(Element::BitString(BitStringRef::new(&sig_data, 0).unwrap()));

    // Encode to DER
    let der_data = cert.to_der().unwrap();

    // Write to file (as invalid certificate)
    std::fs::create_dir_all("tests/vectors").unwrap();
    std::fs::write("tests/vectors/invalid_test_certificate.der", &der_data).unwrap();

    // Also create PEM version
    let pem_data = synta_certificate::der_to_pem("CERTIFICATE", &der_data);

    std::fs::write("tests/vectors/invalid_test_certificate.pem", pem_data).unwrap();

    println!(
        "Generated tests/vectors/invalid_test_certificate.der ({} bytes)",
        der_data.len()
    );
    println!("Generated tests/vectors/invalid_test_certificate.pem");
    println!("\nNOTE: This certificate has a structurally valid ASN.1 encoding");
    println!("      but an invalid public key and signature (for testing purposes).");
}