synta 0.1.12

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


The Python package is built from three Rust cdylib crates and one shared rlib:

```
synta-python/              # Primary extension crate (cdylib → _synta)
├── Cargo.toml             # crate-type = ["cdylib"]; built by maturin
└── src/
    ├── lib.rs             # #[pymodule] entry point, Encoding enum, pem_to_der/der_to_pem
    ├── types.rs           # ASN.1 primitive type wrappers (Integer, OID, BitString, …)
    ├── decoder.rs         # PyDecoder wrapper
    ├── encoder.rs         # PyEncoder wrapper
    ├── error.rs           # SyntaError Python exception class
    ├── certificate/
    │   ├── mod.rs         # re-exports; PKI types live in synta-certificate
    │   ├── cert.rs        # PyCertificate
    │   ├── cert_builder.rs  # CertificateBuilder
    │   ├── csr_builder.rs   # CsrBuilder
    │   ├── name_builder.rs  # NameBuilder
    │   ├── pkix.rs        # CertificateList, OCSPResponse
    │   └── cms/           # synta.cms submodule (RFC 5652 / RFC 9629)
    │       ├── mod.rs     # register_cms_submodule, encode_element_opt helper
    │       ├── container.rs  # ContentInfo, IssuerAndSerialNumber
    │       ├── signed.rs  # SignedData, SignerInfo
    │       ├── enveloped.rs  # EnvelopedData, EncryptedData
    │       ├── digest.rs  # DigestedData, AuthenticatedData
    │       ├── kem.rs     # KEMRecipientInfo, CMSORIforKEMOtherInfo
    │       └── builder.rs # EnvelopedDataBuilder
    ├── ext_builders.rs    # synta.ext submodule: basic_constraints, key_usage, SKI/AKI, SAN/AIA/EKU builders
    ├── crypto.rs          # synta symmetric-crypto primitives (HMAC, PBKDF2, AES, Fernet, OTP)
    └── crypto_keys.rs     # PublicKey, PrivateKey (RSA, EC, EdDSA)

synta-python-krb5/         # Kerberos / SPNEGO extension crate (cdylib → _krb5)
├── Cargo.toml             # crate-type = ["cdylib"]; built with cargo
└── src/
    ├── lib.rs             # #[pymodule] entry point; OnceLock for ObjectIdentifier class
    ├── krb5.rs            # register_krb5_module: Krb5PrincipalName, NT_*/ETYPE_* constants
    ├── krb5_core.rs       # core Kerberos types
    ├── krb5_fast.rs       # FAST armoring types
    ├── pkinit.rs          # PKINIT classes (EncryptionKey, PKAuthenticator, AuthPack, …)
    └── spnego.rs          # register_spnego_module: NegTokenInit, NegTokenResp, NegotiationToken

synta-python-mtc/          # Merkle Tree Certificates extension crate (cdylib → _mtc)
├── Cargo.toml             # crate-type = ["cdylib"]; built with cargo
└── src/
    ├── lib.rs             # #[pymodule] entry point
    └── mtc.rs             # register_mtc_module: all MTC types

synta-python-common/       # Shared infrastructure rlib (no Python module)
├── Cargo.toml             # crate-type = ["rlib"]; statically linked into each cdylib
└── src/
    ├── lib.rs             # re-exports SyntaErr, install_submodule, opt_py_list
    ├── error.rs           # SyntaErr: orphan-rule bridge synta::Error → PyErr
    ├── submodule.rs       # install_submodule: registers PyModule in sys.modules
    └── utils.rs           # opt_py_list: Option<Vec<Py<T>>> → Option<PyList>

python/                    # Python package source (installed by maturin)
├── bench_certificate.py   # Certificate parsing benchmark (synta vs cryptography)
├── bench_x509.py          # Port of cryptography's test_x509.py benchmarks
├── bench_pkcs.py          # PKCS#7 / PKCS#12 extraction benchmark (synta vs cryptography)
├── criterion_compat.py    # Criterion-compatible sampling + JSON output (importable)
└── synta/
    ├── __init__.py        # Package exports; imports _synta first, then _krb5 and _mtc
    └── py.typed           # PEP 561 marker

pyproject.toml             # Maturin configuration (manifest-path → synta-python)
```

## Key source file roles

| Source file | Contents |
|-------------|----------|
| `synta-python/src/lib.rs` | Module registration, `Encoding` enum, `pem_to_der`, `der_to_pem`, top-level exports |
| `synta-python/src/decoder.rs` | `Decoder` class wrapping `synta::Decoder`; includes `decode_any_str()` |
| `synta-python/src/encoder.rs` | `Encoder` class wrapping `synta::Encoder` |
| `synta-python/src/types.rs` | Python wrappers for all ASN.1 primitive types |
| `synta-python/src/error.rs` | `SyntaError` Python exception (defined only in `_synta`) |
| `synta-python/src/certificate/mod.rs` | PKI types: `ObjectIdentifier`, PKCS loaders, `synta.oids` / `synta.oids.attr` submodule registration |
| `synta-python/src/certificate/cert.rs` | `Certificate` pyclass (lazy decode via OnceLock) |
| `synta-python/src/certificate/pkix.rs` | `CertificationRequest`, `CertificateList`, `OCSPResponse` pyclasses |
| `synta-python-krb5/src/lib.rs` | `_krb5` module init; caches `ObjectIdentifier` from `_synta` via `OnceLock` |
| `synta-python-krb5/src/pkinit.rs` | PKINIT classes: `EncryptionKey`, `Checksum`, `KDFAlgorithmId`, `PKAuthenticator`, `AuthPack`, `PaPkAsReq/Rep`, etc. |
| `synta-python-krb5/src/krb5.rs` | `synta.krb5` submodule: `Krb5PrincipalName`, PKINIT classes, `NT_*` constants |
| `synta-python-krb5/src/spnego.rs` | `synta.spnego` submodule: `NegTokenInit`, `NegTokenResp`, `NegotiationToken` |
| `synta-python-mtc/src/mtc.rs` | `synta.mtc` submodule: all Merkle Tree Certificate types |
| `synta-python-common/src/error.rs` | `SyntaErr` newtype: maps `synta::Error` variants to standard Python exceptions |
| `synta-python-common/src/submodule.rs` | `install_submodule`: sets `__name__`, `__package__`, `__doc__`, adds to `sys.modules` |

## Why the split

Kerberos and Merkle Tree Certificate types are not needed in most deployments.
Moving them into separate cdylibs means users who do not import `synta.krb5` or
`synta.mtc` never pay for loading those types at `import synta` time.
The `synta-python-common` rlib avoids duplicating the error-mapping and
submodule-registration boilerplate across the three cdylibs.

The `_synta.abi3.so` PyO3 bindings live in `synta-python`. The `synta-certificate`
and `synta-krb5` Rust library crates have no PyO3 dependency; their types are
wrapped in `synta-python/src/certificate/` and `synta-python-krb5/src/` respectively.

See also [Cargo Features](cargo-features.md) and [Development](development.md).