Meerkat Testing CT Log
A fully RFC 6962-compliant Certificate Transparency log for testing. Accepts precertificate chains and returns cryptographically valid Signed Certificate Timestamps (SCTs). Each request is served by a randomly selected identity from a pool of 8 fake log operators — so SCTs look like they came from different logs.
get-proof-by-hash, get-consistency-proof) return 400.
Log IDs and keys are stable per deployment; do not submit to real browsers or CT monitors.
Available Log Identities
One identity is selected at random per add-pre-chain request.
The returned SCT's id field identifies which log "signed" it.
All identities share a single API endpoint.
| Log Name | Operator | Log ID (base64) | MMD |
|---|---|---|---|
| Meerkat Kablouti CT 2025h1 | Kablouti Certificate Services | LrI+rDU5UrBMxHdSbQs/ksqkWY9YRNFCWqPirEja0d4= | 24 h |
| Meerkat Karkoub CT 2025h2 | Karkoub Trust Infrastructure | YHXtFj/61qZRVe/dcAk6irbvbFvUXSaS/g2F7frPWXw= | 24 h |
| Meerkat Sal7ouf CT 2026h1 | Sal7ouf Digital Logs | 0GyrD3U18/gs3w5Cf/jpOlUkyIsz4tOxpRK4/00bMQU= | 24 h |
| Meerkat Farhoud CT 2025 | Farhoud CT Authority | uHzh+4IJmL+9cP8Ftv3lIocyn32j0ZC1T4K/KMg1bSM= | 24 h |
| Meerkat Habhoub CT 2026 | Habhoub Certificate Logs | KP3TEyr1M4dUo6oaB6vnr1ZaUPNHFMMuEHCOE+cTur8= | 24 h |
| Meerkat Sardouk CT 2025h2 | Sardouk Log Services | 75rphm0netMoLthXadyqWWEjs+gMZL7KNGUkIR9Wre8= | 24 h |
| Meerkat Dhibi CT 2026h1 | Dhibi Digital Trust | 8xodcC80KcEd4+Xp3vhY4OYYS1fooc/yXuChfIk6XfE= | 24 h |
| Meerkat Bousannoun CT 2025 | Bousannoun Certificate Transparency | /71id3uHUcaJyROsw59G72GrEk5I36qPIuSsbklSlLw= | 24 h |
API Base URL: https://thameur.org/ct/v1/ ·
Log ID = SHA-256(SubjectPublicKeyInfo DER of the log's ECDSA P-256 public key)
API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /ct/v1/add-pre-chain | Submit a precertificate chain. Returns a signed SCT. Primary endpoint. |
| GET | /ct/v1/get-sth | Returns a signed tree head for the empty tree. Timestamp is the current UTC millisecond. |
| GET | /ct/v1/get-roots | Returns base64 DER of accepted root and issuing CA certificates. |
| GET | /ct/v1/get-entries | Always returns an empty list. Log is ephemeral — no entries are stored. ephemeral |
| GET | /ct/v1/get-proof-by-hash | Returns HTTP 400 — proof endpoints require persistence. not supported |
POST /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, selects a random log identity, and returns a signed SCT.
Request body:
Request fields:
| Field | Type | Notes |
|---|---|---|
| chain[0] | required | Base64-encoded DER precertificate. Must contain the CT poison extension (OID 1.3.6.1.4.1.11129.2.4.3, critical). |
| chain[1] | optional | Base64-encoded DER issuing CA certificate. Used to compute the issuer_key_hash. If absent, the Meerkat Issuing CA cert is used. |
| chain[2…N] | optional | Additional intermediate CA certificates up to the accepted root (max 10 total). Not used in SCT computation. |
Success response (HTTP 200):
GET /ct/v1/get-sth
Returns a freshly signed Signed Tree Head for the empty tree (tree_size = 0). A new timestamp and a randomly selected log key are used on each call.
GET /ct/v1/get-roots
SCT & Signed Data Structure
The signature field contains a base64-encoded DigitallySigned struct (RFC 6962 §3.2).
The data signed by the log for a precertificate entry (precert_entry = 1):
| Field | Size | Value |
|---|---|---|
| version | 1 byte | 0x00 (v1) |
| signature_type | 1 byte | 0x00 (certificate_timestamp) |
| timestamp | 8 bytes | uint64 big-endian milliseconds since epoch |
| entry_type | 2 bytes | 0x00 0x01 (precert_entry) |
| issuer_key_hash | 32 bytes | SHA-256 of issuer SubjectPublicKeyInfo DER |
| tbs_certificate length | 3 bytes | uint24 big-endian byte count of the TBS |
| tbs_certificate | variable | DER TBSCertificate with CT poison extension removed |
| extensions length | 2 bytes | 0x00 0x00 (no extensions) |
The DigitallySigned encoding:
| Byte(s) | Field | Value |
|---|---|---|
0x04 | hash_algorithm | SHA-256 |
0x03 | signature_algorithm | ECDSA |
| 2 bytes | signature length (uint16 big-endian) | DER ECDSA signature byte count |
| variable | signature | DER-encoded ECDSA signature over the signed data above (P-256 + SHA-256) |
Error Responses
All errors return JSON with error_code (HTTP status) and error_message.
| HTTP | Cause |
|---|---|
| 400 | Missing or malformed chain field; base64 decode failure; chain[0] is not a valid X.509 certificate; CT poison extension not present; proof endpoint requested. |
| 405 | Wrong HTTP method (e.g. GET on add-pre-chain). |
| 404 | Unknown endpoint. |
| 500 | DER parsing failure; ECDSA signing error; log keys not yet generated. |
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 — Encode the chain as base64 DER
Step 3 — Submit to add-pre-chain
Step 4 — Example SCT response
Verify the SCT signature (OpenSSL)
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
- Randomisation: Each request picks one of 8 ECDSA P-256 key pairs at random. The
idin the SCT uniquely identifies which log "signed" it. This prevents issued test certs from appearing to always submit to a single log. - No persistence: The Merkle tree is never built.
get-entriesalways returns an empty list. SCTs are produced on-the-fly — there is no audit trail. - 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. Extensions are re-encoded in-place; no other fields are modified.
- IssuerKeyHash: Computed as SHA-256 of the SubjectPublicKeyInfo DER of the issuing CA certificate (chain[1], or the Meerkat Issuing CA if absent).
- Accepted roots: Meerkat Root CA and Meerkat Test Issuing CA 1. Submit the chain up to one of these two.
- CORS: All endpoints respond with
Access-Control-Allow-Origin: *for browser-based testing. - RFC 6962 §4.1 chain requirement: The chain must chain to an accepted root. Full path verification is not enforced in this testing implementation.