synta 0.1.8

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# Krb5PrincipalName


`Krb5PrincipalName` encodes and decodes the `KRB5PrincipalName` structure (RFC 4556 ยง3.2.2)
used as an `OtherName` Subject Alternative Name value in PKINIT certificates.

## Class

```python
class Krb5PrincipalName:
    def __init__(self, realm: str, name_type: int, components: list[str]) -> None: ...
    # realm must be ASCII.  name_type is one of the NT_* constants.
    # All string arguments must be ASCII; raises ValueError otherwise.

    @staticmethod
    def from_der(data: bytes) -> Krb5PrincipalName: ...

    def to_der(self) -> bytes: ...

    realm: str             # Kerberos realm (e.g. "EXAMPLE.COM")
    name_type: int         # One of the NT_* constants
    components: list[str]  # Name-string components

    def __repr__(self) -> str: ...
    def __eq__(self, other) -> bool: ...
```

## Usage

```python
import synta.krb5 as krb5

# Construct a host principal: host/server.example.com@EXAMPLE.COM
principal = krb5.Krb5PrincipalName(
    realm="EXAMPLE.COM",
    name_type=krb5.NT_SRV_HST,
    components=["host", "server.example.com"],
)
der_bytes = principal.to_der()

# Parse from DER
parsed = krb5.Krb5PrincipalName.from_der(der_bytes)
print(parsed.realm)          # "EXAMPLE.COM"
print(parsed.name_type)      # 3  (NT_SRV_HST)
print(parsed.components)     # ["host", "server.example.com"]

# Read from a PKINIT certificate SAN (OtherName entry)
import synta
import synta.general_name as gn

for san in cert.subject_alt_names():
    if isinstance(san, gn.OtherName):
        # san.type_id is the OID; san.value is the raw DER value bytes
        if san.type_id == krb5.KRB5_PRINCIPAL_NAME_OID:
            # value is the [0] EXPLICIT-wrapped KRB5PrincipalName
            dec = synta.Decoder(san.value, synta.Encoding.DER)
            explicit = dec.decode_explicit_tag(0)
            kpn = krb5.Krb5PrincipalName.from_der(explicit.remaining_bytes())
            print(f"realm={kpn.realm}, name_type={kpn.name_type}, components={kpn.components}")
```

## Encoding a principal name for certificate generation

```python
import synta
import synta.krb5 as krb5

# Build an otherName SAN entry for a PKINIT client certificate
kpn = krb5.Krb5PrincipalName(
    realm="EXAMPLE.COM",
    name_type=krb5.NT_PRINCIPAL,
    components=["alice"],
)
kpn_der = kpn.to_der()

# Wrap in OtherName: SEQUENCE { type-id OID, value [0] EXPLICIT <kpn_der> }
inner = synta.Encoder(synta.Encoding.DER)
inner.encode_oid(krb5.KRB5_PRINCIPAL_NAME_OID)
inner.encode_explicit_tag(0, "Context", kpn_der)

outer = synta.Encoder(synta.Encoding.DER)
outer.encode_sequence(inner.finish())
other_name_der = outer.finish()

# The SAN builder does not have a dedicated other_name() method.
# Encode the SAN extension value manually using the Encoder:
enc = synta.Encoder(synta.Encoding.DER)
enc.encode_sequence(other_name_der)  # wrap in outer SEQUENCE OF GeneralName
san_value_der = enc.finish()
# Then pass san_value_der as the extnValue to your certificate builder.
```

See also [Kerberos V5 Types](krb5.md) for principal-name type and encryption type constants,
and [PKINIT Types](krb5-pkinit.md) for the full PKINIT protocol structure set.