synta 0.2.6

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# PKI Workflow

This tutorial walks through a complete PKI workflow using `synta-certificate`:
parsing a certificate, checking a CRL, and inspecting an OCSP response.

## Adding the dependency

```toml
[dependencies]
synta-certificate = "0.1"
synta = "0.1"
```

The `openssl` feature is enabled by default, so no extra flags are needed for
certificate building and chain verification.  To use the NSS backend instead:

```toml
[dependencies]
synta-certificate = { version = "0.1", default-features = false, features = ["std", "derive", "nss"] }
```

## Parsing a certificate

```rust,ignore
use synta::{Decoder, Encoding};
use synta_certificate::{Certificate, format_dn, identify_signature_algorithm};

let der = std::fs::read("cert.der")?;
let mut decoder = Decoder::new(&der, Encoding::Der);
let cert: Certificate = decoder.decode()?;

let tbs = &cert.tbs_certificate;

// Serial number (eagerly decoded)
println!("Serial: {:?}", tbs.serial_number);

// Issuer and subject are stored as zero-copy RawDer<'a> spans
let issuer_str  = format_dn(tbs.issuer.as_bytes());
let subject_str = format_dn(tbs.subject.as_bytes());
println!("Issuer:  {}", issuer_str);
println!("Subject: {}", subject_str);

// Signature algorithm
let alg_name = identify_signature_algorithm(&cert.signature_algorithm.algorithm);
println!("Algorithm: {}", alg_name);
```

## Subject Alternative Names

```rust,ignore
use synta_certificate::Certificate;

let cert: Certificate = /* ... */;

for (tag, content) in cert.subject_alt_names() {
    match tag {
        2 => println!("DNS: {}", String::from_utf8_lossy(&content)),
        7 if content.len() == 4 => {
            let octets: [u8; 4] = content.try_into().unwrap();
            println!("IP: {}", std::net::Ipv4Addr::from(octets));
        }
        1 => println!("Email: {}", String::from_utf8_lossy(&content)),
        _ => println!("tag={} len={}", tag, content.len()),
    }
}
```

## Parsing DN attributes

```rust,ignore
use synta_certificate::parse_name_attrs;

let attrs = parse_name_attrs(cert.tbs_certificate.subject.as_bytes());
for (oid, value) in &attrs {
    println!("{} = {}", oid, value);
}
// e.g. "2.5.4.3 = example.com", "2.5.4.10 = Example Inc"
```

## PEM encoding and decoding

```rust,ignore
use synta_certificate::{pem_to_der, der_to_pem};

// Decode: may contain multiple blocks (e.g. a certificate chain)
let pem_bytes = std::fs::read("chain.pem")?;
let ders: Vec<Vec<u8>> = pem_to_der(&pem_bytes);

// Encode: standard RFC 7468 format, 64-char lines
let pem_output = der_to_pem("CERTIFICATE", &der_bytes);
std::fs::write("cert.pem", &pem_output)?;
```

## Parsing a CRL

```rust,ignore
use synta::{Decoder, Encoding};
use synta_certificate::crl::CertificateList;

let der = std::fs::read("revoked.crl")?;
let mut dec = Decoder::new(&der, Encoding::Der);
let crl: CertificateList = dec.decode()?;

let tbs = &crl.tbs_cert_list;
let issuer_str = format_dn(tbs.issuer.as_bytes());
println!("CRL issuer: {}", issuer_str);
println!("This update: {:?}", tbs.this_update);

let revoked = tbs.revoked_certificates.as_ref().map_or(0, |v| v.len());
println!("Revoked entries: {}", revoked);
```

## Parsing a CSR

```rust,ignore
use synta::{Decoder, Encoding};
use synta_certificate::csr::CertificationRequest;

let der = std::fs::read("request.csr")?;
let mut dec = Decoder::new(&der, Encoding::Der);
let csr: CertificationRequest = dec.decode()?;

let info = &csr.certification_request_info;
println!("Subject: {:?}", info.subject);
println!("Version: {:?}", info.version);
```

## Parsing an OCSP response

```rust,ignore
use synta::{Decoder, Encoding};
use synta_certificate::ocsp::OCSPResponse;

let der = std::fs::read("response.der")?;
let mut dec = Decoder::new(&der, Encoding::Der);
let resp: OCSPResponse = dec.decode()?;

println!("Status: {:?}", resp.response_status);
if let Some(rb) = &resp.response_bytes {
    println!("Response type OID: {:?}", rb.response_type);
}
```

## Generating a key and building a certificate

`PrivateKeyBuilder` generates keys through the active backend without exposing
backend-specific types.  It works with both the `openssl` and `nss` features:

