Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

X.509 Extension Value Builders

synta.ext provides DER-encoding helpers for the most common X.509 v3 extension values. Each function returns the raw extnValue bytes (the content inside the OCTET STRING wrapper in the Extension SEQUENCE). Import with import synta.ext as ext.

subject_key_identifier and authority_key_identifier require the openssl Cargo feature. basic_constraints, key_usage, and the three builder classes do not.

Key identifier method constants

Pass one of these to subject_key_identifier or authority_key_identifier:

ConstantValueHashInputOutput lengthSpecification
KEYID_RFC52800SHA-1BIT STRING value of subjectPublicKey20 bytesRFC 5280 §4.2.1.2
KEYID_RFC7093M11SHA-256BIT STRING value of subjectPublicKey20 bytes (truncated)RFC 7093 §2 m1
KEYID_RFC7093M22SHA-384BIT STRING value of subjectPublicKey20 bytes (truncated)RFC 7093 §2 m2
KEYID_RFC7093M33SHA-512BIT STRING value of subjectPublicKey20 bytes (truncated)RFC 7093 §2 m3
KEYID_RFC7093M44SHA-256full SubjectPublicKeyInfo DER32 bytesRFC 7093 §2 m4

Key usage bitmask constants

OR these together and pass the result to key_usage():

ConstantMaskNamed bit (RFC 5280 §4.2.1.3)
KU_DIGITAL_SIGNATURE0x001digitalSignature
KU_NON_REPUDIATION0x002contentCommitment
KU_KEY_ENCIPHERMENT0x004keyEncipherment
KU_DATA_ENCIPHERMENT0x008dataEncipherment
KU_KEY_AGREEMENT0x010keyAgreement
KU_KEY_CERT_SIGN0x020keyCertSign
KU_CRL_SIGN0x040cRLSign
KU_ENCIPHER_ONLY0x080encipherOnly
KU_DECIPHER_ONLY0x100decipherOnly

Functions

def basic_constraints(ca: bool = False, path_length: int | None = None) -> bytes: ...

Encode a BasicConstraints extension value (OID 2.5.29.19). Returns the DER SEQUENCE bytes. When ca is False the cA field is omitted (DER DEFAULT-FALSE rule). path_length is ignored when ca is False.

def key_usage(bits: int) -> bytes: ...

Encode a KeyUsage extension value (OID 2.5.29.15). bits is an integer formed by OR-ing KU_* constants. Returns the DER BIT STRING bytes.

def subject_key_identifier(spki_der: bytes, method: int = KEYID_RFC5280) -> bytes: ...

Encode a SubjectKeyIdentifier extension value (OID 2.5.29.14). spki_der must be a complete DER-encoded SubjectPublicKeyInfo. method selects the key-identifier algorithm. Returns the DER OCTET STRING value. Raises ValueError if spki_der cannot be decoded.

def authority_key_identifier(issuer_spki_der: bytes, method: int = KEYID_RFC5280) -> bytes: ...

Encode an AuthorityKeyIdentifier extension value (OID 2.5.29.35). Sets only the keyIdentifier [0] field. Returns the DER AuthorityKeyIdentifier SEQUENCE bytes.

Fluent builder classes

Three builder classes accumulate entries and produce the complete DER extnValue on .build(). No openssl Cargo feature is required.

SubjectAlternativeNameBuilder (alias: SAN)

class SubjectAlternativeNameBuilder:
    def __init__(self) -> None: ...
    def dns_name(self, name: str) -> SubjectAlternativeNameBuilder: ...
    def rfc822_name(self, email: str) -> SubjectAlternativeNameBuilder: ...
    def uri(self, uri: str) -> SubjectAlternativeNameBuilder: ...
    def ip_address(self, addr: bytes) -> SubjectAlternativeNameBuilder: ...
    # Pass 4 bytes for IPv4 or 16 bytes for IPv6.
    def directory_name(self, name_der: bytes) -> SubjectAlternativeNameBuilder: ...
    # name_der is the DER TLV of a Name SEQUENCE.
    def registered_id(self, oid_comps: list[int]) -> SubjectAlternativeNameBuilder: ...
    def build(self) -> bytes: ...
    # Return the DER GeneralNames SEQUENCE.  Raises ValueError on encoding error.

