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

Merkle Tree Certificates

synta.mtc implements the ASN.1 types from draft-ietf-plants-merkle-tree-certs. All classes are immutable (frozen) and constructed via from_der static methods.

import synta.mtc as mtc

Name fields such as issuer_der and subject_der are raw DER-encoded Name SEQUENCES; pass them to synta.parse_name_attrs() to decode the DN attributes.

ProofNode

A single node in a Merkle inclusion proof path.

class ProofNode:
    @staticmethod
    def from_der(data: bytes) -> ProofNode: ...
    is_left: bool   # True if this is the left sibling in the path
    hash: bytes     # raw hash bytes at this proof node

Subtree

A hash subtree covering leaf range [start, end).

class Subtree:
    @staticmethod
    def from_der(data: bytes) -> Subtree: ...
    start: int    # start leaf index (inclusive)
    end: int      # end leaf index (exclusive)
    value: bytes  # aggregated hash bytes for [start, end)

SubtreeProof

Left and right subtree lists for log compaction.

class SubtreeProof:
    @staticmethod
    def from_der(data: bytes) -> SubtreeProof: ...
    left_subtrees: list[Subtree] | None
    right_subtrees: list[Subtree] | None

InclusionProof

Merkle inclusion proof for a log entry.

class InclusionProof:
    @staticmethod
    def from_der(data: bytes) -> InclusionProof: ...
    log_entry_index: int              # leaf position of the certified entry
    tree_size: int                    # total leaves at proof time
    inclusion_path: list[ProofNode]   # ordered sibling hashes

LogID

Identifies a transparency log by its hash algorithm and public key.

class LogID:
    @staticmethod
    def from_der(data: bytes) -> LogID: ...
    hash_alg_oid: str       # hash algorithm OID (dot-notation)
    public_key_der: bytes   # DER-encoded SubjectPublicKeyInfo

CosignerID

Identifies a cosigner (witness) in a countersigned checkpoint.

class CosignerID:
    @staticmethod
    def from_der(data: bytes) -> CosignerID: ...
    hash_alg_oid: str
    public_key_der: bytes

Checkpoint

A signed tree head from a transparency log.

class Checkpoint:
    @staticmethod
    def from_der(data: bytes) -> Checkpoint: ...
    log_id: LogID
    tree_size: int
    timestamp: int      # milliseconds since Unix epoch
    root_hash: bytes
    signature: bytes

SubtreeSignature

A cosigner signature over a checkpoint and subtree proof.

class SubtreeSignature:
    @staticmethod
    def from_der(data: bytes) -> SubtreeSignature: ...
    cosigner_id: CosignerID
    tree_size: int
    timestamp: int
    root_hash: bytes
    signature: bytes

TbsCertificateLogEntry

The to-be-signed body of a Merkle Tree Certificate log entry.

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

    issuer_der: bytes                            # raw Name DER
    validity_not_before: str                     # GeneralizedTime string
    validity_not_after: str                      # GeneralizedTime string
    subject_der: bytes                           # raw Name DER
    subject_public_key_algorithm_oid: str        # algorithm OID
    subject_public_key_hash: bytes               # hash of the SPKI
    issuer_unique_id: bytes | None
    subject_unique_id: bytes | None
    extensions_der: bytes | None                 # raw extensions DER

MerkleTreeCertEntry

Top-level CHOICE wrapper for a Merkle Tree Certificate entry.

class MerkleTreeCertEntry:
    @staticmethod
    def from_der(data: bytes) -> MerkleTreeCertEntry: ...
    variant: str                         # "StandaloneCertificate" or "LandmarkCertificate"
    standalone: StandaloneCertificate | None
    landmark: LandmarkCertificate | None

LandmarkID

Identifies a landmark certificate in the MTC ecosystem.

class LandmarkID:
    @staticmethod
    def from_der(data: bytes) -> LandmarkID: ...
    hash_alg_oid: str
    public_key_der: bytes
    tree_size: int

StandaloneCertificate

class StandaloneCertificate:
    @staticmethod
    def from_der(data: bytes) -> StandaloneCertificate: ...
    proof: InclusionProof
    checkpoint: Checkpoint
    subtree_proof: SubtreeProof | None
    cosignatures: list[SubtreeSignature]
    tbs_cert: TbsCertificateLogEntry
    cert_der: bytes | None          # optional original X.509 DER
    extensions_der: bytes | None

LandmarkCertificate

class LandmarkCertificate:
    @staticmethod
    def from_der(data: bytes) -> LandmarkCertificate: ...
    landmark_id: LandmarkID
    proof: InclusionProof
    checkpoint: Checkpoint
    tbs_cert: TbsCertificateLogEntry
    cert_der: bytes | None
    extensions_der: bytes | None

Usage

import synta
import synta.mtc as mtc

# Parse a Merkle Tree Certificate entry
entry = mtc.MerkleTreeCertEntry.from_der(data)
if entry.variant == "StandaloneCertificate":
    sc = entry.standalone
    print(f"tree size: {sc.checkpoint.tree_size}")
    print(f"leaf index: {sc.proof.log_entry_index}")
    issuer = synta.parse_name_attrs(sc.tbs_cert.issuer_der)
    subject = synta.parse_name_attrs(sc.tbs_cert.subject_der)
    print(f"issuer: {issuer}")
    print(f"subject: {subject}")