synta 0.1.2

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
#!/usr/bin/env python3
"""
Example 7: OCSP response parsing.

Demonstrates: OCSPResponse.from_der, OCSPResponse.from_pem, OCSPResponse.to_pem,
and all OCSPResponse properties (status, response_type_oid, response_bytes, to_der).
"""

import synta

# Successful OCSP response (status=successful, contains BasicOCSPResponse)
_OCSP_SUCCESS_DER = bytes.fromhex(
    "308201c40a0100a08201bd308201b906092b0601050507300101048201aa3082"
    "01a630818fa216041451faf8a55a16074dc0703456a9a831e6f1f8d1b8180f32"
    "303236303331303136303033345a30643062303a300906052b0e03021a050004"
    "14bf7052c8b9c0f760c89123e099815eb2c0394226041451faf8a55a16074dc0"
    "703456a9a831e6f1f8d1b802012a8000180f32303236303130313030303030305a"
    "30110a0f32303236303130313030303030305a300d06092a864886f70d01010b"
    "050003820101004de5a70defb08fe67d2ae1c4ab1ce22db43707db4ca3b65537"
    "a99cf799acbda8194697f4aaf51ab13d7c36ff45abbff19ebd1071d329b30058"
    "025185837125cba733ae42413ab56899d408b934121b16d8325331392a343772"
    "083daa11da186476ea1fb4201c7bc1ac71d380357ff78071b18ecdbfdd6b1c0c"
    "0ab996dae5475d849d27b2c22780b4dc76371eaaaa487d11ed13d48bfd121c9f"
    "847f82ff70bf0143977d06f3f59e70cd8332976058e8dcf23bc1cd2b520ddc36"
    "5a61cc81d6e2e881719056d4db925eb4d86ab4f116f6fc376365c85912dea5b3"
    "4983cea9efe51cfbcbbabef08263aa39bc5f1742e9ecf0986b09025b56ed15a2"
    "a2f8a012fbaad5"
)

# Non-successful OCSP response: tryLater (status=3), no responseBytes
_OCSP_TRYLATER_DER = bytes.fromhex("30030a0103")


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


def demo_successful_response():
    section("Successful OCSP response")
    resp = synta.OCSPResponse.from_der(_OCSP_SUCCESS_DER)

    print(f"  status:              {resp.status}")
    print(f"  response_type_oid:   {resp.response_type_oid}")
    print(f"  response_bytes:      <{len(resp.response_bytes)} bytes>")
    print(f"  to_der():            <{len(resp.to_der())} bytes>")

    assert resp.status == "successful"
    assert resp.response_type_oid is not None
    # id-pkix-ocsp-basic = 1.3.6.1.5.5.7.48.1.1
    assert str(resp.response_type_oid) == "1.3.6.1.5.5.7.48.1.1"
    assert resp.response_bytes is not None


def demo_trylater_response():
    section("Non-successful OCSP response — tryLater")
    resp = synta.OCSPResponse.from_der(_OCSP_TRYLATER_DER)

    print(f"  status:            {resp.status}")
    print(f"  response_type_oid: {resp.response_type_oid!r}  (None for error responses)")
    print(f"  response_bytes:    {resp.response_bytes!r}  (None for error responses)")

    assert resp.status == "tryLater"
    assert resp.response_type_oid is None
    assert resp.response_bytes is None


def demo_all_status_values():
    section("All OCSP response status strings")
    status_values = [
        (0, "successful"),
        (1, "malformedRequest"),
        (2, "internalError"),
        (3, "tryLater"),
        (5, "sigRequired"),
        (6, "unauthorized"),
    ]
    for code, name in status_values:
        # Build minimal OCSPResponse DER: SEQUENCE { ENUMERATED(code) }
        der = bytes([0x30, 0x03, 0x0a, 0x01, code])
        resp = synta.OCSPResponse.from_der(der)
        print(f"  ENUMERATED({code}) → status={resp.status!r}")
        assert resp.status == name


def demo_to_der_roundtrip():
    section("to_der() round-trip")
    resp = synta.OCSPResponse.from_der(_OCSP_SUCCESS_DER)
    der2 = resp.to_der()
    assert der2 == _OCSP_SUCCESS_DER
    print("  to_der() round-trip: OK")


def demo_pem_roundtrip():
    section("from_pem / to_pem round-trip")
    resp = synta.OCSPResponse.from_der(_OCSP_SUCCESS_DER)
    pem = synta.OCSPResponse.to_pem(resp)
    assert pem.startswith(b"-----BEGIN OCSP RESPONSE-----")
    print(f"  to_pem(): {len(pem)} bytes")

    resp2 = synta.OCSPResponse.from_pem(pem)
    assert resp2.status == resp.status
    assert resp2.response_bytes == resp.response_bytes
    print("  from_pem() round-trip: OK")


def main():
    print("=" * 60)
    print("Example 7: OCSP response parsing")
    print("=" * 60)
    demo_successful_response()
    demo_trylater_response()
    demo_all_status_values()
    demo_to_der_roundtrip()
    demo_pem_roundtrip()
    print("\nAll OCSP examples completed.")


if __name__ == "__main__":
    main()