SAN = SubjectAlternativeNameBuilder  # short alias

AuthorityInformationAccessBuilder (alias: AIA)

class AuthorityInformationAccessBuilder:
    def __init__(self) -> None: ...
    def ocsp(self, uri: str) -> AuthorityInformationAccessBuilder: ...
    def ca_issuers(self, uri: str) -> AuthorityInformationAccessBuilder: ...
    def build(self) -> bytes: ...

AIA = AuthorityInformationAccessBuilder  # short alias

ExtendedKeyUsageBuilder (alias: EKU)

class ExtendedKeyUsageBuilder:
    def __init__(self) -> None: ...
    def server_auth(self) -> ExtendedKeyUsageBuilder: ...    # id-kp-serverAuth
    def client_auth(self) -> ExtendedKeyUsageBuilder: ...    # id-kp-clientAuth
    def code_signing(self) -> ExtendedKeyUsageBuilder: ...   # id-kp-codeSigning
    def email_protection(self) -> ExtendedKeyUsageBuilder: ... # id-kp-emailProtection
    def time_stamping(self) -> ExtendedKeyUsageBuilder: ...  # id-kp-timeStamping
    def ocsp_signing(self) -> ExtendedKeyUsageBuilder: ...   # id-kp-OCSPSigning
    def add_oid(self, oid: str | ObjectIdentifier) -> ExtendedKeyUsageBuilder: ...
    def build(self) -> bytes: ...

EKU = ExtendedKeyUsageBuilder  # short alias

Usage

import synta
import synta.ext as ext

# Parse a CA certificate to extract its SubjectPublicKeyInfo DER
ca_der = open("ca.der", "rb").read()
ca_cert = synta.Certificate.from_der(ca_der)
spki_der = ca_cert.subject_public_key_info_raw_der

# ── BasicConstraints (OID 2.5.29.19) ──────────────────────────────────────────

# End-entity certificate: empty SEQUENCE → 30 00
ee_bc = ext.basic_constraints()

# CA with no path-length limit: cA = TRUE → 30 03 01 01 ff
ca_bc = ext.basic_constraints(ca=True)

# CA with pathLen = 0 → 30 06 01 01 ff 02 01 00
ca_pl0 = ext.basic_constraints(ca=True, path_length=0)

# ── KeyUsage (OID 2.5.29.15) ──────────────────────────────────────────────────

# Typical CA key usage: keyCertSign | cRLSign | digitalSignature
ku = ext.key_usage(ext.KU_KEY_CERT_SIGN | ext.KU_CRL_SIGN | ext.KU_DIGITAL_SIGNATURE)

# TLS server key usage: digitalSignature | keyEncipherment
ku_server = ext.key_usage(ext.KU_DIGITAL_SIGNATURE | ext.KU_KEY_ENCIPHERMENT)

# ── SubjectKeyIdentifier (OID 2.5.29.14) ──────────────────────────────────────

# RFC 5280 default: SHA-1 of the BIT STRING value of subjectPublicKey
ski = ext.subject_key_identifier(spki_der)

# RFC 7093 method 1: SHA-256 of BIT STRING value, truncated to 160 bits
ski_m1 = ext.subject_key_identifier(spki_der, method=ext.KEYID_RFC7093M1)

# RFC 7093 method 4: SHA-256 of the full SubjectPublicKeyInfo DER
ski_m4 = ext.subject_key_identifier(spki_der, method=ext.KEYID_RFC7093M4)

# ── AuthorityKeyIdentifier (OID 2.5.29.35) ────────────────────────────────────

aki = ext.authority_key_identifier(spki_der)
aki_m1 = ext.authority_key_identifier(spki_der, method=ext.KEYID_RFC7093M1)

# ── Fluent builders ───────────────────────────────────────────────────────────

san = ext.SAN().dns_name("www.example.com").dns_name("example.com").build()
aia = ext.AIA().ocsp("http://ocsp.example.com").ca_issuers("http://ca.example.com/ca.crt").build()
eku = ext.EKU().server_auth().client_auth().build()

See also CRL and OCSP Builders for building complete CRL and OCSP response structures.