import pytest
import synta
def _alg_id_with_null(oid: synta.ObjectIdentifier) -> bytes:
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_oid(oid)
inner.encode_null()
outer = synta.Encoder(synta.Encoding.DER)
outer.encode_sequence(inner.finish())
return bytes(outer.finish())
SHA1_ALG = _alg_id_with_null(synta.ObjectIdentifier("1.3.14.3.2.26"))
SHA256_WITH_RSA_ALG = _alg_id_with_null(synta.oids.SHA256_WITH_RSA)
NAME_HASH = bytes(20)
KEY_HASH = bytes(20)
SERIAL = bytes([0x42])
def test_cert_id_spec_fields():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
assert spec is not None
def test_build_unsigned_request():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = synta.OCSPRequestBuilder().add_request(spec).build_tbs()
assert isinstance(der, bytes)
assert len(der) > 0
def test_unsigned_request_round_trip():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = synta.OCSPRequestBuilder().add_request(spec).build_tbs()
req = synta.OCSPRequest.from_der(der)
assert len(req.request_list) == 1
cert_id = req.request_list[0]
assert cert_id.issuer_name_hash == NAME_HASH
assert cert_id.issuer_key_hash == KEY_HASH
assert cert_id.serial_number == int.from_bytes(SERIAL, "big")
assert req.requestor_name is None
assert req.request_extensions is None
def test_multiple_requests_accumulated():
serial2 = bytes([0x01, 0x99]) spec1 = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
spec2 = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=serial2,
)
der = (
synta.OCSPRequestBuilder()
.add_request(spec1)
.add_request(spec2)
.build_tbs()
)
req = synta.OCSPRequest.from_der(der)
assert len(req.request_list) == 2
serials = {cid.serial_number for cid in req.request_list}
assert int.from_bytes(SERIAL, "big") in serials
assert int.from_bytes(serial2, "big") in serials
def test_build_tbs_double_call_raises():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
builder = synta.OCSPRequestBuilder().add_request(spec)
builder.build_tbs()
with pytest.raises(ValueError, match="already called"):
builder.build_tbs()
def test_build_tbs_inner_double_call_raises():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
builder = synta.OCSPRequestBuilder().add_request(spec)
builder.build_tbs_inner()
with pytest.raises(ValueError, match="already called"):
builder.build_tbs_inner()
def test_empty_request_list_raises():
with pytest.raises(ValueError):
synta.OCSPRequestBuilder().build_tbs()
def test_invalid_alg_id_raises():
with pytest.raises(ValueError):
synta.OCSPRequestBuilder().add_request(
synta.OCSPCertIDSpec(
hash_algorithm_der=b"\xff\x00", issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
).build_tbs()
def test_build_signed_request():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
tbs_inner = synta.OCSPRequestBuilder().add_request(spec).build_tbs_inner()
assert isinstance(tbs_inner, bytes)
assert len(tbs_inner) > 0
sig = bytes(32)
ocsp_der = synta.OCSPRequestBuilder.assemble(tbs_inner, SHA256_WITH_RSA_ALG, sig)
req = synta.OCSPRequest.from_der(ocsp_der)
assert len(req.request_list) == 1
def test_assemble_invalid_tbs_raises():
with pytest.raises(ValueError):
synta.OCSPRequestBuilder.assemble(b"\xff\x00", SHA256_WITH_RSA_ALG, bytes(32))
def test_assemble_invalid_sig_alg_raises():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
tbs_inner = synta.OCSPRequestBuilder().add_request(spec).build_tbs_inner()
with pytest.raises(ValueError):
synta.OCSPRequestBuilder.assemble(tbs_inner, b"\xff\x00", bytes(32))
def _der_length(n: int) -> bytes:
if n < 0x80:
return bytes([n])
if n < 0x100:
return bytes([0x81, n])
return bytes([0x82, n >> 8, n & 0xFF])
def test_requestor_name_present():
rn_der = synta.NameBuilder().common_name("Requestor").build()
gn_der = bytes([0xa4]) + _der_length(len(rn_der)) + rn_der
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = (
synta.OCSPRequestBuilder()
.requestor_name(gn_der)
.add_request(spec)
.build_tbs()
)
req = synta.OCSPRequest.from_der(der)
assert req.requestor_name is not None
assert isinstance(req.requestor_name, bytes)
assert len(req.requestor_name) > 0
def test_requestor_name_invalid_der_raises():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
with pytest.raises(ValueError):
synta.OCSPRequestBuilder().requestor_name(b"\xff\xff").add_request(spec).build_tbs()
def test_ocsp_request_to_der_roundtrip():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = synta.OCSPRequestBuilder().add_request(spec).build_tbs()
req = synta.OCSPRequest.from_der(der)
assert req.to_der() == der
def test_ocsp_request_repr():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = synta.OCSPRequestBuilder().add_request(spec).build_tbs()
req = synta.OCSPRequest.from_der(der)
r = repr(req)
assert "OCSPRequest" in r
def test_cert_id_properties():
spec = synta.OCSPCertIDSpec(
hash_algorithm_der=SHA1_ALG,
issuer_name_hash=NAME_HASH,
issuer_key_hash=KEY_HASH,
serial=SERIAL,
)
der = synta.OCSPRequestBuilder().add_request(spec).build_tbs()
req = synta.OCSPRequest.from_der(der)
cert_id = req.request_list[0]
assert cert_id.issuer_name_hash == NAME_HASH
assert cert_id.issuer_key_hash == KEY_HASH
assert cert_id.serial_number == int.from_bytes(SERIAL, "big")
assert str(cert_id.hash_algorithm_oid) == "1.3.14.3.2.26"
r = repr(cert_id)
assert "CertID" in r