synta 0.1.9

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
#!/usr/bin/env python3
"""
Example 13: UtcTime and GeneralizedTime.

Demonstrates: UtcTime(…), UtcTime properties (year, month, day, hour, minute, second),
GeneralizedTime(…), GeneralizedTime properties,
Encoder.encode_utc_time, Encoder.encode_utc_time_object,
Encoder.encode_generalized_time, Encoder.encode_generalized_time_object,
Decoder.decode_utc_time, Decoder.decode_generalized_time.
"""

import synta


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


def demo_utctime_properties():
    section("UtcTime — constructor and all properties")
    # UtcTime is defined as YY[MM[DD[HH[MM[SS]]]]]Z
    # Year range 00–49 → 2000–2049, 50–99 → 1950–1999
    t = synta.UtcTime(2026, 3, 10, 14, 30, 0)
    print(f"  UtcTime(2026,3,10,14,30,0)")
    print(f"  year:   {t.year}")
    print(f"  month:  {t.month}")
    print(f"  day:    {t.day}")
    print(f"  hour:   {t.hour}")
    print(f"  minute: {t.minute}")
    print(f"  second: {t.second}")
    print(f"  str:    {t}")

    assert t.year == 2026
    assert t.month == 3
    assert t.day == 10
    assert t.hour == 14
    assert t.minute == 30
    assert t.second == 0


def demo_generalizedtime_properties():
    section("GeneralizedTime — constructor and all properties")
    gt = synta.GeneralizedTime(2026, 3, 10, 14, 30, 59, None)
    print(f"  GeneralizedTime(2026,3,10,14,30,59)")
    print(f"  year:   {gt.year}")
    print(f"  month:  {gt.month}")
    print(f"  day:    {gt.day}")
    print(f"  hour:   {gt.hour}")
    print(f"  minute: {gt.minute}")
    print(f"  second: {gt.second}")
    print(f"  str:    {gt}")

    assert gt.year == 2026
    assert gt.second == 59


def demo_utctime_roundtrip():
    section("encode_utc_time / decode_utc_time round-trip")
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_utc_time(synta.UtcTime(2026, 6, 1, 0, 0, 0))
    data = enc.finish()
    print(f"  DER: {data.hex()}")
    print(f"  tag: 0x{data[0]:02x} (UTCTime = 0x17)")
    assert data[0] == 0x17

    dec = synta.Decoder(data, synta.Encoding.DER)
    t = dec.decode_utc_time()
    print(f"  Decoded: year={t.year} month={t.month} day={t.day}")
    assert t.year == 2026 and t.month == 6 and t.day == 1
    print("  UTCTime encode/decode round-trip: OK")


def demo_utctime_object_variant():
    section("encode_utc_time_object — encode a UtcTime instance")
    t = synta.UtcTime(2027, 1, 1, 12, 0, 0)
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_utc_time_object(t)
    data = enc.finish()

    dec = synta.Decoder(data, synta.Encoding.DER)
    t2 = dec.decode_utc_time()
    assert t2.year == t.year and t2.month == t.month
    print(f"  encode_utc_time_object → {str(t2)}: OK")


def demo_generalizedtime_roundtrip():
    section("encode_generalized_time / decode_generalized_time round-trip")
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_generalized_time(synta.GeneralizedTime(2049, 12, 31, 23, 59, 59, None))
    data = enc.finish()
    print(f"  DER: {data.hex()}")
    print(f"  tag: 0x{data[0]:02x} (GeneralizedTime = 0x18)")
    assert data[0] == 0x18

    dec = synta.Decoder(data, synta.Encoding.DER)
    gt = dec.decode_generalized_time()
    print(f"  Decoded: {gt}")
    assert gt.year == 2049 and gt.month == 12 and gt.second == 59
    print("  GeneralizedTime encode/decode round-trip: OK")


