import synta
import synta.krb5 as krb5
def section(title):
print(f"\n{'─' * 60}\n{title}\n{'─' * 60}")
def demo_synta_error_class():
section("SyntaError — module exception class")
print(f" synta.SyntaError: {synta.SyntaError}")
print(f" MRO: {[c.__name__ for c in synta.SyntaError.__mro__]}")
assert issubclass(synta.SyntaError, Exception)
print(" issubclass(synta.SyntaError, Exception): True")
def demo_unexpected_eof():
section("EOFError — truncated / empty input")
try:
synta.Decoder(b"", synta.Encoding.DER).decode_integer()
print(" No error (unexpected)")
except EOFError as e:
print(f" EOFError (empty input): {e}")
try:
synta.Decoder(b"\x02", synta.Encoding.DER).decode_integer()
print(" No error (unexpected)")
except EOFError as e:
print(f" EOFError (tag only): {e}")
try:
synta.Decoder(b"\x02\x04\x01\x02", synta.Encoding.DER).decode_integer()
print(" No error (unexpected)")
except EOFError as e:
print(f" EOFError (truncated value): {e}")
try:
synta.Certificate.from_der(b"\x30\x82\x04\x00\x30")
print(" No error (unexpected)")
except (EOFError, ValueError) as e:
print(f" {type(e).__name__} (truncated certificate): {e}")
def demo_unexpected_tag():
section("ValueError — unexpected ASN.1 tag")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_boolean(True)
bool_der = enc.finish()
dec = synta.Decoder(bool_der, synta.Encoding.DER)
try:
dec.decode_integer()
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (bool as integer): {e}")
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_octet_string(b"hello")
oct_der = enc2.finish()
dec2 = synta.Decoder(oct_der, synta.Encoding.DER)
try:
dec2.decode_utf8_string()
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (octet as utf8): {e}")
def demo_invalid_encoding():
section("ValueError — DER constraint violations")
bad_bool = b"\x01\x01\x01" dec = synta.Decoder(bad_bool, synta.Encoding.DER)
try:
dec.decode_boolean()
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (non-canonical BOOLEAN): {e}")
bad_int = b"\x02\x02\x00\x01" dec2 = synta.Decoder(bad_int, synta.Encoding.DER)
try:
dec2.decode_integer()
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (non-minimal INTEGER): {e}")
def demo_integer_overflow():
section("OverflowError — Integer.to_int() and to_i128() on large values")
big_bytes = b"\x7f" + b"\xff" * 19 big = synta.Integer.from_bytes(big_bytes)
try:
big.to_int()
print(" No error (unexpected)")
except OverflowError as e:
print(f" OverflowError from to_int(): {e}")
val_128 = b"\x7f" + b"\xff" * 15
ok = synta.Integer.from_bytes(val_128)
print(f" to_i128() on 2^127-1: {ok.to_i128()}")
too_big = b"\x01" + b"\x00" * 16 huge = synta.Integer.from_bytes(too_big)
try:
huge.to_i128()
print(" No error (unexpected)")
except OverflowError as e:
print(f" OverflowError from to_i128(): {e}")
def demo_validation_errors():
section("ValueError — type constructor validation")
try:
synta.BmpString("𝄞") print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (BmpString non-BMP): {e}")
try:
synta.UniversalString.from_bytes(b"\x00\x00\x00") print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (UniversalString bad length): {e}")
try:
synta.GeneralizedTime(2026, 13, 1, 0, 0, 0, None) print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (GeneralizedTime bad month): {e}")
try:
synta.ObjectIdentifier("not.a.valid.oid.string!")
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (invalid OID string): {e}")
try:
krb5.Krb5PrincipalName("RÉALM", krb5.NT_PRINCIPAL, ["alice"])
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (Krb5PrincipalName non-ASCII realm): {e}")
try:
synta.GeneralString.from_ascii("réalm")
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (GeneralString non-ASCII): {e}")
def demo_invalid_oid():
section("ValueError — invalid OID in DER")
bad_oid = b"\x06\x02\x2b\x80" dec = synta.Decoder(bad_oid, synta.Encoding.DER)
try:
dec.decode_oid()
print(" No error (unexpected)")
except ValueError as e:
print(f" ValueError (malformed OID arc): {e}")
def demo_encoder_state_errors():
section("Encoder state — normal usage and finish() behavior")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(1)
data = enc.finish()
assert data == b"\x02\x01\x01"
print(f" Normal encode+finish: {data.hex()} (INTEGER 1)")
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_integer(2)
first = enc2.finish()
second = enc2.finish()
print(f" First finish(): {first.hex()}")
print(f" Second finish(): {second.hex()!r} (empty — encoder consumed)")
def demo_feature_gate():
section("ImportError / ValueError — feature-gated functionality")
try:
import synta
synta.Pkcs12.from_der(b"\x30\x00")
print(" Pkcs12 available")
except AttributeError:
print(" synta.Pkcs12 not available (pkcs feature not compiled)")
except (ImportError, ValueError) as e:
print(f" {type(e).__name__}: {e}")
def main():
print("=" * 60)
print("Example 20: Error handling")
print("=" * 60)
demo_synta_error_class()
demo_unexpected_eof()
demo_unexpected_tag()
demo_invalid_encoding()
demo_integer_overflow()
demo_validation_errors()
demo_invalid_oid()
demo_encoder_state_errors()
demo_feature_gate()
print("\nAll error handling examples completed.")
if __name__ == "__main__":
main()