```rust,ignore
use synta::{Integer, UtcTime};
use synta_certificate::{CertificateBuilder, PrivateKeyBuilder, x509_types::Time};

let issuer_der:  &[u8] = /* DER-encoded Name SEQUENCE */;
let subject_der: &[u8] = /* DER-encoded Name SEQUENCE */;

// Generate a P-256 key — no backend type appears in caller code
let key      = PrivateKeyBuilder::ec("P-256").generate().expect("key gen failed");
let spki_der = key.public_key_spki_der().expect("SPKI failed");
let signer   = key.as_signer("sha256");

let cert_der: Vec<u8> = CertificateBuilder::new()
    .issuer_name(issuer_der)
    .subject_name(subject_der)
    .public_key_der(&spki_der)
    .serial_number(Integer::from(1i64))
    .not_valid_before(Time::UtcTime(UtcTime::new(2024, 1, 1, 0, 0, 0).unwrap()))
    .not_valid_after(Time::UtcTime(UtcTime::new(2025, 1, 1, 0, 0, 0).unwrap()))
    .sign(signer.as_ref())
    .expect("certificate signing failed");
```

When you already hold an OpenSSL `PKey`, use `OpensslCertificateSigner` directly
(requires the `openssl` feature):

```rust,ignore
use synta_certificate::{CertificateBuilder, OpensslCertificateSigner};

let pkey: native_ossl::pkey::Pkey<native_ossl::pkey::Private> = /* existing OpenSSL private key */;
let signer = OpensslCertificateSigner::new(&pkey, "sha256");

let cert_der: Vec<u8> = CertificateBuilder::new()
    /* … set fields … */
    .sign(&signer)
    .expect("certificate signing failed");
```

For ML-DSA keys, pass an optional FIPS 204 §5.2 context string via `with_context`:

```rust,ignore
// ML-DSA key with optional FIPS 204 §5.2 context string
use synta_certificate::OpensslCertificateSigner;

let pkey: native_ossl::pkey::Pkey<native_ossl::pkey::Private> = /* ML-DSA-44/65/87 key */;
let signer = OpensslCertificateSigner::new(&pkey, "")
    .with_context(b"application-v1"); // domain-separating context; omit for default signing

let cert_der: Vec<u8> = CertificateBuilder::new()
    /* … set fields … */
    .sign(&signer)
    .expect("certificate signing failed");
```

## Building a CSR

```rust,ignore
use synta_certificate::{CsrBuilder, PrivateKeyBuilder};

let key    = PrivateKeyBuilder::rsa(3072).generate()?;
let spki   = key.public_key_spki_der()?;
let signer = key.as_signer("sha256");

let csr_der: Vec<u8> = CsrBuilder::new()
    .subject_name(subject_der)
    .public_key_der(&spki)
    .sign(signer.as_ref())
    .expect("CSR signing failed");
```

## Building a PKCS#12 archive

```rust,ignore
use synta_certificate::{Pkcs12Builder, OpensslPkcs12Encryptor};

let pfx_der: Vec<u8> = Pkcs12Builder::new()
    .certificate(&cert_der)
    .private_key(&key_der)
    .build(b"s3cr3t", &OpensslPkcs12Encryptor::new())
    .expect("PKCS#12 build failed");

std::fs::write("keystore.p12", &pfx_der)?;
```

## Loading a key from a hardware token (PKCS#11)

When private key material lives in an HSM or smart card, use
`BackendPrivateKey::from_pkcs11_uri` to obtain a key reference without
extracting the key material.  The `pkcs11-provider` OpenSSL provider (or an
equivalent NSS PKCS#11 module) must be configured in the system OpenSSL
configuration before calling this function.

```rust,ignore
use synta_certificate::{BackendPrivateKey, CertificateBuilder};

// The URI identifies the token, object label, and (optionally) a PIN.
let key = BackendPrivateKey::from_pkcs11_uri(
    "pkcs11:token=MyHSM;object=ca-signing-key;type=private?pin-value=1234"
)?;

// The public SPKI bytes are extracted from the token; private material stays
// inside the HSM for all signing operations.
let spki_der = key.public_key_spki_der()?;
let signer   = key.as_signer("sha256");

let cert_der: Vec<u8> = CertificateBuilder::new()
    .issuer_name(issuer_der)
    .subject_name(subject_der)
    .public_key_der(&spki_der)
    /* … other fields … */
    .sign(signer.as_ref())
    .expect("certificate signing failed");
```

See [PKI: Keys — PKCS#11 URI](../pki/keys.md#pkcs11-uri--hardware-token-keys) for
the URI format and structured attribute access via `Pkcs11Uri`.

## Verifying a certificate chain

See [PKI: Verification](../pki/verification.md) for the full chain verification
API including trust store setup, policy configuration, and revocation checking.

## Next steps

- [PKI: Certificate]../pki/certificate.md — full Certificate API reference
- [PKI: Keys]../pki/keys.md — public key decoding and algorithm identification
- [PKI: Extensions]../pki/extensions.md — extension access and encoding helpers
- [PKI: Verification]../pki/verification.md — RFC 5280 path validation