Test log — do not submit to real browsers or CT monitors. Log IDs and keys are stable per deployment. SCTs are valid and Merkle trees are maintained, but these logs are not trusted by any browser, OS, or CT auditor.

Available Log Identities

Each identity is a fully independent CT log. Submit to the log's own /{slug}/ct/v1/add-pre-chain endpoint to receive an SCT signed by that log's key. The returned SCT's id field identifies which log signed it.

Log Name Operator Base URL Log ID (base64) MMD
Meerkat Bousannoun CT 2025 Bousannoun Certificate Transparency https://thameur.org/bousannoun/ct/v1/ iwnHdSIcKx8Ghz4kbh8q6pXRm1W8R4ELzhB+zQsYcCs= 24 h
Chalhoub CT 2026h2 Ganfous Errdaief GMBH https://thameur.org/chalhoub/ct/v1/ QbqhGVKRrVFvtBi5Me9culXIlDi/9a7JupvFgD6bWfU= 24 h
Meerkat Dhibi CT 2026h1 Dhibi Digital Trust https://thameur.org/dhibi/ct/v1/ fH1x8dROT9Kw0LwQMvc4xYjq7PJMyzypx4yZjy58efM= 24 h
Meerkat Farhoud CT 2025 Farhoud CT Authority https://thameur.org/farhoud/ct/v1/ hvxltxKBcrAnEDZHWgf6nMYy07hkovBzcnZg2WBSD68= 24 h
Meerkat Habhoub CT 2026 Habhoub Certificate Logs https://thameur.org/habhoub/ct/v1/ N4FkhYpvMuQqv/rBV+ifYqOB2M516xKaivOkxHdzHVk= 24 h
Finally the ninth CT LOG Harhour GMBH https://thameur.org/harhour/ct/v1/ nb4XK1iOYM2Lk+khiyBUXuycsZcqzV5WpQG4ifKluuA= 24 h
Meerkat Kablouti CT 2025h1 Kablouti Certificate Services https://thameur.org/kablouti/ct/v1/ hTHSlyqT8WJPI8sY3+w8rATgCEhtul+mdijguxKrOt4= 24 h
Meerkat Karkoub CT 2025h2 Karkoub Trust Infrastructure https://thameur.org/karkoub/ct/v1/ Y/QMWnvgbCTNukIqMBNwqx8BH3V4NyA2/TyklEhpFH8= 24 h
Meerkat Sal7ouf CT 2026h1 Sal7ouf Digital Logs https://thameur.org/sal7ouf/ct/v1/ bzp3sBRXyfGvWrmAJtkBhiCPhUFlW65qSRgce7ghsSY= 24 h
Meerkat Sardouk CT 2025h2 Sardouk Log Services https://thameur.org/sardouk/ct/v1/ B9HDwAipkqj3Rc8AB0cfPPxCwro9whPdosOHWztOovM= 24 h

