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}")