synta-python 0.1.1

Python extension module for the synta ASN.1 library
Documentation

synta-python

Table of Contents generated with DocToc

Python extension module crate for the synta ASN.1 library.

Overview

This crate builds the _synta native extension module using PyO3 and maturin. It exposes the synta ASN.1 encoder/decoder and the synta-certificate X.509 parser to Python 3.8+ through a low-overhead Rust-native API.

The resulting module is imported as synta._synta and re-exported through the synta Python package. End-users should refer to python/README.md and docs/PYTHON_BINDINGS.md for usage documentation.

Module Structure

Source file Contents
src/lib.rs Module registration, Encoding enum, pem_to_der, der_to_pem, top-level exports
src/decoder.rs Decoder class wrapping synta::Decoder; includes decode_any_str()
src/encoder.rs Encoder class wrapping synta::Encoder
src/types.rs Python wrappers for all ASN.1 primitive types
src/error.rs SyntaError Python exception
src/certificate.rs PKI types: ObjectIdentifier, Certificate, CertificationRequest, CertificateList, OCSPResponse, PKCS loaders, synta.oids / synta.oids.attr submodules
src/pkinit.rs PKINIT classes: EncryptionKey, Checksum, KDFAlgorithmId, PKAuthenticator, AuthPack, PaPkAsReq/Rep, etc.
src/krb5.rs synta.krb5 submodule registration: Krb5PrincipalName, PKINIT classes, NT_* constants

All PyO3 bindings live directly in synta-python. The synta-certificate and synta-krb5 library crates have no PyO3 dependency; their types are wrapped here in src/certificate.rs and src/pkinit.rs respectively.

Python module hierarchy

synta                          top-level module (_synta extension)
├── Encoding                   enum: DER / BER / CER
├── SyntaError                 exception
├── Decoder / Encoder          streaming ASN.1 codec
├── Integer, OctetString, BitString, Boolean, Real, Null
├── UtcTime, GeneralizedTime
├── Utf8String, PrintableString, IA5String, NumericString,
│   TeletexString, VisibleString, GeneralString,
│   UniversalString, BmpString
├── TaggedElement, RawElement
├── ObjectIdentifier           OID type (from synta-certificate)
├── Certificate, CertificationRequest,
│   CertificateList, OCSPResponse
├── load_der_pkcs7_certificates, load_pem_pkcs7_certificates,
│   load_pkcs12_certificates, load_pkcs12_keys, read_pki_blocks
├── parse_general_names        parse SEQUENCE OF GeneralName → list[tuple[int, bytes]]
├── parse_name_attrs           parse Name DER → list[tuple[str, str]]
├── pem_to_der, der_to_pem
├── synta.general_name         GeneralName tag constants
│   ├── OTHER_NAME (0), RFC822_NAME (1), DNS_NAME (2), X400_ADDRESS (3)
│   ├── DIRECTORY_NAME (4), EDI_PARTY_NAME (5), URI (6)
│   ├── IP_ADDRESS (7), REGISTERED_ID (8)
├── synta.krb5                 Kerberos V5 / PKINIT submodule
│   ├── Krb5PrincipalName
│   ├── EncryptionKey, Checksum, KDFAlgorithmId
│   ├── IssuerAndSerialNumber, ExternalPrincipalIdentifier
│   ├── PKAuthenticator, AuthPack, PaPkAsReq
│   ├── DHRepInfo, KDCDHKeyInfo, ReplyKeyPack, PaPkAsRep
│   ├── KRB5_PRINCIPAL_NAME_OID
│   └── NT_UNKNOWN … NT_SRV_HST_DOMAIN
└── synta.oids                 well-known OID constants
    ├── ML_DSA_44/65/87, ML_KEM_512/768/1024
    ├── SLH_DSA_SHA2_*/SHAKE_* (12 variants)
    ├── ED25519, ED448
    ├── RSA_ENCRYPTION, SHA*_WITH_RSA, RSA
    ├── EC_PUBLIC_KEY, ECDSA_WITH_SHA*, ECDSA, EC_CURVE_*
    ├── SHA224/256/384/512, SHA512_224/256
    ├── SHA3_224/256/384/512, SHAKE128/256
    ├── SUBJECT_KEY_IDENTIFIER, KEY_USAGE, SUBJECT_ALT_NAME,
    │   ISSUER_ALT_NAME, BASIC_CONSTRAINTS,
    │   CRL_DISTRIBUTION_POINTS, CERTIFICATE_POLICIES,
    │   AUTHORITY_KEY_IDENTIFIER, EXTENDED_KEY_USAGE,
    │   AUTHORITY_INFO_ACCESS, CT_PRECERT_SCTS
    ├── KP_SERVER_AUTH, KP_CLIENT_AUTH, KP_CODE_SIGNING,
    │   KP_EMAIL_PROTECTION, KP_TIME_STAMPING,
    │   KP_OCSP_SIGNING, ANY_EXTENDED_KEY_USAGE
    ├── PKINIT_SAN, PKINIT_KP_CLIENT_AUTH, PKINIT_KP_KDC,
    │   PKINIT_AUTH_DATA, PKINIT_DHKEY_DATA, PKINIT_RKEY_DATA,
    │   PKINIT_KDF, PKINIT_KDF_SHA1/256/384/512
    ├── MS_SAN_UPN, MS_CERTIFICATE_TEMPLATE_NAME,
    │   MS_CERTIFICATE_TEMPLATE, MS_KP_SMARTCARD_LOGON,
    │   MS_NTDS_REPLICATION
    ├── PKCS9_EMAIL_ADDRESS, PKCS9_CONTENT_TYPE, PKCS9_MESSAGE_DIGEST,
    │   PKCS9_SIGNING_TIME, PKCS9_COUNTERSIGNATURE,
    │   PKCS9_CHALLENGE_PASSWORD, PKCS9_EXTENSION_REQUEST,
    │   PKCS9_FRIENDLY_NAME, PKCS9_LOCAL_KEY_ID
    ├── identify_signature_algorithm(oid) -> str
    ├── identify_public_key_algorithm(oid) -> str | None
    ├── ec_curve_short_name(oid) -> str | None
    ├── ec_curve_nist_name(oid) -> str | None
    ├── ec_curve_key_bits(oid) -> int | None
    ├── extension_oid_name(oid) -> str
    └── synta.oids.attr        DN attribute OIDs
        └── COMMON_NAME, COUNTRY, STATE, LOCALITY,
            ORGANIZATION, ORG_UNIT, ORG_IDENTIFIER,
            STREET, SURNAME, GIVEN_NAME, INITIALS,
            TITLE, SERIAL_NUMBER, EMAIL_ADDRESS,
            USER_ID, DOMAIN_COMPONENT

