synta 0.1.12

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


## Extension module layout

The `synta` Python package is delivered as three separate native extension
modules.  End users only need `import synta`; the subsystem modules are loaded
automatically by `python/synta/__init__.py`.

| File installed in `synta/` | Built by | Registers |
|---|---|---|
| `_synta.abi3.so` | maturin (`synta-python` crate) | Core types, X.509/PKI, CMS, OIDs, and all submodules that live in `_synta` |
| `_krb5.abi3.so` | cargo (`synta-python-krb5` crate) | `synta.krb5` and `synta.spnego` |
| `_mtc.abi3.so` | cargo (`synta-python-mtc` crate) | `synta.mtc` |

`synta-python-common` is a Rust `rlib` (no Python module of its own) that is
statically linked into each cdylib.  It provides `SyntaErr` (error bridging),
`install_submodule` (registers a `PyModule` in `sys.modules`), and `opt_py_list`.

### Type identity across module boundaries

`synta.ObjectIdentifier` and `synta.SyntaError` are defined only in `_synta.so`.
At init time each subsystem module imports `synta._synta` from `sys.modules` and
caches a reference to `ObjectIdentifier` via `OnceLock<Py<PyType>>`.  All OID
values returned from `_krb5` or `_mtc` are instances of that cached class, so
`isinstance(oid, synta.ObjectIdentifier)` returns `True` regardless of which
`.so` produced the value.

### Import order guarantee

`python/synta/__init__.py` imports `synta._synta` first, then imports
`synta._krb5` and `synta._mtc`.  The subsystem modules assert that `synta._synta`
is already in `sys.modules` and raise `ImportError` if it is not.  Importing a
subsystem module directly without first doing `import synta` is therefore not
supported.

## Crate-to-module mapping

| Rust crate | Extension module | Contributes |
|---|---|---|
| `synta` | `_synta.abi3.so` | `Encoding`, `Decoder`, `Encoder`, all primitive types |
| `synta-certificate` | `_synta.abi3.so` | `ObjectIdentifier`, `Certificate`, `CertificationRequest`, `CertificateList`, `OCSPResponse`, `OCSPRequest`, `CertID`, `PublicKey`, `PrivateKey`, `CertificateBuilder`, `CsrBuilder`, `NameBuilder`, `CertificateListBuilder`, `OCSPResponseBuilder`, `OCSPSingleResponse`, `OCSPRequestBuilder`, `OCSPCertIDSpec`, `synta.cms.SignedDataBuilder`, `synta.ext`, `synta.oids`, PKCS#7/12 loaders, `format_dn`, `format_dn_slash`, `find_extension_value`, `encode_general_names`, `signing_algorithm_der`, `key_usage_bit`, `decode_public_key_info`, `synta.pkixalgs`, `synta.ac`, `synta.crmf`, `synta.cmp`, `synta.pkcs8`, `synta.pkcs9`, `synta.kem`; `OpensslSignatureVerifier` |
| `synta-krb5` | `_krb5.abi3.so` | `synta.krb5`: `Krb5PrincipalName`, PKINIT classes, `NT_*`/`ETYPE_*` constants |
| `synta-mtc` | `_mtc.abi3.so` | `synta.mtc`: all Merkle Tree Certificate types |
| `synta-x509-verification` | `_synta.abi3.so` | `synta.x509`: `TrustStore`, `CrlStore`, `VerificationPolicy`, chain verification functions |
| `synta-python-common` | (rlib, no module) | `SyntaErr`, `install_submodule`, `opt_py_list` — statically linked into all cdylibs |

The package surface visible to Python is defined in `python/synta/__init__.py`,
which re-exports everything from `_synta` and binds `krb5`, `mtc`, and `spnego`
as attributes of the top-level `synta` namespace.

## Full module tree

