import synta
import synta.krb5 as krb5
def section(title):
print(f"\n{'─' * 60}\n{title}\n{'─' * 60}")
def _enc(fn):
enc = synta.Encoder(synta.Encoding.DER)
fn(enc)
return enc.finish()
def _seq(*parts):
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_sequence(b"".join(parts))
return enc.finish()
def _explicit(n, content):
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_explicit_tag(n, "Context", content)
return enc.finish()
def _implicit(n, inner_der):
orig_tag = inner_der[0]
constructed = orig_tag & 0x20 length_byte = inner_der[1]
assert length_byte < 0x80, "only short-form length supported in helper"
content = inner_der[2:2 + length_byte]
ctx_tag = 0x80 | constructed | n
return bytes([ctx_tag, len(content)]) + content
def _int_der(v):
return _enc(lambda e: e.encode_integer(v))
def _oct_der(b):
return _enc(lambda e: e.encode_octet_string(b))
def _oid_der(s):
return _enc(lambda e: e.encode_oid(synta.ObjectIdentifier(s)))
def _gt_der():
return _enc(
lambda e: e.encode_generalized_time(
synta.GeneralizedTime(2026, 1, 1, 0, 0, 0, None)
)
)
def _bit_der(b):
return _enc(lambda e: e.encode_bit_string(synta.BitString(b, 0)))
ENC_KEY_DER = _seq(
_explicit(0, _int_der(17)), _explicit(1, _oct_der(b"\xaa" * 16)), )
CHECKSUM_DER = _seq(
_explicit(0, _int_der(7)), _explicit(1, _oct_der(b"\xbb" * 8)), )
KDFALGOID_DER = _seq(_oid_der("1.3.6.1.5.2.3.6.2"))
ISSUER_SERIAL_DER = _seq(
_oct_der(b"\x30\x00"), _int_der(42), )
PKA_DER = _seq(
_explicit(0, _int_der(0)), _explicit(1, _gt_der()), _explicit(2, _int_der(12345)), )
PKA_WITH_CHECKSUM_DER = _seq(
_explicit(0, _int_der(500)),
_explicit(1, _gt_der()),
_explicit(2, _int_der(99999)),
_explicit(3, _oct_der(b"\xcc" * 20)), )
DHREPINFO_DER = _seq(_implicit(0, _oct_der(b"\xca\xfe\xba\xbe")))
KDCDHKEYINFO_DER = _seq(
_explicit(0, _bit_der(b"\xaa\xbb\xcc\xdd")), _explicit(1, _int_der(12345)), )
REPLYKEYPACK_DER = _seq(
_explicit(0, ENC_KEY_DER),
_explicit(1, CHECKSUM_DER),
)
EPI_SKI_DER = _seq(_implicit(2, _oct_der(b"\xde\xad\xbe\xef")))
EPI_ISN_DER = _seq(_implicit(1, ISSUER_SERIAL_DER))
AUTHPACK_DER = _seq(_explicit(0, PKA_DER))
AUTHPACK_KDF_DER = _seq(
_explicit(0, PKA_DER),
_explicit(4, _seq(KDFALGOID_DER)), )
PAPKASREQ_DER = _seq(_implicit(0, _oct_der(b"\x01\x02\x03\x04")))
PAPKASREP_DHINFO_DER = _explicit(0, DHREPINFO_DER)
PAPKASREP_ENCKEYPACK_DER = _implicit(1, _oct_der(b"\x05\x06\x07\x08"))
def demo_encryption_key():
section("EncryptionKey — RFC 3961 §2")
key = krb5.EncryptionKey.from_der(ENC_KEY_DER)
assert key.keytype == 17
assert key.keyvalue == b"\xaa" * 16
print(f" keytype: {key.keytype} (aes128-cts-hmac-sha1-96)")
print(f" keyvalue: {key.keyvalue.hex()}")
print(f" repr: {repr(key)}")
def demo_checksum():
section("Checksum — RFC 3961 §4")
ck = krb5.Checksum.from_der(CHECKSUM_DER)
assert ck.cksumtype == 7
assert ck.checksum == b"\xbb" * 8
print(f" cksumtype: {ck.cksumtype} (rsa-md5)")
print(f" checksum: {ck.checksum.hex()}")
print(f" repr: {repr(ck)}")
def demo_kdf_algorithm_id():
section("KDFAlgorithmId — RFC 8636 §3.1")
kdf = krb5.KDFAlgorithmId.from_der(KDFALGOID_DER)
assert str(kdf.kdf_id) == "1.3.6.1.5.2.3.6.2"
print(f" kdf_id: {kdf.kdf_id} (id-pkinit-kdf-ah-sha256)")
print(f" repr: {repr(kdf)}")
def demo_issuer_and_serial_number():
section("IssuerAndSerialNumber — RFC 4556 §3.2.2")
isn = krb5.IssuerAndSerialNumber.from_der(ISSUER_SERIAL_DER)
assert isn.issuer == b"\x30\x00"
assert isn.serial_number == 42
print(f" issuer (raw Name bytes): {isn.issuer.hex()}")
print(f" serial_number: {isn.serial_number}")
print(f" repr: {repr(isn)}")
def demo_external_principal_identifier():
section("ExternalPrincipalIdentifier — RFC 4556 §3.2.2")
epi_empty = krb5.ExternalPrincipalIdentifier.from_der(b"\x30\x00")
assert epi_empty.subject_name is None
assert epi_empty.issuer_and_serial_number is None
assert epi_empty.subject_key_identifier is None
print(f" empty EPI: all fields None ✓")
epi = krb5.ExternalPrincipalIdentifier.from_der(EPI_SKI_DER)
assert epi.subject_name is None
assert epi.issuer_and_serial_number is None
assert epi.subject_key_identifier == b"\xde\xad\xbe\xef"
print(f" subject_key_identifier: {epi.subject_key_identifier.hex()}")
epi2 = krb5.ExternalPrincipalIdentifier.from_der(EPI_ISN_DER)
assert epi2.subject_name is None
assert epi2.subject_key_identifier is None
isn = epi2.issuer_and_serial_number
assert isn is not None
assert isn.serial_number == 42
print(f" issuer_and_serial_number.serial: {isn.serial_number}")
def demo_pk_authenticator():
section("PKAuthenticator — RFC 4556 §3.2.1")
auth = krb5.PKAuthenticator.from_der(PKA_DER)
assert auth.cusec == 0
assert auth.ctime == "20260101000000Z"
assert auth.nonce == 12345
assert auth.pa_checksum is None
assert auth.freshness_token is None
print(f" cusec: {auth.cusec}")
print(f" ctime: {auth.ctime}")
print(f" nonce: {auth.nonce}")
print(f" pa_checksum: {auth.pa_checksum}")
print(f" freshness_token: {auth.freshness_token}")
print(f" repr: {repr(auth)}")
auth2 = krb5.PKAuthenticator.from_der(PKA_WITH_CHECKSUM_DER)
assert auth2.cusec == 500
assert auth2.nonce == 99999
assert auth2.pa_checksum == b"\xcc" * 20
print(f" (with pa_checksum) pa_checksum: {auth2.pa_checksum.hex()[:16]}...")
def demo_dh_rep_info():
section("DHRepInfo — RFC 4556 §3.2.4")
rep = krb5.DHRepInfo.from_der(DHREPINFO_DER)
assert rep.dh_signed_data == b"\xca\xfe\xba\xbe"
assert rep.server_dhnonce is None
print(f" dh_signed_data ({len(rep.dh_signed_data)} bytes): {rep.dh_signed_data.hex()}")
print(f" server_dhnonce: {rep.server_dhnonce}")
print(f" repr: {repr(rep)}")
def demo_kdc_dh_key_info():
section("KDCDHKeyInfo — RFC 4556 §3.2.4")
info = krb5.KDCDHKeyInfo.from_der(KDCDHKEYINFO_DER)
assert info.subject_public_key == b"\xaa\xbb\xcc\xdd"
assert info.nonce == 12345
assert info.dh_key_expiration is None
print(f" subject_public_key: {info.subject_public_key.hex()}")
print(f" nonce: {info.nonce}")
print(f" dh_key_expiration: {info.dh_key_expiration}")
print(f" repr: {repr(info)}")
def demo_reply_key_pack():
section("ReplyKeyPack — RFC 4556 §3.2.3")
pack = krb5.ReplyKeyPack.from_der(REPLYKEYPACK_DER)
key = pack.reply_key
ck = pack.as_checksum
assert key.keytype == 17
assert key.keyvalue == b"\xaa" * 16
assert ck.cksumtype == 7
assert ck.checksum == b"\xbb" * 8
print(f" reply_key.keytype: {key.keytype}")
print(f" reply_key.keyvalue: {key.keyvalue.hex()}")
print(f" as_checksum.cksumtype: {ck.cksumtype}")
print(f" as_checksum.checksum: {ck.checksum.hex()}")
def demo_pa_pk_as_rep():
section("PaPkAsRep — RFC 4556 §3.2.4 (CHOICE)")
rep = krb5.PaPkAsRep.from_der(PAPKASREP_DHINFO_DER)
assert rep.variant == "DhInfo"
assert rep.enc_key_pack is None
dh = rep.dh_info
assert dh is not None
assert dh.dh_signed_data == b"\xca\xfe\xba\xbe"
print(f" variant: {rep.variant}")
print(f" dh_info.dh_signed_data: {dh.dh_signed_data.hex()}")
print(f" repr: {repr(rep)}")
rep2 = krb5.PaPkAsRep.from_der(PAPKASREP_ENCKEYPACK_DER)
assert rep2.variant == "EncKeyPack"
assert rep2.dh_info is None
assert rep2.enc_key_pack == b"\x05\x06\x07\x08"
print(f" variant: {rep2.variant}")
print(f" enc_key_pack: {rep2.enc_key_pack.hex()}")
def demo_auth_pack():
section("AuthPack — RFC 4556 §3.2.1")
pack = krb5.AuthPack.from_der(AUTHPACK_DER)
pka = pack.pk_authenticator
assert pka.nonce == 12345
assert pka.ctime == "20260101000000Z"
assert pack.client_public_value is None
assert pack.supported_cmstypes is None
assert pack.client_dhnonce is None
assert pack.supported_kdfs is None
print(f" pk_authenticator.nonce: {pka.nonce}")
print(f" pk_authenticator.ctime: {pka.ctime}")
print(f" client_public_value: {pack.client_public_value}")
print(f" supported_kdfs: {pack.supported_kdfs}")
pack2 = krb5.AuthPack.from_der(AUTHPACK_KDF_DER)
kdfs = pack2.supported_kdfs
assert kdfs is not None
assert len(kdfs) == 1
assert str(kdfs[0].kdf_id) == "1.3.6.1.5.2.3.6.2"
print(f" supported_kdfs[0]: {kdfs[0].kdf_id}")
def demo_pa_pk_as_req():
section("PaPkAsReq — RFC 4556 §3.2.2")
req = krb5.PaPkAsReq.from_der(PAPKASREQ_DER)
assert req.signed_auth_pack == b"\x01\x02\x03\x04"
assert req.trusted_certifiers is None
assert req.kdc_pk_id is None
print(f" signed_auth_pack ({len(req.signed_auth_pack)} bytes): {req.signed_auth_pack.hex()}")
print(f" trusted_certifiers: {req.trusted_certifiers}")
print(f" kdc_pk_id: {req.kdc_pk_id}")
print(f" repr: {repr(req)}")
def main():
print("=" * 60)
print("Example 19: PKINIT ASN.1 structures (RFC 4556 / RFC 8636)")
print("=" * 60)
demo_encryption_key()
demo_checksum()
demo_kdf_algorithm_id()
demo_issuer_and_serial_number()
demo_external_principal_identifier()
demo_pk_authenticator()
demo_dh_rep_info()
demo_kdc_dh_key_info()
demo_reply_key_pack()
demo_pa_pk_as_rep()
demo_auth_pack()
demo_pa_pk_as_req()
print("\nAll PKINIT examples completed.")
if __name__ == "__main__":
main()