synta 0.3.1

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
"""
synta.crmf — RFC 4211 Certificate Request Message Format types.

Provides :class:`CertReqMessages` and :class:`CertReqMsg` for parsing
DER-encoded CRMF certificate request messages, along with OID constants
for CRMF registration controls.
"""

from synta import ObjectIdentifier

# ── pubMethod constants (RFC 4211 §11) ────────────────────────────────────────

PUB_METHOD_DONT_CARE: int
"""``pubMethod`` value: ``dontCare(0)`` — no publication preference."""
PUB_METHOD_X500: int
"""``pubMethod`` value: ``x500(1)`` — publish in an X.500 directory."""
PUB_METHOD_WEB: int
"""``pubMethod`` value: ``web(2)`` — publish via HTTP/HTTPS URI."""
PUB_METHOD_LDAP: int
"""``pubMethod`` value: ``ldap(3)`` — publish in an LDAP directory."""

# ── CertReqMsg ────────────────────────────────────────────────────────────────

class CertReqMsg:
    """A single CRMF certificate request message.

    ``cert_template_der`` holds the raw DER-encoded CertTemplate;
    use a ``synta.Decoder`` to inspect individual optional fields.
    ``popo_type`` and ``popo_der`` describe the proof-of-possession (if present).
    """

    @property
    def cert_req_id(self) -> int:
        """Integer certificate request ID."""
        ...

    @property
    def cert_template_der(self) -> bytes:
        """DER-encoded CertTemplate SEQUENCE."""
        ...

    @property
    def popo_type(self) -> str | None:
        """Proof-of-possession type string, or ``None`` if absent."""
        ...

    @property
    def popo_der(self) -> bytes | None:
        """DER-encoded proof-of-possession value, or ``None``."""
        ...

    @property
    def subject_der(self) -> bytes | None:
        """DER-encoded subject Name from the template, or ``None``."""
        ...

    @property
    def issuer_der(self) -> bytes | None:
        """DER-encoded issuer Name from the template, or ``None``."""
        ...

    def __repr__(self) -> str: ...

# ── CertReqMsgBuilder ─────────────────────────────────────────────────────────

class CertReqMsgBuilder:
    """Fluent builder for a single CRMF certificate request message.

    Chain setters and call :meth:`build` to obtain a :class:`CertReqMsg`.

    Example:

    ```python
    import synta, synta.crmf as crmf

    name_der = synta.NameBuilder().common_name("host.example.com").build()
    req = (
        crmf.CertReqMsgBuilder()
        .cert_req_id(0)
        .subject_name(name_der)
        .popo_ra_verified()
        .build()
    )
    ```
    """

    def __new__(cls) -> CertReqMsgBuilder: ...

    def cert_req_id(self, id: int) -> CertReqMsgBuilder:
        """Set the ``certReqId`` integer."""
        ...

    def subject_name(self, name_der: bytes) -> CertReqMsgBuilder:
        """Set the subject ``Name`` from pre-encoded DER bytes."""
        ...

    def issuer_name(self, name_der: bytes) -> CertReqMsgBuilder:
        """Set the issuer ``Name`` from pre-encoded DER bytes."""
        ...

    def public_key_der(self, spki_der: bytes) -> CertReqMsgBuilder:
        """Set the ``SubjectPublicKeyInfo`` from pre-encoded DER bytes."""
        ...

    def popo_ra_verified(self) -> CertReqMsgBuilder:
        """Set proof-of-possession to ``raVerified`` (``[0] IMPLICIT NULL``)."""
        ...

    def publication_action(self, action: int) -> CertReqMsgBuilder:
        """Set PKIPublicationInfo action (0=dontPublish, 1=pleasePublish)."""
        ...

    def add_pub_info(self, pub_method: int) -> CertReqMsgBuilder:
        """Add a SinglePubInfo with no pubLocation.

        ``pub_method`` should be one of the ``PUB_METHOD_*`` module constants.
        """
        ...

    def pub_location_uri(self, pub_method: int, uri: str) -> CertReqMsgBuilder:
        """Add a SinglePubInfo with a URI pubLocation."""
        ...

    def pub_location_rfc822(self, pub_method: int, email: str) -> CertReqMsgBuilder:
        """Add a SinglePubInfo with an rfc822Name pubLocation."""
        ...

    def pub_location_dns(self, pub_method: int, host: str) -> CertReqMsgBuilder:
        """Add a SinglePubInfo with a dNSName pubLocation."""
        ...

    def pub_location_directory_name(
        self, pub_method: int, name_der: bytes
    ) -> CertReqMsgBuilder:
        """Add a SinglePubInfo with a directoryName pubLocation (DER Name bytes)."""
        ...

    def build(self) -> CertReqMsg:
        """Encode and return the :class:`CertReqMsg`.

        :raises ValueError: if stored Name/SPKI bytes are invalid.
        """
        ...

    def __repr__(self) -> str: ...