```
synta                          # top-level package
├── Encoding                   # enum: DER | BER | CER
├── Decoder                    # streaming ASN.1 decoder
├── Encoder                    # ASN.1 encoder
├── SyntaError                 # exception class
├── __version__                # str, e.g. "0.1.0"
│
├── Integer                    # primitive types
├── OctetString
├── ObjectIdentifier
├── BitString
├── Boolean
├── Real
├── Null
├── UtcTime
├── GeneralizedTime
├── Utf8String
├── PrintableString
├── IA5String
├── NumericString
├── TeletexString
├── VisibleString
├── GeneralString
├── UniversalString
├── BmpString
├── TaggedElement
├── RawElement
│
├── Certificate                # PKI types
├── CertificationRequest
├── CertificateList
├── OCSPResponse
├── PublicKey                  # backend-agnostic key types (RSA, EC, EdDSA, ML-DSA, ML-KEM)
├── PrivateKey
├── CertificateBuilder         # X.509 v3 certificate builder
├── CsrBuilder                 # PKCS#10 CSR builder
├── NameBuilder                # X.509 distinguished name builder
├── CertificateListBuilder     # RFC 5280 CRL TBS builder
├── OCSPRequest                # RFC 6960 / RFC 9654 OCSP request parser
├── CertID                     # single queried certificate identity inside an OCSPRequest
├── OCSPResponseBuilder        # RFC 6960 OCSP TBS builder
├── OCSPSingleResponse         # single OCSP response entry (passed to OCSPResponseBuilder)
├── OCSPRequestBuilder         # RFC 6960 OCSP request builder
├── OCSPCertIDSpec             # single cert-ID input spec (passed to OCSPRequestBuilder)
│
├── pem_to_der()               # PEM helpers
├── der_to_pem()
│
├── create_pkcs12()                 # PKCS#12 archive builder (cipher=, mac_algorithm= kwargs)
├── load_der_pkcs7_certificates()   # PKCS#7 / PKCS#12 loaders
├── load_pem_pkcs7_certificates()
├── load_pkcs12_certificates()
├── load_pkcs12_keys()
├── load_pkcs12()
├── read_pki_blocks()
│
├── format_dn()                    # Name utility functions
├── format_dn_slash()
├── find_extension_value()
├── encode_general_names()
├── signing_algorithm_der()
├── key_usage_bit()
├── decode_public_key_info()
│
├── ext                        # synta.ext submodule — extension value builders
│   ├── basic_constraints(), key_usage()
│   ├── subject_key_identifier(), authority_key_identifier()  # require openssl feature
│   ├── KEYID_RFC5280, KEYID_RFC7093M1, …                    # key-id method constants
│   ├── KU_DIGITAL_SIGNATURE, KU_KEY_CERT_SIGN, …           # key-usage bitmask constants
│   ├── SubjectAlternativeNameBuilder (alias: SAN)
│   ├── AuthorityInformationAccessBuilder (alias: AIA)
│   ├── ExtendedKeyUsageBuilder (alias: EKU)
│   ├── NameConstraintsBuilder (alias: NC)
│   ├── CRLDistributionPointsBuilder (alias: CDP)
│   ├── IssuerAlternativeNameBuilder (alias: IAN)
│   ├── IssuingDistributionPointBuilder (alias: IDP)
│   └── CertificatePoliciesBuilder (alias: CP)
│
├── general_name               # synta.general_name submodule
│   ├── OTHER_NAME, RFC822_NAME, DNS_NAME, X400_ADDRESS
│   ├── DIRECTORY_NAME, EDI_PARTY_NAME, URI
│   ├── IP_ADDRESS, REGISTERED_ID   (integer tag constants)
│   ├── OtherName, RFC822Name, DNSName, X400Address
│   ├── DirectoryName, EDIPartyName
│   └── UniformResourceIdentifier, IPAddress, RegisteredID
│
├── oids                       # synta.oids submodule
│   ├── RSA_ENCRYPTION, SHA256_WITH_RSA, ...
│   ├── EC_PUBLIC_KEY, EC_CURVE_P256, ...
│   ├── ED25519, ED448, ML_DSA_44, ...
│   ├── SUBJECT_ALT_NAME, BASIC_CONSTRAINTS, ...
│   ├── KP_SERVER_AUTH, KP_CLIENT_AUTH, ...
│   ├── PKINIT_SAN, PKINIT_KP_CLIENT_AUTH, ...
│   ├── MS_SAN_UPN, MS_KP_SMARTCARD_LOGON, ...
│   └── attr                   # synta.oids.attr submodule
│       ├── COMMON_NAME, ORGANIZATION, COUNTRY, ...
│       └── ...
│
├── krb5                       # synta.krb5 submodule  [from _krb5.abi3.so]
│   ├── KRB5_PRINCIPAL_NAME_OID
│   ├── NT_UNKNOWN, NT_PRINCIPAL, NT_SRV_INST, ...
│   ├── Krb5PrincipalName
│   ├── EncryptionKey
│   ├── Checksum
│   ├── KDFAlgorithmId
│   ├── IssuerAndSerialNumber
│   ├── ExternalPrincipalIdentifier
│   ├── PKAuthenticator
│   ├── AuthPack
│   ├── PaPkAsReq
│   ├── DHRepInfo
│   ├── KDCDHKeyInfo
│   ├── ReplyKeyPack
│   └── PaPkAsRep
│
├── pkixalgs                   # synta.pkixalgs submodule (RFC 3279)
│   ├── DssParms, DssSigValue, EcdsaSigValue, ECParameters
│   └── ID_DSA, ID_EC_PUBLIC_KEY, ECDSA_WITH_SHA256, PRIME256V1, ...
│
├── ac                         # synta.ac submodule (RFC 5755)
│   ├── AttributeCertificate   # parse / PEM / verify_issued_by
│   ├── AttributeCertificateBuilder
│   └── ID_AT_ROLE, ID_AT_CLEARANCE, ID_PE_AC_AUDIT_IDENTITY, ...
│
├── crmf                       # synta.crmf submodule (RFC 4211)
│   ├── CertReqMessages, CertReqMsg
│   ├── CertReqMsgBuilder, CertReqMessagesBuilder
│   ├── PUB_METHOD_DONT_CARE, PUB_METHOD_X500, PUB_METHOD_WEB, PUB_METHOD_LDAP
│   └── ID_REG_CTRL_REG_TOKEN, ID_REG_CTRL_AUTHENTICATOR, ...
│
├── cmp                        # synta.cmp submodule (RFC 9810)
│   ├── CMPMessage
│   ├── CMPMessageBuilder
│   └── ID_PASSWORD_BASED_MAC, ID_DHBASED_MAC, ID_KP_CM_KGA, ...
│
├── pkcs8                      # synta.pkcs8 submodule (RFC 5958 / PKCS#8)
│   ├── OneAsymmetricKey       # parse DER-encoded private-key envelope
│   └── PrivateKeyInfo         # alias for OneAsymmetricKey
│
├── pkcs9                      # synta.pkcs9 submodule (RFC 2985 / PKCS#9)
│   ├── ID_PKCS_9, ID_EMAIL_ADDRESS, ID_CONTENT_TYPE, ID_MESSAGE_DIGEST
│   ├── ID_SIGNING_TIME, ID_COUNTERSIGNATURE, ID_CHALLENGE_PASSWORD
│   └── ID_EXTENSION_REQUEST, ID_FRIENDLY_NAME, ID_LOCAL_KEY_ID, ...
│
├── kem                        # synta.kem submodule (RFC 9629 / FIPS 203)
│   ├── KEMRecipientInfo       # KEM recipient structure in CMS EnvelopedData
│   ├── CMSORIforKEMOtherInfo  # KDF input structure for KEMRecipientInfo
│   ├── ID_ML_KEM_512, ID_ML_KEM_768, ID_ML_KEM_1024
│   └── ID_ORI, ID_ORI_KEM
│
│
├── cms                        # synta.cms submodule — CMS message types
│   ├── ContentInfo            # CMS ContentInfo wrapper; from_der entry point
│   ├── SignedData             # RFC 5652 §5 — parse existing signed messages
│   ├── SignerInfo             # per-signer information within a SignedData
│   ├── SignedDataBuilder      # fluent builder — construct and sign new SignedData
│   ├── DigestedData           # RFC 5652 §7
│   ├── AuthenticatedData      # RFC 5652 §9
│   ├── EnvelopedData          # RFC 5652 §6
│   ├── EnvelopedDataBuilder   # fluent builder for encrypted CMS messages
│   └── EncryptedData          # RFC 5652 §8
├── spnego                     # synta.spnego submodule (RFC 4178)  [from _krb5.abi3.so]
│   ├── NegTokenInit           # initiator proposal (mech_types, mech_token, …)
│   ├── NegTokenResp           # acceptor response (neg_state, supported_mech, …)
│   ├── NegotiationToken       # CHOICE wrapper; from_der handles GSSAPI 0x60 form
│   ├── NEG_STATE_ACCEPT_COMPLETED, NEG_STATE_ACCEPT_INCOMPLETE
│   ├── NEG_STATE_REJECT, NEG_STATE_REQUEST_MIC
│   └── SPNEGO_OID             # "1.3.6.1.5.5.2"
│
├── ms_pki                     # synta.ms_pki submodule (Microsoft AD CS)
│   ├── MSCSTemplateV2         # id-ms-certificate-template (OID 1.3.6.1.4.1.311.21.7)
│   ├── RequestClientInfo      # id-ms-request-Client-Info (OID 1.3.6.1.4.1.311.21.20)
│   └── ID_MS_CERTSRV_CA_VERSION, ID_MS_KP_CA_EXCHANGE, ID_MS_KP_EFS_CRYPTO, …
│
├── mtc                        # synta.mtc submodule  [from _mtc.abi3.so]
│   ├── ProofNode, Subtree, SubtreeProof, InclusionProof
│   ├── LogID, CosignerID, Checkpoint, SubtreeSignature
│   ├── TbsCertificateLogEntry, MerkleTreeCertEntry
│   ├── LandmarkID, StandaloneCertificate, LandmarkCertificate
│   └── (all classes parsed via from_der; names are raw DER, pass to parse_name_attrs)
│
└── x509                       # synta.x509 submodule (RFC 5280 / CABF path validation)
    ├── TrustStore             # trusted root CA store (DER bytes)
    ├── CrlStore               # CRL revocation checking store (DER bytes)
    ├── OcspStore              # pre-fetched OCSP response store (DER bytes)
    ├── VerificationPolicy     # server_names, name_match, validation_time, max_chain_depth, profile
    ├── X509VerificationError  # raised on any chain or policy failure
    ├── verify_server_certificate(leaf, intermediates, store, policy, crls=None, ocsp=None) → list[bytes]
    └── verify_client_certificate(leaf, intermediates, store, policy, crls=None, ocsp=None) → list[bytes]
```