import synta
def section(title):
print(f"\n{'─' * 60}\n{title}\n{'─' * 60}")
def demo_encode_set():
section("encode_set — build a SET containing two PrintableStrings")
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_printable_string("Alice")
inner.encode_printable_string("Bob")
inner_bytes = inner.finish()
outer = synta.Encoder(synta.Encoding.DER)
outer.encode_set(inner_bytes)
data = outer.finish()
print(f" SET DER: {data.hex()}")
assert data[0] == 0x31
dec = synta.Decoder(data, synta.Encoding.DER)
child = dec.decode_set()
s1 = child.decode_printable_string()
s2 = child.decode_printable_string()
assert child.is_empty()
print(f" Decoded: {s1.as_str()!r}, {s2.as_str()!r}")
def demo_encode_implicit_tag():
section("encode_implicit_tag — [0] IMPLICIT IA5String dNSName")
name = b"example.com"
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_implicit_tag(2, "Context", False, name) data = enc.finish()
print(f" DER: {data.hex()}")
assert data[0] == 0x82 assert data[1] == len(name)
assert data[2:] == name
print(f" Tag: 0x{data[0]:02x} (Context[2] primitive)")
dec = synta.Decoder(data, synta.Encoding.DER)
child = dec.decode_implicit_tag(2, "Context")
raw = child.remaining_bytes()
assert raw == name
print(f" Decoded dNSName: {raw.decode('ascii')!r}")
def demo_encode_explicit_tag():
section("encode_explicit_tag — nested SEQUENCE { [0] EXPLICIT SEQUENCE { INTEGER } }")
int_enc = synta.Encoder(synta.Encoding.DER)
int_enc.encode_integer(42)
int_bytes = int_enc.finish()
seq_enc = synta.Encoder(synta.Encoding.DER)
seq_enc.encode_sequence(int_bytes)
seq_bytes = seq_enc.finish()
tag_enc = synta.Encoder(synta.Encoding.DER)
tag_enc.encode_explicit_tag(0, "Context", seq_bytes)
tag_bytes = tag_enc.finish()
outer_enc = synta.Encoder(synta.Encoding.DER)
outer_enc.encode_sequence(tag_bytes)
data = outer_enc.finish()
print(f" SEQUENCE {{ [0] EXPLICIT SEQUENCE {{ INTEGER 42 }} }}")
print(f" DER: {data.hex()}")
dec = synta.Decoder(data, synta.Encoding.DER)
outer = dec.decode_sequence()
tagged = outer.decode_explicit_tag(0) inner = tagged.decode_sequence()
val = inner.decode_integer()
assert val.to_int() == 42
print(f" Decoded INTEGER: {val.to_int()}")
print(" Nested encoding/decoding: OK")
def demo_object_variants():
section("_object encode variants — typed objects from decode")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(7)
enc.encode_boolean(True)
enc.encode_octet_string(b"hi")
enc.encode_bit_string(synta.BitString(b"\xff", 0))
enc.encode_null()
enc.encode_utf8_string("test")
enc.encode_printable_string("ok")
enc.encode_ia5_string("ia5")
enc.encode_numeric_string("123")
enc.encode_teletex_string(b"teletex")
enc.encode_visible_string("visible")
enc.encode_general_string(b"general")
enc.encode_universal_string("uni")
enc.encode_bmp_string("bmp")
enc.encode_oid(synta.ObjectIdentifier("1.2.3"))
enc.encode_utc_time(synta.UtcTime(2026, 1, 1, 0, 0, 0))
enc.encode_generalized_time(synta.GeneralizedTime(2026, 1, 1, 0, 0, 0, None))
original = enc.finish()
dec = synta.Decoder(original, synta.Encoding.DER)
obj_int = dec.decode_integer()
obj_bool = dec.decode_boolean()
obj_oct = dec.decode_octet_string()
obj_bit = dec.decode_bit_string()
obj_null = dec.decode_null()
obj_utf8 = dec.decode_utf8_string()
obj_print = dec.decode_printable_string()
obj_ia5 = dec.decode_ia5_string()
obj_num = dec.decode_numeric_string()
obj_tel = dec.decode_teletex_string()
obj_vis = dec.decode_visible_string()
obj_gen = dec.decode_general_string()
obj_uni = dec.decode_universal_string()
obj_bmp = dec.decode_bmp_string()
obj_oid = dec.decode_oid()
obj_utc = dec.decode_utc_time()
obj_gt = dec.decode_generalized_time()
assert dec.is_empty()
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_integer_object(obj_int)
enc2.encode_boolean_object(obj_bool)
enc2.encode_octet_string_object(obj_oct)
enc2.encode_bit_string_object(obj_bit)
enc2.encode_null_object(obj_null)
enc2.encode_utf8_string_object(obj_utf8)
enc2.encode_printable_string_object(obj_print)
enc2.encode_ia5_string_object(obj_ia5)
enc2.encode_numeric_string_object(obj_num)
enc2.encode_teletex_string_object(obj_tel)
enc2.encode_visible_string_object(obj_vis)
enc2.encode_general_string_object(obj_gen)
enc2.encode_universal_string_object(obj_uni)
enc2.encode_bmp_string_object(obj_bmp)
enc2.encode_oid_object(obj_oid)
enc2.encode_utc_time_object(obj_utc)
enc2.encode_generalized_time_object(obj_gt)
reconstructed = enc2.finish()
assert reconstructed == original, (
f"Mismatch:\n orig: {original.hex()}\n got: {reconstructed.hex()}"
)
print(f" All _object variants round-trip ({len(original)} bytes): OK")
def demo_application_and_private_tags():
section("encode_explicit_tag — Application and Private tag classes")
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_integer(1)
inner_bytes = inner.finish()
for tag_class in ("Application", "Private"):
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_explicit_tag(3, tag_class, inner_bytes)
data = enc.finish()
print(f" {tag_class}[3] EXPLICIT INTEGER 1: {data.hex()}")
try:
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_explicit_tag(0, "BadClass", inner_bytes)
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError for unknown tag class: {e}")
def main():
print("=" * 60)
print("Example 17: Advanced Encoder operations")
print("=" * 60)
demo_encode_set()
demo_encode_implicit_tag()
demo_encode_explicit_tag()
demo_object_variants()
demo_application_and_private_tags()
print("\nAll advanced Encoder examples completed.")
if __name__ == "__main__":
main()