synta 0.2.0

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# 27. `example_ms_pki.py` — Microsoft PKI (AD CS) extension types

[← Example index](index.md) · [example_ms_pki.py on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_ms_pki.py)

Bindings: `synta.ms_pki.MSCSTemplateV2`, `synta.ms_pki.RequestClientInfo`
and OID constants.

- Parse `MSCSTemplateV2` with major version only and with both versions; verify
  `template_id`, `template_major_version`, `template_minor_version`, and
  `to_der()` round-trip.
- Parse `RequestClientInfo` with all four fields present, with partial fields,
  and from an empty SEQUENCE.
- Print all nineteen OID constants with their dot-notation values.

## Source

```python
#!/usr/bin/env python3
"""
Example 22: Microsoft PKI (AD CS) certificate extensions.

Demonstrates: synta.ms_pki.MSCSTemplateV2, synta.ms_pki.RequestClientInfo,
and the OID constants defined in the synta.ms_pki submodule.
"""

import synta
import synta.ms_pki as ms_pki


def section(title):
    print(f"\n{'─' * 60}\n{title}\n{'─' * 60}")


# ── DER building helpers ──────────────────────────────────────

def _enc(fn):
    """Encode one element and return its DER bytes."""
    enc = synta.Encoder(synta.Encoding.DER)
    fn(enc)
    return enc.finish()


def _seq(*parts):
    """Wrap raw TLV bytes in a SEQUENCE."""
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_sequence(b"".join(parts))
    return enc.finish()


def _explicit(n, content):
    """Wrap bytes in a [n] EXPLICIT context tag (constructed)."""
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_explicit_tag(n, "Context", content)
    return enc.finish()


def _oid(dotted):
    """Encode an OID in dot-notation and return its DER bytes."""
    return _enc(lambda e: e.encode_oid(synta.ObjectIdentifier(dotted)))


def _int(n):
    """Encode a Python integer as an ASN.1 INTEGER and return DER bytes."""
    return _enc(lambda e: e.encode_integer(n))


def _utf8(s):
    """Encode a Python str as an ASN.1 UTF8String and return DER bytes."""
    return _enc(lambda e: e.encode_utf8_string(s))


# ── Pre-built DER test vectors ────────────────────────────────

# MSCSTemplateV2 — szOID_CERTIFICATE_TEMPLATE (1.3.6.1.4.1.311.21.7)
# Enterprise template OID: 1.3.6.1.4.1.311.21.8.<enterprise>.<template>
# Example uses a representative enterprise + template suffix.
_TMPL_OID_DER   = _oid("1.3.6.1.4.1.311.21.8.12345678.1")
_TMPL_MAJOR_DER = _int(100)  # templateMajorVersion = 100
_TMPL_MINOR_DER = _int(5)    # templateMinorVersion = 5  (OPTIONAL)

# MSCSTemplateV2 with major version only (minorVersion absent)
TMPL_V2_NO_MINOR_DER = _seq(_TMPL_OID_DER, _TMPL_MAJOR_DER)

# MSCSTemplateV2 with both major and minor version
TMPL_V2_FULL_DER = _seq(_TMPL_OID_DER, _TMPL_MAJOR_DER, _TMPL_MINOR_DER)

# RequestClientInfo — szOID_REQUEST_CLIENT_INFO (1.3.6.1.4.1.311.21.20)
# All four OPTIONAL fields present:
#   clientId    [0] INTEGER   = 2  (Xen auto-enrollment; placeholder)
#   machineName [1] UTF8String
#   userName    [2] UTF8String
#   processName [3] UTF8String
_CLIENT_ID_FIELD    = _explicit(0, _int(2))
_MACHINE_NAME_FIELD = _explicit(1, _utf8("MYWORKSTATION"))
_USER_NAME_FIELD    = _explicit(2, _utf8("DOMAIN\\alice"))
_PROCESS_NAME_FIELD = _explicit(3, _utf8("certreq.exe"))

REQ_CLIENT_INFO_FULL_DER = _seq(
    _CLIENT_ID_FIELD,
    _MACHINE_NAME_FIELD,
    _USER_NAME_FIELD,
    _PROCESS_NAME_FIELD,
)

# RequestClientInfo — only machineName present (all others absent)
REQ_CLIENT_INFO_PARTIAL_DER = _seq(_MACHINE_NAME_FIELD)

# RequestClientInfo — empty SEQUENCE (all OPTIONAL fields absent)
REQ_CLIENT_INFO_EMPTY_DER = b"\x30\x00"


# ── Demo functions ────────────────────────────────────────────

def demo_template_v2_major_only():
    section("MSCSTemplateV2 — major version only (minorVersion absent)")

    tmpl = ms_pki.MSCSTemplateV2.from_der(TMPL_V2_NO_MINOR_DER)

    assert str(tmpl.template_id) == "1.3.6.1.4.1.311.21.8.12345678.1"
    assert tmpl.template_major_version == 100
    assert tmpl.template_minor_version is None

    print(f"  template_id:           {tmpl.template_id}")
    print(f"  template_major_version: {tmpl.template_major_version}")
    print(f"  template_minor_version: {tmpl.template_minor_version}")
    print(f"  repr: {repr(tmpl)}")


def demo_template_v2_full():
    section("MSCSTemplateV2 — with both major and minor version")

    tmpl = ms_pki.MSCSTemplateV2.from_der(TMPL_V2_FULL_DER)

    assert str(tmpl.template_id) == "1.3.6.1.4.1.311.21.8.12345678.1"
    assert tmpl.template_major_version == 100
    assert tmpl.template_minor_version == 5

    print(f"  template_id:            {tmpl.template_id}")
    print(f"  template_major_version: {tmpl.template_major_version}")
    print(f"  template_minor_version: {tmpl.template_minor_version}")
    print(f"  repr: {repr(tmpl)}")


def demo_template_v2_roundtrip():
    section("MSCSTemplateV2 — to_der() round-trip")

    # Parse, re-encode, and re-parse.  The recovered fields must be identical.
    tmpl1 = ms_pki.MSCSTemplateV2.from_der(TMPL_V2_FULL_DER)
    der2  = tmpl1.to_der()
    tmpl2 = ms_pki.MSCSTemplateV2.from_der(der2)

    assert der2 == TMPL_V2_FULL_DER
    assert str(tmpl2.template_id)     == str(tmpl1.template_id)
    assert tmpl2.template_major_version == tmpl1.template_major_version
    assert tmpl2.template_minor_version == tmpl1.template_minor_version

    print(f"  original DER:    {TMPL_V2_FULL_DER.hex()}")
    print(f"  to_der() output: {der2.hex()}")
    print(f"  DER round-trip matches ✓")
    print(f"  template_id:            {tmpl2.template_id}")
    print(f"  template_major_version: {tmpl2.template_major_version}")
    print(f"  template_minor_version: {tmpl2.template_minor_version}")


def demo_request_client_info_full():
    section("RequestClientInfo — all four OPTIONAL fields present")

    info = ms_pki.RequestClientInfo.from_der(REQ_CLIENT_INFO_FULL_DER)

    # clientId: numeric enrollment type
    assert info.client_id == 2
    # machineName: NetBIOS / DNS machine name
    assert info.machine_name == "MYWORKSTATION"
    # userName: DOMAIN\user format
    assert info.user_name == "DOMAIN\\alice"
    # processName: enrolling process executable name
    assert info.process_name == "certreq.exe"

    print(f"  client_id:    {info.client_id}")
    print(f"  machine_name: {info.machine_name}")
    print(f"  user_name:    {info.user_name}")
    print(f"  process_name: {info.process_name}")
    print(f"  repr: {repr(info)}")


def demo_request_client_info_partial():
    section("RequestClientInfo — machineName only (other fields absent)")

    info = ms_pki.RequestClientInfo.from_der(REQ_CLIENT_INFO_PARTIAL_DER)

    assert info.client_id    is None
    assert info.machine_name == "MYWORKSTATION"
    assert info.user_name    is None
    assert info.process_name is None

    print(f"  client_id:    {info.client_id}")
    print(f"  machine_name: {info.machine_name}")
    print(f"  user_name:    {info.user_name}")
    print(f"  process_name: {info.process_name}")
    print(f"  repr: {repr(info)}")


def demo_request_client_info_empty():
    section("RequestClientInfo — empty SEQUENCE (all fields absent)")

    info = ms_pki.RequestClientInfo.from_der(REQ_CLIENT_INFO_EMPTY_DER)

    assert info.client_id    is None
    assert info.machine_name is None
    assert info.user_name    is None
    assert info.process_name is None

    print(f"  client_id:    {info.client_id}")
    print(f"  machine_name: {info.machine_name}")
    print(f"  user_name:    {info.user_name}")
    print(f"  process_name: {info.process_name}")
    print(f"  all fields None ✓")


def demo_oid_constants():
    section("OID constants — synta.ms_pki module")

    # AD CS / Certificate Services OIDs (1.3.6.1.4.1.311.21.*)
    print(f"  ID_MS_CERTSRV_CA_VERSION:        {ms_pki.ID_MS_CERTSRV_CA_VERSION}")
    print(f"  ID_MS_CERTSRV_PREVIOUS_CERT_HASH:{ms_pki.ID_MS_CERTSRV_PREVIOUS_CERT_HASH}")
    print(f"  ID_MS_CRL_VIRTUAL_BASE:          {ms_pki.ID_MS_CRL_VIRTUAL_BASE}")
    print(f"  ID_MS_CRL_NEXT_PUBLISH:          {ms_pki.ID_MS_CRL_NEXT_PUBLISH}")
    print(f"  ID_MS_ENTERPRISE_OID_ROOT:       {ms_pki.ID_MS_ENTERPRISE_OID_ROOT}")
    print(f"  ID_MS_REQUEST_CLIENT_INFO:       {ms_pki.ID_MS_REQUEST_CLIENT_INFO}")
    print(f"  ID_MS_ENCRYPTED_KEY_HASH:        {ms_pki.ID_MS_ENCRYPTED_KEY_HASH}")
    print(f"  ID_MS_CERTSRV_CROSSCA_VERSION:   {ms_pki.ID_MS_CERTSRV_CROSSCA_VERSION}")

    # Extended key usage OIDs (1.3.6.1.4.1.311.10.3.*)
    print(f"  ID_MS_KP_CA_EXCHANGE:            {ms_pki.ID_MS_KP_CA_EXCHANGE}")
    print(f"  ID_MS_KP_KEY_RECOVERY_AGENT:     {ms_pki.ID_MS_KP_KEY_RECOVERY_AGENT}")
    print(f"  ID_MS_KP_CTL_USAGE_SIGNING:      {ms_pki.ID_MS_KP_CTL_USAGE_SIGNING}")
    print(f"  ID_MS_KP_TIME_STAMP_SIGNING:     {ms_pki.ID_MS_KP_TIME_STAMP_SIGNING}")
    print(f"  ID_MS_KP_EFS_CRYPTO:             {ms_pki.ID_MS_KP_EFS_CRYPTO}")
    print(f"  ID_MS_KP_EFS_RECOVERY:           {ms_pki.ID_MS_KP_EFS_RECOVERY}")
    print(f"  ID_MS_KP_KEY_RECOVERY:           {ms_pki.ID_MS_KP_KEY_RECOVERY}")
    print(f"  ID_MS_KP_DOCUMENT_SIGNING:       {ms_pki.ID_MS_KP_DOCUMENT_SIGNING}")
    print(f"  ID_MS_KP_LIFETIME_SIGNING:       {ms_pki.ID_MS_KP_LIFETIME_SIGNING}")
    print(f"  ID_MS_AUTO_ENROLL_CTL_USAGE:     {ms_pki.ID_MS_AUTO_ENROLL_CTL_USAGE}")
    print(f"  ID_MS_APPLICATION_CERT_POLICIES: {ms_pki.ID_MS_APPLICATION_CERT_POLICIES}")

    # Verify a few known OID string values
    assert str(ms_pki.ID_MS_CERTSRV_CA_VERSION)    == "1.3.6.1.4.1.311.21.1"
    assert str(ms_pki.ID_MS_ENTERPRISE_OID_ROOT)    == "1.3.6.1.4.1.311.21.8"
    assert str(ms_pki.ID_MS_REQUEST_CLIENT_INFO)    == "1.3.6.1.4.1.311.21.20"
    assert str(ms_pki.ID_MS_KP_CTL_USAGE_SIGNING)  == "1.3.6.1.4.1.311.10.3.1"
    assert str(ms_pki.ID_MS_KP_EFS_CRYPTO)         == "1.3.6.1.4.1.311.10.3.4"
    assert str(ms_pki.ID_MS_AUTO_ENROLL_CTL_USAGE) == "1.3.6.1.4.1.311.20.1"
    print(f"  selected OID string values verified ✓")


def main():
    print("=" * 60)
    print("Example 22: Microsoft PKI (AD CS) certificate extensions")
    print("=" * 60)
    demo_template_v2_major_only()
    demo_template_v2_full()
    demo_template_v2_roundtrip()
    demo_request_client_info_full()
    demo_request_client_info_partial()
    demo_request_client_info_empty()
    demo_oid_constants()
    print("\nAll MS PKI examples completed.")


if __name__ == "__main__":
    main()
```