Log ID = SHA-256(SubjectPublicKeyInfo DER of the log's ECDSA P-256 public key)

API Endpoints

Replace {slug} with the log slug (e.g. kablouti). Each log has its own independent Merkle tree.

MethodPathDescription
POST/{slug}/ct/v1/add-pre-chainSubmit a precertificate chain. Returns a signed SCT and persists the entry in this log's Merkle tree. Primary endpoint.
GET/{slug}/ct/v1/get-sthReturns a signed tree head for this log's Merkle tree.
GET/{slug}/ct/v1/get-rootsReturns base64 DER of accepted root and issuing CA certificates.
GET/{slug}/ct/v1/get-entriesReturns persisted log entries for a given leaf index range within this log.
GET/{slug}/ct/v1/get-proof-by-hashReturns a Merkle audit proof for a given leaf hash within this log's tree.

POST /{slug}/ct/v1/add-pre-chain

Accepts a JSON body containing the precertificate chain (RFC 6962 §4.1). Validates the CT poison extension, strips it from the TBSCertificate, computes the issuer key hash, signs the SCT with the log's key, and persists the entry in this log's Merkle tree.

Request body:

// Content-Type: application/json { "chain": [ "<base64-DER-precertificate>", // required — must contain OID 1.3.6.1.4.1.11129.2.4.3 "<base64-DER-issuing-CA-cert>" // optional — falls back to Meerkat Issuing CA if omitted ] }

Request fields:

FieldTypeNotes
chain[0]requiredBase64-encoded DER precertificate. Must contain the CT poison extension (OID 1.3.6.1.4.1.11129.2.4.3, critical).
chain[1]optionalBase64-encoded DER issuing CA certificate. Used to compute the issuer_key_hash. If absent, the Meerkat Issuing CA cert is used.
chain[2…N]optionalAdditional intermediate CA certificates up to the accepted root (max 10 total). Stored in extra_data for get-entries.

Success response (HTTP 200):

{ "sct_version": 0, // always 0 (v1) "id": "<base64 32-byte log ID>", // SHA-256(SPKI) of this log's key "timestamp": 1747217000000, // Unix milliseconds (uint64) "extensions": "", // always empty "signature": "<base64 DigitallySigned>" // see SCT Structure below }

GET /{slug}/ct/v1/get-sth

Returns a freshly signed Signed Tree Head for this log's Merkle tree. The tree_size and sha256_root_hash reflect the current state of entries submitted to this specific log.

{ "tree_size": 42, // entries in this log's tree "timestamp": 1747217000000, "sha256_root_hash": "<base64 32-byte MTH>", // RFC 6962 §2.1 Merkle Tree Hash "tree_head_signature": "<base64 DigitallySigned>" }

GET /{slug}/ct/v1/get-roots

{ "certificates": [ "<base64 DER Meerkat Root CA>", "<base64 DER Meerkat Issuing CA>" ] }

GET /{slug}/ct/v1/get-entries?start=<n>&end=<m>

Returns persisted log entries for leaf indices [start, end] inclusive within this log's own tree (0-indexed). Maximum 1 000 entries per request.

ParameterTypeNotes
startrequiredFirst leaf index to return (0-based, within this log).
endrequiredLast leaf index to return (inclusive). Clamped to start + 999.
{ "entries": [ { "leaf_input": "<base64 MerkleTreeLeaf>", // RFC 6962 §3.4 leaf structure "extra_data": "<base64 PrecertChainEntry>" // RFC 6962 §3.1: precert + issuer chain }, ... ] }

GET /{slug}/ct/v1/get-proof-by-hash?hash=<base64>&tree_size=<n>

Returns a Merkle audit proof (RFC 6962 §4.5) for the leaf identified by its hash within this log's tree.

ParameterTypeNotes
hashrequiredBase64 of SHA-256(0x00 || MerkleTreeLeaf) — the leaf hash.
tree_sizeoptionalSnapshot tree size to prove against. Defaults to current tree size for this log.
{ "leaf_index": 5, "audit_path": [ "<base64 32-byte sibling hash>", "<base64 32-byte sibling hash>" ... ] }

Verify the proof with the STH root hash: reconstruct the path hash from leaf → root by applying SHA-256(0x01 || left || right) at each level, and compare the final hash against sha256_root_hash from get-sth.

Merkle Tree (RFC 6962 §2.1)

Each log maintains its own independent Merkle tree. Leaf hashes and interior node hashes follow RFC 6962 §2.1 conventions:

Node typeHash computation
Empty treeSHA-256("")
Leaf nodeSHA-256(0x00 || MerkleTreeLeaf) — stored as leaf_hash
Interior nodeSHA-256(0x01 || left_child || right_child)

SCT & Signed Data Structure

The signature field contains a base64-encoded DigitallySigned struct (RFC 6962 §3.2). The signed data for a precert_entry is identical to the MerkleTreeLeaf wire format — both start with 0x00 0x00 (version + signature_type / leaf_type):

FieldSizeValue
version / leaf_type1 + 1 byte0x00 0x00 (v1, certificate_timestamp / timestamped_entry)
timestamp8 bytesuint64 big-endian milliseconds since epoch
entry_type2 bytes0x00 0x01 (precert_entry)
issuer_key_hash32 bytesSHA-256 of issuer SubjectPublicKeyInfo DER
tbs_certificate length3 bytesuint24 big-endian byte count of the TBS
tbs_certificatevariableDER TBSCertificate with CT poison extension removed
extensions length2 bytes0x00 0x00 (no extensions)

Error Responses

All errors return JSON with error_code (HTTP status) and error_message.

HTTPCause
400Missing or malformed chain field; base64 decode failure; chain[0] is not a valid X.509 certificate; CT poison extension not present; invalid hash or start/end parameters; leaf not within tree_size snapshot.
404Unknown slug; unknown endpoint; hash not found in this log.
405Wrong HTTP method (e.g. GET on add-pre-chain).
503Log slug is active but has no keys — issue keys from the admin panel.
500DER parsing failure; ECDSA signing error.

Integration Guide

Step 1 — Issue a precertificate

Use the Meerkat Certificate Factory "Issue Precertificate" button, or issue one via your own CA pipeline with the CT poison extension (OID 1.3.6.1.4.1.11129.2.4.3, critical, value = ASN.1 NULL 05 00).

Step 2 — Submit to a specific log's add-pre-chain

curl -s -X POST https://thameur.org/kablouti/ct/v1/add-pre-chain \ -H 'Content-Type: application/json' \ -d '{ "chain": [ "'"$(openssl x509 -in precert.pem -outform DER | base64 -w0)"'", "'"$(openssl x509 -in issuing-ca.pem -outform DER | base64 -w0)"'" ] }' | jq .

Submit the same precertificate to multiple log slugs to collect independent SCTs from different log identities.

Step 3 — Verify inclusion with get-proof-by-hash

The leaf hash is SHA-256(0x00 || leaf_input) where leaf_input is the MerkleTreeLeaf bytes from the SCT. Pass the base64 leaf hash to get-proof-by-hash, then reconstruct the root from the audit path and compare against get-sth.

Embed the SCT in a certificate extension

The SCT can be embedded in the final certificate as a SignedCertificateTimestampList (OID 1.3.6.1.4.1.11129.2.4.2), or delivered via a TLS extension, or via OCSP stapling. Encoding of the SCT list is described in RFC 6962 §3.3.

Technical Notes

  • Independent logs: Each slug is a completely separate CT log with its own ECDSA P-256 key pair and its own Merkle tree. There is no shared state between logs.
  • Persistence: Every submitted precertificate is stored in the database scoped to the target log. get-entries returns entries only for the queried log. get-sth reflects the real tree size and Merkle root for that log.
  • Poison stripping: The TBSCertificate submitted in the chain has the CT poison extension (OID 1.3.6.1.4.1.11129.2.4.3) removed before it is hashed into the signed data, per RFC 6962 §3.2.
  • IssuerKeyHash: Computed as SHA-256 of the SubjectPublicKeyInfo DER of the issuing CA certificate (chain[1], or the Meerkat Issuing CA if absent).
  • CORS: All endpoints respond with Access-Control-Allow-Origin: * for browser-based testing.

We use only essential cookies and local browser storage for preferences and security. See our Privacy Policy for details.

Confirm action