import base64
import synta
import synta.oids as oids
def test_integer_decode():
print("Testing INTEGER decode...")
data = b'\x02\x01\x2A' decoder = synta.Decoder(data, synta.Encoding.DER)
integer = decoder.decode_integer()
assert integer.to_int() == 42
print(" ✓ INTEGER decode: OK")
def test_integer_encode():
print("Testing INTEGER encode...")
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_integer(42)
output = encoder.finish()
assert output == b'\x02\x01\x2A'
print(" ✓ INTEGER encode: OK")
def test_large_integer():
print("Testing large INTEGER...")
large_val = 2**128 - 1
encoder = synta.Encoder(synta.Encoding.DER)
large_bytes = large_val.to_bytes(17, byteorder='big') large_int = synta.Integer.from_bytes(large_bytes)
encoder.encode_integer_object(large_int)
output = encoder.finish()
decoder = synta.Decoder(output, synta.Encoding.DER)
decoded = decoder.decode_integer()
assert decoded.to_bytes() == large_bytes
print(" ✓ Large INTEGER: OK")
def test_oid_decode():
print("Testing OID decode...")
oid_data = b'\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
decoder = synta.Decoder(oid_data, synta.Encoding.DER)
oid = decoder.decode_oid()
assert oid == oids.RSA_ENCRYPTION
print(" ✓ OID decode: OK")
def test_oid_create():
print("Testing OID create...")
oid = synta.ObjectIdentifier(str(oids.EC_PUBLIC_KEY))
assert oid == oids.EC_PUBLIC_KEY
components = oid.components()
assert components == (1, 2, 840, 10045, 2, 1)
print(" ✓ OID create: OK")
def test_oid_from_components():
print("Testing OID from components...")
oid = synta.ObjectIdentifier.from_components([1, 2, 840, 10045, 4, 3, 2])
assert oid == oids.ECDSA_WITH_SHA256
print(" ✓ OID from components: OK")
def test_oid_encode():
print("Testing OID encode...")
oid = oids.RSA_ENCRYPTION
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_oid(oid)
output = encoder.finish()
assert output == b'\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
print(" ✓ OID encode: OK")
def test_octet_string_decode():
print("Testing OCTET STRING decode...")
octet_data = b'\x04\x05hello'
decoder = synta.Decoder(octet_data, synta.Encoding.DER)
octet_string = decoder.decode_octet_string()
assert octet_string.to_bytes() == b'hello'
assert len(octet_string) == 5
print(" ✓ OCTET STRING decode: OK")
def test_octet_string_encode():
print("Testing OCTET STRING encode...")
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_octet_string(b'hello')
output = encoder.finish()
assert output == b'\x04\x05hello'
print(" ✓ OCTET STRING encode: OK")
def test_boolean_decode():
print("Testing BOOLEAN decode...")
bool_data = b'\x01\x01\xff'
decoder = synta.Decoder(bool_data, synta.Encoding.DER)
boolean = decoder.decode_boolean()
assert boolean.value()
assert bool(boolean)
bool_data = b'\x01\x01\x00'
decoder = synta.Decoder(bool_data, synta.Encoding.DER)
boolean = decoder.decode_boolean()
assert not boolean.value()
assert not bool(boolean)
print(" ✓ BOOLEAN decode: OK")
def test_boolean_encode():
print("Testing BOOLEAN encode...")
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_boolean(True)
output = encoder.finish()
assert output == b'\x01\x01\xff'
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_boolean(False)
output = encoder.finish()
assert output == b'\x01\x01\x00'
print(" ✓ BOOLEAN encode: OK")
def test_bit_string_create():
print("Testing BIT STRING create...")
bit_string = synta.BitString(b'\xff\x00', 0)
assert bit_string.unused_bits() == 0
assert bit_string.bit_len() == 16
assert bit_string.to_bytes() == b'\xff\x00'
print(" ✓ BIT STRING create: OK")
def test_bit_string_encode_decode():
print("Testing BIT STRING encode/decode...")
bs = synta.BitString(b'\xff\x00', 0)
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_bit_string(bs)
encoded = encoder.finish()
assert encoded == b'\x03\x03\x00\xff\x00', f"Unexpected encoding: {encoded.hex()}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
decoded = decoder.decode_bit_string()
assert decoded.to_bytes() == b'\xff\x00'
assert decoded.unused_bits() == 0
assert decoded.bit_len() == 16
assert decoder.is_empty()
bs2 = synta.BitString(b'\xff\x80', 3)
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_bit_string(bs2)
encoded2 = encoder2.finish()
assert encoded2 == b'\x03\x03\x03\xff\x80'
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
decoded2 = decoder2.decode_bit_string()
assert decoded2.to_bytes() == b'\xff\x80'
assert decoded2.unused_bits() == 3
assert decoded2.bit_len() == 13
print(" ✓ BIT STRING encode/decode: OK")
def test_decoder_state():
print("Testing decoder state...")
data = b'\x02\x01\x2A\x01\x01\xff' decoder = synta.Decoder(data, synta.Encoding.DER)
assert not decoder.is_empty()
assert decoder.remaining() == 6
assert decoder.position() == 0
integer = decoder.decode_integer()
assert integer.to_int() == 42
assert decoder.position() == 3
assert decoder.remaining() == 3
boolean = decoder.decode_boolean()
assert boolean.value()
assert decoder.position() == 6
assert decoder.remaining() == 0
assert decoder.is_empty()
print(" ✓ Decoder state: OK")
def test_error_handling():
print("Testing error handling...")
try:
synta.ObjectIdentifier("5.2.840")
assert False, "Should have raised ValueError"
except ValueError:
pass
try:
decoder = synta.Decoder(b'\x02\x05', synta.Encoding.DER)
decoder.decode_integer()
assert False, "Should have raised EOFError"
except EOFError:
pass
try:
decoder = synta.Decoder(b'\x05\x00', synta.Encoding.DER) decoder.decode_integer() assert False, "Should have raised ValueError"
except ValueError:
pass
print(" ✓ Error handling: OK")
def test_null_decode():
print("Testing NULL decode...")
null_data = b'\x05\x00'
decoder = synta.Decoder(null_data, synta.Encoding.DER)
null = decoder.decode_null()
assert isinstance(null, synta.Null)
assert decoder.is_empty()
print(" ✓ NULL decode: OK")
def test_null_encode():
print("Testing NULL encode...")
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_null()
output = encoder.finish()
assert output == b'\x05\x00'
print(" ✓ NULL encode: OK")
def test_utf8_string():
print("Testing UTF8String...")
text = "Hello, World!"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_utf8_string(text)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_utf8_string()
assert s.as_str() == text
assert str(s) == text
assert len(s) == len(text)
s2 = synta.Utf8String("test")
assert s2.as_str() == "test"
assert s2 == synta.Utf8String("test")
print(" ✓ UTF8String: OK")
def test_printable_string():
print("Testing PrintableString...")
text = "Example Corp"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_printable_string(text)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_printable_string()
assert s.as_str() == text
assert str(s) == text
try:
synta.PrintableString("Hello@World") assert False, "Should have raised ValueError"
except ValueError:
pass
print(" ✓ PrintableString: OK")
def test_ia5_string():
print("Testing IA5String...")
text = "user@example.com"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_ia5_string(text)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_ia5_string()
assert s.as_str() == text
assert str(s) == text
try:
synta.IA5String("héllo") assert False, "Should have raised ValueError"
except ValueError:
pass
print(" ✓ IA5String: OK")
def test_integer_to_i128():
print("Testing INTEGER to_i128...")
large = 2**64 + 1
large_bytes = large.to_bytes(9, byteorder='big')
n = synta.Integer.from_bytes(large_bytes)
val = n.to_i128()
assert val == large
n2 = synta.Integer.from_u64(2**63)
assert n2.to_i128() == 2**63
print(" ✓ INTEGER to_i128: OK")
def test_utc_time_constructor():
print("Testing UtcTime constructor...")
t = synta.UtcTime(2024, 1, 15, 10, 30, 0)
assert t.year == 2024
assert t.month == 1
assert t.day == 15
assert t.hour == 10
assert t.minute == 30
assert t.second == 0
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_utc_time(t)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
t2 = decoder.decode_utc_time()
assert t2.year == 2024
assert t2.month == 1
assert t2.day == 15
print(" ✓ UtcTime constructor: OK")
def test_generalized_time_constructor():
print("Testing GeneralizedTime constructor...")
t = synta.GeneralizedTime(2024, 6, 15, 12, 0, 0, None)
assert t.year == 2024
assert t.month == 6
assert t.milliseconds is None
t2 = synta.GeneralizedTime(2024, 6, 15, 12, 0, 0, 500)
assert t2.milliseconds == 500
print(" ✓ GeneralizedTime constructor: OK")
def test_decode_any_real():
import math
import struct
print("Testing decode_any with REAL...")
decoder = synta.Decoder(b'\x09\x00', synta.Encoding.DER)
r = decoder.decode_any()
assert isinstance(r, synta.Real), f"Expected Real, got {type(r)}"
assert r.value() == 0.0
decoder = synta.Decoder(b'\x09\x01\x40', synta.Encoding.DER)
r = decoder.decode_any()
assert isinstance(r, synta.Real)
assert math.isinf(float(r)) and float(r) > 0
decoder = synta.Decoder(b'\x09\x01\x41', synta.Encoding.DER)
r = decoder.decode_any()
assert isinstance(r, synta.Real)
assert math.isinf(float(r)) and float(r) < 0
value = 2.71828
data = bytes([0x09, 0x09, 0x80]) + struct.pack('>d', value)
decoder = synta.Decoder(data, synta.Encoding.DER)
r = decoder.decode_any()
assert isinstance(r, synta.Real)
assert r.value() == value
print(" ✓ decode_any Real: OK")
def test_decode_any_primitive():
print("Testing decode_any (primitives)...")
decoder = synta.Decoder(b'\x02\x01\x2A', synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.Integer)
assert val.to_int() == 42
decoder = synta.Decoder(b'\x01\x01\xff', synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.Boolean)
assert val.value() is True
decoder = synta.Decoder(b'\x05\x00', synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.Null)
decoder = synta.Decoder(b'\x04\x03abc', synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.OctetString)
assert val.to_bytes() == b'abc'
print(" ✓ decode_any (primitives): OK")
def test_decode_any_sequence():
print("Testing decode_any (SEQUENCE)...")
data = b'\x30\x06\x02\x01\x01\x01\x01\xff'
decoder = synta.Decoder(data, synta.Encoding.DER)
seq = decoder.decode_any()
assert isinstance(seq, list)
assert len(seq) == 2
assert isinstance(seq[0], synta.Integer)
assert seq[0].to_int() == 1
assert isinstance(seq[1], synta.Boolean)
assert seq[1].value() is True
print(" ✓ decode_any (SEQUENCE): OK")
_RSA_CERT_PEM = """\
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"""
_ECDSA_CERT_PEM = """\
MIICCTCCAa+gAwIBAgIUZVVIpXfjuxT9d3gDVq3eCWYxwkUwCgYIKoZIzj0EAwIw
WjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNp
c2NvMQ0wCwYDVQQKDARUZXN0MRcwFQYDVQQDDA5lY2RzYS50ZXN0LmNvbTAeFw0y
NjAyMjMxMDU0NTNaFw0yNzAyMjMxMDU0NTNaMFoxCzAJBgNVBAYTAlVTMQswCQYD
VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwEVGVzdDEX
MBUGA1UEAwwOZWNkc2EudGVzdC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
AATLXHqYJi2uIgdejzQyxF+jpAgyRylYeRh6JBKtXXoNH1m85zRmhEVR9hqUhPb+
Hm0xMX3xgAs3U52aIRATRZpYo1MwUTAdBgNVHQ4EFgQUxha7J/RFOfgWVwUZPgig
jbCihNwwHwYDVR0jBBgwFoAUxha7J/RFOfgWVwUZPgigjbCihNwwDwYDVR0TAQH/
BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAhhM4PhuCnuqSYeGLtBaaVCxx+4pu
fyHLHbI1YzgOlBkCIBXAMEJWKCp22U253kkRGjdflyJmn2GGHKHeGvEl91dF"""
def test_certificate_rsa():
print("Testing Certificate.from_der (RSA)...")
der = base64.b64decode(_RSA_CERT_PEM)
cert = synta.Certificate.from_der(der)
assert cert.version == 2, f"Expected v3 (2), got {cert.version}"
assert str(cert.signature_algorithm) == oids.identify_signature_algorithm(oids.SHA256_WITH_RSA), \
f"Unexpected sig alg: {cert.signature_algorithm}"
assert str(cert.public_key_algorithm) == oids.identify_public_key_algorithm(oids.RSA_ENCRYPTION), \
f"Unexpected pubkey alg: {cert.public_key_algorithm}"
assert len(cert.public_key) > 0
assert isinstance(cert.serial_number, int)
assert cert.not_before
assert cert.not_after
assert cert.subject
assert cert.issuer
assert cert.subject == cert.issuer
print(" ✓ Certificate RSA: OK")
def test_certificate_ecdsa():
print("Testing Certificate.from_der (ECDSA)...")
der = base64.b64decode(_ECDSA_CERT_PEM)
cert = synta.Certificate.from_der(der)
assert str(cert.signature_algorithm) == oids.identify_signature_algorithm(oids.ECDSA_WITH_SHA256), \
f"Unexpected sig alg: {cert.signature_algorithm}"
assert str(cert.public_key_algorithm) == oids.identify_public_key_algorithm(oids.EC_PUBLIC_KEY), \
f"Unexpected pubkey alg: {cert.public_key_algorithm}"
assert cert.version == 2
assert isinstance(cert.serial_number, int)
assert len(cert.public_key) > 0
assert cert.subject == cert.issuer
print(" ✓ Certificate ECDSA: OK")
def test_certificate_serial_number_round_trip():
import secrets, datetime
key = synta.PrivateKey.generate_rsa(2048)
now = datetime.datetime.now(datetime.timezone.utc)
def round_trip(sn_in):
b = synta.CertificateBuilder()
b = b.subject_name(b'\x30\x00')
b = b.issuer_name(b'\x30\x00')
b = b.public_key(key.public_key)
b = b.serial_number(sn_in)
b = b.not_valid_before_utc(now)
b = b.not_valid_after_utc(now + datetime.timedelta(days=365))
cert = b.sign(key, 'sha256')
return cert.serial_number
cases = [
(42, "small"),
(2**63 - 1, "max i64"),
(2**63, "first value past i64"),
(2**63 + 1, "2^63 + 1"),
(2**127 - 1, "max positive 127-bit"),
(2**127, "2^127 (MSB set, typical RSNv3)"),
(2**127 + 42, "2^127 + 42"),
(secrets.randbits(128) | (1 << 127), "128-bit RSNv3 random"),
]
for sn_in, label in cases:
sn_out = round_trip(sn_in)
assert sn_out == sn_in, (
f"serial_number round-trip failed for {label}: "
f"in={sn_in:#x} out={sn_out:#x}"
)
print(" ✓ Certificate serial_number round-trip: OK")
def test_certificate_invalid():
print("Testing Certificate.from_der (invalid input)...")
try:
synta.Certificate.from_der(b'\x00\x00\x00')
assert False, "Should have raised an error"
except Exception:
pass
print(" ✓ Certificate invalid input: OK")
def test_real_decode():
print("Testing Real decode...")
zero_data = b'\x09\x00'
decoder = synta.Decoder(zero_data, synta.Encoding.DER)
r = decoder.decode_real()
assert isinstance(r, synta.Real)
assert r.value() == 0.0
assert float(r) == 0.0
assert r.is_finite()
assert decoder.is_empty()
inf_data = b'\x09\x01\x40'
decoder = synta.Decoder(inf_data, synta.Encoding.DER)
r = decoder.decode_real()
assert r.is_infinite()
assert float(r) > 0
neg_inf_data = b'\x09\x01\x41'
decoder = synta.Decoder(neg_inf_data, synta.Encoding.DER)
r = decoder.decode_real()
assert r.is_infinite()
assert float(r) < 0
nan_data = b'\x09\x01\x42'
decoder = synta.Decoder(nan_data, synta.Encoding.DER)
r = decoder.decode_real()
assert r.is_nan()
print(" ✓ Real decode: OK")
def test_real_encode():
import math
print("Testing Real encode...")
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real(0.0)
data = encoder.finish()
assert data == b'\x09\x00', f"Expected zero encoding, got {data.hex()}"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real(math.inf)
data = encoder.finish()
assert data == b'\x09\x01\x40', f"Expected +inf encoding, got {data.hex()}"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real(-math.inf)
data = encoder.finish()
assert data == b'\x09\x01\x41', f"Expected -inf encoding, got {data.hex()}"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real(math.nan)
data = encoder.finish()
assert data == b'\x09\x01\x42', f"Expected NaN encoding, got {data.hex()}"
value = 3.14
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real(value)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
r = decoder.decode_real()
assert r.value() == value
assert r.is_finite()
assert not r.is_nan()
assert not r.is_infinite()
real_obj = synta.Real(2.71828)
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_real_object(real_obj)
encoded = encoder.finish()
decoder = synta.Decoder(encoded, synta.Encoding.DER)
r2 = decoder.decode_real()
assert r2.value() == real_obj.value()
print(" ✓ Real encode: OK")
def test_real_object():
import math
print("Testing Real object...")
r = synta.Real(1.5)
assert r.value() == 1.5
assert float(r) == 1.5
assert r.is_finite()
assert not r.is_nan()
assert not r.is_infinite()
assert repr(r) == "Real(1.5)"
assert str(r) == "1.5"
assert r == synta.Real(1.5)
assert not (r == synta.Real(2.0))
assert synta.Real(math.inf).is_infinite()
assert synta.Real(-math.inf).is_infinite()
assert synta.Real(math.nan).is_nan()
print(" ✓ Real object: OK")
def test_encode_object_variants():
print("Testing encode_*_object variants...")
bool_obj = synta.Decoder(b'\x01\x01\xff', synta.Encoding.DER).decode_boolean()
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_boolean_object(bool_obj)
assert enc.finish() == b'\x01\x01\xff'
os_obj = synta.Decoder(b'\x04\x03abc', synta.Encoding.DER).decode_octet_string()
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_octet_string_object(os_obj)
assert enc.finish() == b'\x04\x03abc'
oid_bytes = b'\x06\x03\x55\x04\x03' oid_obj = synta.Decoder(oid_bytes, synta.Encoding.DER).decode_oid()
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_oid_object(oid_obj)
assert enc.finish() == oid_bytes
bs_bytes = b'\x03\x02\x00\xff' bs_obj = synta.Decoder(bs_bytes, synta.Encoding.DER).decode_bit_string()
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_bit_string_object(bs_obj)
assert enc.finish() == bs_bytes
null_obj = synta.Decoder(b'\x05\x00', synta.Encoding.DER).decode_null()
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_null_object(null_obj)
assert enc.finish() == b'\x05\x00'
t = synta.UtcTime(2024, 3, 1, 9, 0, 0)
enc1 = synta.Encoder(synta.Encoding.DER)
enc1.encode_utc_time(t)
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_utc_time_object(t)
assert enc1.finish() == enc2.finish()
gt = synta.GeneralizedTime(2024, 6, 15, 12, 0, 0, None)
enc1 = synta.Encoder(synta.Encoding.DER)
enc1.encode_generalized_time(gt)
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_generalized_time_object(gt)
assert enc1.finish() == enc2.finish()
s = synta.Utf8String("hello")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_utf8_string_object(s)
data = enc.finish()
assert synta.Decoder(data, synta.Encoding.DER).decode_utf8_string().as_str() == "hello"
ps = synta.PrintableString("Test Corp")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_printable_string_object(ps)
data = enc.finish()
assert synta.Decoder(data, synta.Encoding.DER).decode_printable_string().as_str() == "Test Corp"
ia5 = synta.IA5String("user@example.com")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_ia5_string_object(ia5)
data = enc.finish()
assert synta.Decoder(data, synta.Encoding.DER).decode_ia5_string().as_str() == "user@example.com"
print(" ✓ encode_*_object variants: OK")
def test_numeric_string():
print("Testing NumericString...")
text = "12345 67890"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_numeric_string(text)
encoded = encoder.finish()
assert encoded[0] == 0x12, f"Wrong tag: {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_numeric_string()
assert s.as_str() == text
assert str(s) == text
assert len(s) == len(text)
s2 = synta.NumericString("0 9")
assert s2.as_str() == "0 9"
assert s2 == synta.NumericString("0 9")
try:
synta.NumericString("abc")
assert False, "Should have raised ValueError"
except ValueError:
pass
obj = synta.NumericString("999")
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_numeric_string_object(obj)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s3 = decoder2.decode_numeric_string()
assert s3.as_str() == "999"
print(" ✓ NumericString: OK")
def test_teletex_string():
print("Testing TeletexString...")
data = b"hello\x80\xff"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_teletex_string(data)
encoded = encoder.finish()
assert encoded[0] == 0x14, f"Wrong tag: {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_teletex_string()
assert s.to_bytes() == data
assert len(s) == len(data)
obj = synta.TeletexString(b"test")
assert obj.to_bytes() == b"test"
assert obj == synta.TeletexString(b"test")
obj2 = synta.TeletexString.from_str("Hello")
assert obj2.as_str() == "Hello"
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_teletex_string_object(obj)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s2 = decoder2.decode_teletex_string()
assert s2.to_bytes() == b"test"
print(" ✓ TeletexString: OK")
def test_visible_string():
print("Testing VisibleString...")
text = "Hello, World!"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_visible_string(text)
encoded = encoder.finish()
assert encoded[0] == 0x1a, f"Wrong tag: {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_visible_string()
assert s.as_str() == text
assert str(s) == text
assert len(s) == len(text)
s2 = synta.VisibleString("test123")
assert s2.as_str() == "test123"
assert s2 == synta.VisibleString("test123")
try:
synta.VisibleString("\x00")
assert False, "Should have raised ValueError"
except ValueError:
pass
obj = synta.VisibleString("visible")
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_visible_string_object(obj)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s3 = decoder2.decode_visible_string()
assert s3.as_str() == "visible"
print(" ✓ VisibleString: OK")
def test_general_string():
print("Testing GeneralString...")
data = b"krbtgt\x00"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_general_string(data)
encoded = encoder.finish()
assert encoded[0] == 0x1b, f"Wrong tag: {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_general_string()
assert s.to_bytes() == data
assert len(s) == len(data)
obj = synta.GeneralString(b"EXAMPLE.COM")
assert obj.to_bytes() == b"EXAMPLE.COM"
assert obj == synta.GeneralString(b"EXAMPLE.COM")
obj2 = synta.GeneralString.from_str("test")
assert obj2.as_str() == "test"
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_general_string_object(obj)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s2 = decoder2.decode_general_string()
assert s2.to_bytes() == b"EXAMPLE.COM"
print(" ✓ GeneralString: OK")
def test_universal_string():
print("Testing UniversalString...")
text = "Hello"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_universal_string(text)
encoded = encoder.finish()
assert encoded[0] == 0x1c, f"Wrong tag: {encoded[0]:#x}"
assert len(encoded) == 2 + 4 * len(text)
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_universal_string()
assert s.as_str() == text
assert str(s) == text
text2 = "你好"
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_universal_string(text2)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s2 = decoder2.decode_universal_string()
assert s2.as_str() == text2
obj = synta.UniversalString("test")
assert obj.as_str() == "test"
assert obj == synta.UniversalString("test")
obj2 = synta.UniversalString.from_bytes(b"\x00\x00\x00\x41")
assert obj2.as_str() == "A"
encoder3 = synta.Encoder(synta.Encoding.DER)
encoder3.encode_universal_string_object(obj)
encoded3 = encoder3.finish()
decoder3 = synta.Decoder(encoded3, synta.Encoding.DER)
s3 = decoder3.decode_universal_string()
assert s3.as_str() == "test"
print(" ✓ UniversalString: OK")
def test_bmp_string():
print("Testing BMPString...")
text = "café"
encoder = synta.Encoder(synta.Encoding.DER)
encoder.encode_bmp_string(text)
encoded = encoder.finish()
assert encoded[0] == 0x1e, f"Wrong tag: {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
s = decoder.decode_bmp_string()
assert s.as_str() == text
assert str(s) == text
obj = synta.BmpString("Hello")
assert obj.as_str() == "Hello"
assert obj == synta.BmpString("Hello")
try:
synta.BmpString("\U0001F600") assert False, "Should have raised ValueError"
except ValueError:
pass
obj2 = synta.BmpString.from_bytes(b"\x00\x41")
assert obj2.as_str() == "A"
encoder2 = synta.Encoder(synta.Encoding.DER)
encoder2.encode_bmp_string_object(obj)
encoded2 = encoder2.finish()
decoder2 = synta.Decoder(encoded2, synta.Encoding.DER)
s2 = decoder2.decode_bmp_string()
assert s2.as_str() == "Hello"
print(" ✓ BMPString: OK")
def test_encode_decode_sequence():
print("Testing encode_sequence / decode_sequence...")
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_integer(42)
inner.encode_boolean(True)
inner_bytes = inner.finish()
outer = synta.Encoder(synta.Encoding.DER)
outer.encode_sequence(inner_bytes)
encoded = outer.finish()
assert encoded[0] == 0x30, f"Expected SEQUENCE tag 0x30, got {encoded[0]:#x}"
assert encoded[1] == len(inner_bytes)
decoder = synta.Decoder(encoded, synta.Encoding.DER)
child = decoder.decode_sequence()
assert decoder.is_empty()
assert not child.is_empty()
integer = child.decode_integer()
assert integer.to_int() == 42
assert not child.is_empty()
boolean = child.decode_boolean()
assert boolean.value() is True
assert child.is_empty()
print(" ✓ encode_sequence / decode_sequence: OK")
def test_encode_decode_set():
print("Testing encode_set...")
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_integer(7)
inner_bytes = inner.finish()
outer = synta.Encoder(synta.Encoding.DER)
outer.encode_set(inner_bytes)
encoded = outer.finish()
assert encoded[0] == 0x31, f"Expected SET tag 0x31, got {encoded[0]:#x}"
assert encoded[1] == len(inner_bytes)
print(" ✓ encode_set: OK")
def test_encode_decode_explicit_tag():
print("Testing encode_explicit_tag / decode_explicit_tag...")
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_integer(99)
inner_bytes = inner.finish()
outer = synta.Encoder(synta.Encoding.DER)
outer.encode_explicit_tag(1, "Context", inner_bytes)
encoded = outer.finish()
assert encoded[0] == 0xa1, f"Expected [1] EXPLICIT (0xa1), got {encoded[0]:#x}"
decoder = synta.Decoder(encoded, synta.Encoding.DER)
child = decoder.decode_explicit_tag(1)
assert decoder.is_empty()
integer = child.decode_integer()
assert integer.to_int() == 99
assert child.is_empty()
decoder2 = synta.Decoder(encoded, synta.Encoding.DER)
try:
decoder2.decode_explicit_tag(2)
assert False, "Should have raised ValueError"
except ValueError:
pass
for cls in ("Application", "Private"):
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_explicit_tag(0, cls, inner_bytes)
enc2.finish()
try:
enc3 = synta.Encoder(synta.Encoding.DER)
enc3.encode_explicit_tag(0, "Invalid", inner_bytes)
assert False, "Should have raised ValueError"
except ValueError:
pass
print(" ✓ encode_explicit_tag / decode_explicit_tag: OK")
def test_decode_any_new_string_types():
print("Testing decode_any (new string types)...")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_numeric_string("123")
data = enc.finish()
decoder = synta.Decoder(data, synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.NumericString), f"Got {type(val)}"
assert val.as_str() == "123"
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_visible_string("hi")
data = enc.finish()
decoder = synta.Decoder(data, synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.VisibleString), f"Got {type(val)}"
assert val.as_str() == "hi"
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_general_string(b"realm")
data = enc.finish()
decoder = synta.Decoder(data, synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.GeneralString), f"Got {type(val)}"
assert val.to_bytes() == b"realm"
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_bmp_string("hi")
data = enc.finish()
decoder = synta.Decoder(data, synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.BmpString), f"Got {type(val)}"
assert val.as_str() == "hi"
print(" ✓ decode_any (new string types): OK")
def test_decode_any_raw_element():
print("Testing decode_any (RawElement for unknown tag)...")
raw_tlv = bytes([0x19, 0x03, ord('a'), ord('b'), ord('c')])
decoder = synta.Decoder(raw_tlv, synta.Encoding.DER)
val = decoder.decode_any()
assert isinstance(val, synta.RawElement), f"Got {type(val)}"
assert val.tag_number == 25
assert val.tag_class == "Universal"
assert val.is_constructed is False
assert val.data == b"abc"
print(" ✓ decode_any (RawElement): OK")
def test_encode_integer_large():
print("Testing encode_integer with large Python ints...")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(42)
assert enc.finish() == b'\x02\x01\x2a'
val = 2**64
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(val)
out = enc.finish()
dec = synta.Decoder(out, synta.Encoding.DER)
decoded = dec.decode_integer()
assert decoded.to_bytes() == val.to_bytes((val.bit_length() + 8) // 8, 'big', signed=True)
serial = 2**159 - 1
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(serial)
out = enc.finish()
dec = synta.Decoder(out, synta.Encoding.DER)
decoded = dec.decode_integer()
expected = b'\x7f' + b'\xff' * 19 assert decoded.to_bytes() == expected, f"Got {decoded.to_bytes().hex()}"
val = 2**127 enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(val)
out = enc.finish()
assert out[0] == 0x02 assert out[2] == 0x00
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(-128)
assert enc.finish() == b'\x02\x01\x80'
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(-129)
assert enc.finish() == b'\x02\x02\xff\x7f'
print(" encode_integer large ints: OK")
def test_decoder_remaining_bytes():
print("Testing Decoder.remaining_bytes()...")
name = b"example.com"
tlv = bytes([0x82, len(name)]) + name
decoder = synta.Decoder(tlv, synta.Encoding.DER)
child = decoder.decode_implicit_tag(2, "Context")
raw = child.remaining_bytes()
assert raw == name, f"Got {raw!r}, expected {name!r}"
assert raw.decode("ascii") == "example.com"
assert child.remaining() == len(name)
raw2 = child.remaining_bytes()
assert raw2 == name
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_integer(1)
enc.encode_integer(2)
combined = enc.finish()
dec = synta.Decoder(combined, synta.Encoding.DER)
dec.decode_integer() rest = dec.remaining_bytes()
assert rest == b'\x02\x01\x02'
print(" Decoder.remaining_bytes(): OK")
def test_certificate_get_extension_value_der():
print("Testing Certificate.get_extension_value_der()...")
der = base64.b64decode(_RSA_CERT_PEM)
cert = synta.Certificate.from_der(der)
bc = cert.get_extension_value_der(oids.BASIC_CONSTRAINTS)
assert bc is not None, "BasicConstraints extension not found"
assert bc == bytes.fromhex("30030101ff"), f"Unexpected BasicConstraints: {bc.hex()}"
bc_dec = synta.Decoder(bc, synta.Encoding.DER)
bc_seq = bc_dec.decode_sequence()
ca_flag = bc_seq.decode_boolean()
assert ca_flag.value() is True
ski = cert.get_extension_value_der(oids.SUBJECT_KEY_IDENTIFIER)
assert ski is not None, "SKI extension not found"
assert ski[0] == 0x04 and ski[1] == 0x14, \
f"Expected OCTET STRING(20), got {ski.hex()}"
assert cert.get_extension_value_der("1.2.3.4") is None
try:
cert.get_extension_value_der("not-an-oid")
assert False, "Expected ValueError"
except ValueError:
pass
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_implicit_tag(2, "Context", False, b"example.com")
enc.encode_implicit_tag(7, "Context", False, bytes([127, 0, 0, 1]))
san_der = synta.Encoder(synta.Encoding.DER)
san_der.encode_sequence(enc.finish())
san_bytes = san_der.finish()
dec = synta.Decoder(san_bytes, synta.Encoding.DER)
san_seq = dec.decode_sequence()
dns_name = None
ip_addr = None
while not san_seq.is_empty():
tag_num, tag_class, _ = san_seq.peek_tag()
child = san_seq.decode_implicit_tag(tag_num, "Context")
if tag_num == 2:
dns_name = child.remaining_bytes().decode("ascii")
elif tag_num == 7:
ip_addr = child.remaining_bytes()
assert dns_name == "example.com", f"Got {dns_name!r}"
assert ip_addr == bytes([127, 0, 0, 1]), f"Got {ip_addr!r}"
print(" Certificate.get_extension_value_der(): OK")
def test_oid_from_der_value():
print("Testing ObjectIdentifier.from_der_value()...")
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_oid(oids.SHA256_WITH_RSA)
tlv = enc.finish()
assert tlv[0] == 0x06
length = tlv[1]
content = tlv[2 : 2 + length]
oid = synta.ObjectIdentifier.from_der_value(content)
assert oid == oids.SHA256_WITH_RSA, f"Got {oid}"
content_cn = bytes([0x55, 0x04, 0x03])
oid_cn = synta.ObjectIdentifier.from_der_value(content_cn)
assert str(oid_cn) == "2.5.4.3", f"Got {oid_cn}"
enc2 = synta.Encoder(synta.Encoding.DER)
enc2.encode_implicit_tag(8, "Context", False, content_cn)
san_bytes = enc2.finish()
dec = synta.Decoder(san_bytes, synta.Encoding.DER)
tag_num, tag_class, constructed = dec.peek_tag()
assert tag_num == 8 and tag_class == "Context" and not constructed
child = dec.decode_implicit_tag(8, "Context")
raw = child.remaining_bytes()
assert raw == content_cn
oid_reg = synta.ObjectIdentifier.from_der_value(raw)
assert str(oid_reg) == "2.5.4.3", f"Got {oid_reg}"
try:
synta.ObjectIdentifier.from_der_value(b"")
assert False, "Expected ValueError for empty input"
except ValueError:
pass
try:
synta.ObjectIdentifier.from_der_value(b"\xff\xff") assert False, "Expected ValueError for invalid OID bytes"
except (ValueError, synta.SyntaError):
pass
print(" ObjectIdentifier.from_der_value(): OK")
def test_all_in_dir():
print("Testing synta.__all__ consistency...")
missing = set(synta.__all__) - set(dir(synta))
assert not missing, (
f"Names listed in synta.__all__ but not found in dir(synta): {sorted(missing)}"
)
print(" synta.__all__ ⊆ dir(synta): OK")
def test_oids_submodule():
print("Testing synta.oids submodule...")
import synta.oids as oids
from synta.oids import SHA256_WITH_RSA, ED25519, ML_DSA_44
from synta.oids.attr import COMMON_NAME, COUNTRY, ORGANIZATION
assert isinstance(SHA256_WITH_RSA, synta.ObjectIdentifier)
assert str(SHA256_WITH_RSA) == "1.2.840.113549.1.1.11"
assert str(ED25519) == "1.3.101.112"
assert str(ML_DSA_44) == "2.16.840.1.101.3.4.3.17"
assert SHA256_WITH_RSA == "1.2.840.113549.1.1.11"
assert SHA256_WITH_RSA in {"1.2.840.113549.1.1.11", "1.2.840.113549.1.1.5"}
assert ED25519 not in {"1.2.840.113549.1.1.11"}
assert str(COMMON_NAME) == "2.5.4.3"
assert str(COUNTRY) == "2.5.4.6"
assert str(ORGANIZATION) == "2.5.4.10"
assert str(oids.ML_KEM_512) == "2.16.840.1.101.3.4.4.1"
assert str(oids.SLH_DSA_SHA2_128S) == "2.16.840.1.101.3.4.3.20"
assert str(oids.SHA3_256) == "2.16.840.1.101.3.4.2.8"
assert str(oids.SUBJECT_ALT_NAME) == "2.5.29.17"
assert str(oids.EC_CURVE_P256) == "1.2.840.10045.3.1.7"
assert oids.identify_signature_algorithm(SHA256_WITH_RSA) == "SHA256WithRSA"
assert oids.identify_signature_algorithm(ED25519) == "Ed25519"
assert oids.identify_signature_algorithm(ML_DSA_44) == "ML-DSA-44"
assert oids.identify_signature_algorithm("1.2.840.113549.1.1.11") == "SHA256WithRSA"
assert oids.identify_signature_algorithm(synta.ObjectIdentifier("1.2.99999")) == "Other"
assert oids.identify_public_key_algorithm(oids.RSA_ENCRYPTION) == "RSA"
assert oids.identify_public_key_algorithm(oids.EC_PUBLIC_KEY) == "ECDSA"
assert oids.identify_public_key_algorithm(synta.ObjectIdentifier("1.2.99999")) is None
assert oids.ec_curve_short_name(oids.EC_CURVE_P256) == "prime256v1"
assert oids.ec_curve_short_name(oids.EC_CURVE_P384) == "secp384r1"
assert oids.ec_curve_short_name(synta.ObjectIdentifier("1.2.99999")) is None
assert oids.ec_curve_nist_name(oids.EC_CURVE_P256) == "P-256"
assert oids.ec_curve_nist_name(oids.EC_CURVE_SECP256K1) is None
assert oids.ec_curve_key_bits(oids.EC_CURVE_P256) == 256
assert oids.ec_curve_key_bits(oids.EC_CURVE_P521) == 521
assert oids.ec_curve_key_bits(synta.ObjectIdentifier("1.2.99999")) is None
assert oids.extension_oid_name(oids.KEY_USAGE) == "X509v3 Key Usage"
assert oids.extension_oid_name(oids.SUBJECT_ALT_NAME) == "X509v3 Subject Alternative Name"
assert oids.extension_oid_name(synta.ObjectIdentifier("1.2.99999")) == "1.2.99999"
assert str(oids.ALG_UNSIGNED) == "1.3.6.1.5.5.7.6.36"
assert str(oids.RDNA_UNSIGNED) == "1.3.6.1.5.5.7.25.1"
assert oids.identify_signature_algorithm(oids.ALG_UNSIGNED) == "Unsigned"
print(" synta.oids submodule: OK")
def main():
print("=" * 60)
print("Synta Python Bindings - Basic Tests")
print("=" * 60)
print()
tests = [
test_integer_decode,
test_integer_encode,
test_large_integer,
test_oid_decode,
test_oid_create,
test_oid_from_components,
test_oid_encode,
test_octet_string_decode,
test_octet_string_encode,
test_boolean_decode,
test_boolean_encode,
test_bit_string_create,
test_bit_string_encode_decode,
test_decoder_state,
test_error_handling,
test_null_decode,
test_null_encode,
test_utf8_string,
test_printable_string,
test_ia5_string,
test_integer_to_i128,
test_utc_time_constructor,
test_generalized_time_constructor,
test_decode_any_real,
test_decode_any_primitive,
test_decode_any_sequence,
test_certificate_rsa,
test_certificate_ecdsa,
test_certificate_serial_number_round_trip,
test_certificate_invalid,
test_real_decode,
test_real_encode,
test_real_object,
test_encode_object_variants,
test_numeric_string,
test_teletex_string,
test_visible_string,
test_general_string,
test_universal_string,
test_bmp_string,
test_encode_decode_sequence,
test_encode_decode_set,
test_encode_decode_explicit_tag,
test_decode_any_new_string_types,
test_decode_any_raw_element,
test_encode_integer_large,
test_decoder_remaining_bytes,
test_certificate_get_extension_value_der,
test_oid_from_der_value,
test_all_in_dir,
test_oids_submodule,
]
for test in tests:
try:
test()
except Exception as e:
print(f" ✗ {test.__name__} FAILED: {e}")
raise
print()
print("=" * 60)
print(f"All {len(tests)} tests passed! ✓")
print("=" * 60)
if __name__ == '__main__':
main()