# ── CertReqMessagesBuilder ────────────────────────────────────────────────────

class CertReqMessagesBuilder:
    """Fluent builder for a CRMF batch of certificate request messages.

    Example:

    ```python
    import synta, synta.crmf as crmf

    name_der = synta.NameBuilder().common_name("host.example.com").build()
    req = (
        crmf.CertReqMsgBuilder()
        .cert_req_id(0)
        .subject_name(name_der)
        .popo_ra_verified()
        .build()
    )
    msgs = crmf.CertReqMessagesBuilder().add_request(req).build()
    raw = msgs.to_der()
    ```
    """

    def __new__(cls) -> CertReqMessagesBuilder: ...

    def add_request(self, req: CertReqMsg) -> CertReqMessagesBuilder:
        """Append a :class:`CertReqMsg` to the batch."""
        ...

    def build(self) -> CertReqMessages:
        """Encode and return the :class:`CertReqMessages` SEQUENCE OF.

        :raises ValueError: if ASN.1 encoding fails.
        """
        ...

    def __repr__(self) -> str: ...

# ── CertReqMessages ───────────────────────────────────────────────────────────

class CertReqMessages:
    """A SEQUENCE OF CertReqMsg (the outer CRMF message container).

    Example:

    ```python
    import synta.crmf as crmf

    msgs = crmf.CertReqMessages.from_der(raw)
    for req in msgs:
        print(req.cert_req_id, req.subject_der)
    ```
    """

    @staticmethod
    def from_der(data: bytes) -> CertReqMessages:
        """Parse a DER-encoded CertReqMessages SEQUENCE."""
        ...

    def to_der(self) -> bytes:
        """Re-encode to DER bytes."""
        ...

    @property
    def requests(self) -> list[CertReqMsg]:
        """All certificate request messages in the sequence."""
        ...

    def __len__(self) -> int: ...
    def __iter__(self) -> object: ...
    def __getitem__(self, index: int) -> CertReqMsg: ...
    def __repr__(self) -> str: ...

# ── OID constants ─────────────────────────────────────────────────────────────

ID_REG_CTRL_REG_TOKEN: ObjectIdentifier
"""id-regCtrl-regToken — registration token control OID."""

ID_REG_CTRL_AUTHENTICATOR: ObjectIdentifier
"""id-regCtrl-authenticator — authenticator control OID."""

ID_REG_CTRL_PKI_PUBLICATION_INFO: ObjectIdentifier
"""id-regCtrl-pkiPublicationInfo — publication info control OID."""

ID_REG_CTRL_PKI_ARCHIVE_OPTIONS: ObjectIdentifier
"""id-regCtrl-pkiArchiveOptions — archive options control OID."""

ID_REG_CTRL_OLD_CERT_ID: ObjectIdentifier
"""id-regCtrl-oldCertID — old certificate ID control OID."""

ID_REG_CTRL_PROTOCOL_ENCR_KEY: ObjectIdentifier
"""id-regCtrl-protocolEncrKey — protocol encryption key control OID."""

ID_REG_INFO_UTF8_PAIRS: ObjectIdentifier
"""id-regInfo-utf8Pairs — UTF-8 pairs registration info OID."""

ID_REG_INFO_CERT_REQ: ObjectIdentifier
"""id-regInfo-certReq — certificate request registration info OID."""