def demo_generalizedtime_object_variant():
    section("encode_generalized_time_object — encode a GeneralizedTime instance")
    gt = synta.GeneralizedTime(2030, 7, 4, 8, 30, 0, None)
    enc = synta.Encoder(synta.Encoding.DER)
    enc.encode_generalized_time_object(gt)
    data = enc.finish()

    dec = synta.Decoder(data, synta.Encoding.DER)
    gt2 = dec.decode_generalized_time()
    assert gt2.year == gt.year and gt2.month == gt.month
    print(f"  encode_generalized_time_object → {str(gt2)}: OK")


def demo_cert_validity_parsing():
    section("Real-world cert validity uses UTCTime / GeneralizedTime")
    import base64
    # Self-signed RSA cert with UTCTime validity
    der = base64.b64decode(
        "MIIDiTCCAnGgAwIBAgIUXhaeS3ad5SJp60GRJU73OQaO0xkwDQYJKoZIhvcNAQEL"
        "BQAwVDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJh"
        "bmNpc2NvMQ0wCwYDVQQKDARUZXN0MREwDwYDVQQDDAh0ZXN0LmNvbTAeFw0yNjAy"
        "MjMxMDU0MzRaFw0yNzAyMjMxMDU0MzRaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQI"
        "DAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwEVGVzdDERMA8G"
        "A1UEAwwIdGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP"
        "9oir0NwIXFZ6gOUo//akzjNjvUhA/V1KSUY0L/iXOGWRHFcdcf4gVhoCgR+DgCV6"
        "bJKKrYPIvfEwmd8DdpPj1WU4Dztb4NNLgxquFZym2Swe0xDLQdtWoIQYerF/ER8D"
        "9Pk0qQ5QVaCO+KB3UKyXiJwcTc/LJnDqEX24mrf0ZH/HqB2GsUE3aI9aW5Lgwm9A"
        "7+gV7FrumaT7fQqpfNucWwlXU2SIRm//JKUrT0MGrh99vmmkGRZK+c9wLfIK+pny"
        "UQxSD1E395bpQTqTWIfcMWti6af3ix3GsWeoXwY+GDfZlZ1w22GjLmSgg1RMhhKZ"
        "9l+QFnI/GtmiXX2pCRZfAgMBAAGjUzBRMB0GA1UdDgQWBBRCjPvAUpiRe0Zs6DTL"
        "K+KLoTZfezAfBgNVHSMEGDAWgBRCjPvAUpiRe0Zs6DTLK+KLoTZfezAPBgNVHRMB"
        "Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQC+xBpTScGlcZGYvwtWLZuF2qRu"
        "o9xhYzHXgIDJglXZ8i70O+ut2WRyI9RJOSMsa7BI2qmc87Ki9ZMCO2QIMQCQo7cB"
        "kZtQvK8iGGHhSwepMORekzdbfUUs7N4YEM3Xako1+4RzL+T1Z3qzQ6nrnQ+gYyQo"
        "GiIFKbYZONu2OlqXGQe5LPwbsPU52GUbttkxodaHgCdP7yKO/l3sDifXpaFEXJhY"
        "5RZqgSG77jymh8YKcY0X9J53OtP1So/IOS1Za137k+eYci6iCB4w511qEhSRZdCy"
        "+3NEoGrBearMcJHttGbMplR6TU6fDFRIUAdelPdWfpfmtl1iElRDwNdQkBBR"
    )
    cert = synta.Certificate.from_der(der)
    print(f"  not_before string: {cert.not_before}")
    print(f"  not_after  string: {cert.not_after}")
    # Certificate not_before/not_after are returned as formatted strings


def main():
    print("=" * 60)
    print("Example 13: UtcTime and GeneralizedTime")
    print("=" * 60)
    demo_utctime_properties()
    demo_generalizedtime_properties()
    demo_utctime_roundtrip()
    demo_utctime_object_variant()
    demo_generalizedtime_roundtrip()
    demo_generalizedtime_object_variant()
    demo_cert_validity_parsing()
    print("\nAll time type examples completed.")


if __name__ == "__main__":
    main()