Building

The extension module is built with maturin. The workspace pyproject.toml points to this crate automatically.

# Install maturin (once)
pip install maturin

# Development install into active virtualenv
maturin develop

# Build release wheel
maturin build --release

# Install built wheel
pip install target/wheels/synta-*.whl

Requirements:

  • Rust toolchain (1.70 or later)
  • Python 3.8 or later (abi3 stable ABI; compatible with CPython 3.8–3.14+)
  • maturin 1.x

Testing

# Run the Python test suite from the workspace root
python -m pytest tests/python/

# Or via the CI helper script
./contrib/ci/local-ci.sh python-test

Dependencies

Crate Role
synta Core ASN.1 encoder/decoder
synta-certificate X.509 PKI types + OID constants
synta-krb5 Kerberos V5 / PKINIT types
pyo3 0.26 Python/Rust interop (abi3-py38 feature)

Performance Design

  • Input bytes are borrowed: PyDecoder holds a Py<PyBytes> reference and passes a &[u8] slice to the Rust decoder — no copy of the input buffer.
  • Python string caching: Certificate stores OnceLock<Py<PyString>> for each string field. The first access constructs the Python object; subsequent calls use clone_ref() (~0.3 µs for all fields together).
  • Zero-copy certificate fields: issuer, subject, and extensions are stored as raw DER byte spans inside the Rust Certificate; the Python binding wraps them in PyBytes on first access.
  • Lazy decode: field values are decoded on demand rather than at parse time.

See docs/performance.md and python/README.md for benchmark numbers.

Cargo Features

Feature Description
extension-module Required by PyO3 for native extension module builds (set via maturin)
abi3-py38 Builds against the stable Python 3.8 ABI for broad wheel compatibility

License

Licensed under either of:

at your option.