The monitor attempts to fetch each log's current Signed Tree Head (STH)
every 5 minutes using the /ct/v1/get-sth
endpoint. The uptime
column shows the percentage of get-sth
requests that were
successful over a rolling period of the last 90 days.
Responses must contain valid JSON to be counted as successful. Therefore, even if a log is reachable, it may still be counted as down if the monitor can't parse the STH or if the log does not return a HTTP 200 OK response.
The uptime calculation is intended to roughly match Chromium's log uptime requirements. However, Google's exact requirements are not publicly known and it is likely that the methodology the monitor uses is much simpler than Google's. Therefore, it shouldn't be surprising if the figures on this website do not match up with Google's figures.
Due to disk space requirements, the backend of the monitor is hosted on my home server, which is connected to the Internet using a residential VDSL2 connection. The connection does go down occasionally and all the logs will be counted as down if this happens.
The monitor also exchanges STH gossip with other monitors every 5 minutes. For logs which have mirrors, it also fetches the current STH from each mirror.
Gossiped STHs fetched from other monitors and mirrors are treated in almost exactly the same manner as STHs fetched directly from the log. There are a few minor exceptions:
Signed Tree Heads that have not yet been verified are marked as pending. Generally, they are not in this state for long as the monitor continuously polls the queue of pending STHs to verify them. However, verifying an STH requires downloading all the entries up to its tree size. It can therefore take a while to verify the STHs belonging to a log that was recently added to the monitor or whose tree size has suddenly increased by a large number.
After verification, a STH is marked as either good or bad. There are a number of failures that can cause a STH to be marked as bad. The internal codes and an explanation of each are displayed in the list below:
Indicates that the signature is not valid.
Indicates that the signature is not signed with a hash algorithm of SHA-256, as required by section 2.1.4 of RFC 6962.
The signature algorithm itself is checked separately when the monitor starts up, by examining the log's key. Checking the key, rather than the algorithm identifier in the STH, also allows the key length or curve to be checked. The results of this check are not currently displayed in the web interface.
Indicates that the Merkle Tree Hash in the STH does not match the hash computed locally by the monitor. This indicates that the log has violated the append-only property.
Indicates that the difference between this STH and the previous STH is greater than the log's Maximum Merge Delay (MMD).
In an attempt to prevent false positives caused by monitor downtime, the monitor must have at least attempted to make half of the requests it would normally have done so between the two STH timestamps.
False positives caused by network outages may still occur. This additional check only prevents false positives caused by power outages or the monitor backend crashing.
This check if skipped if the log has not committed to an MMD.
Indicates that the STH's timestamp is before the timestamp of a prior
TimestampedEntry
in the tree. This is forbidden by
section 3.5
of RFC 6962.
Indicates that the tree size is strictly less than the previous STH's tree size or strictly greater than the next STH's tree size. This indicates that the log has violated the append-only property.
Indicates that the tree size is strictly greater than the final STH's tree size if the log is frozen.
Indicates that the timestamp is after the final STH's timestamp if the log is frozen.
Indicates that the STH's timestamp was in the future at the time the STH was fetched.
Indicates that the STH's timestamp was at least as old as the log's MMD at the time the STH was fetched.
This check is skipped if the log has not committed to an MMD or is frozen.
Signed Tree Heads may not be received in order. For example, some logs are distributed across multiple servers and a subsequent request may be routed to a different server that is lagging behind the original server. It takes time for STH gossip to propagate between monitors, by which time the log may already be serving a newer STH.
The monitor allows for STHs to be verified in any order by maintaining a list of verified STHs sorted by timestamp. When an STH is pulled from the queue of STHs that are awaiting verification, it is inserted into the list using an 'insertion sort'-style algorithm. The STH is checked against the STHs on either side of it - not just the previous STH.
The monitor's time is synchronized to UTC using NTP. It currently allows for up to 1 minute of clock skew, in the log's favour, when comparisons are made between the monitor's view of time and a log's view of time. This allowance may be reduced in the future.
No allowance for clock skew is made when comparing two times which are both from the log's point of view - for example, the gap between two adjacent STHs.
The following algorithm is used to determine the overall status of each log shown on the index page:
The monitor periodically requests each log's list of accepted root certificates. The current list of root certificates is stored in the database, along with a history of the changes (additions and removals) and the time at which each change was observed. This information is not currently displayed in the web interface.
As the monitor stores a copy of all log entries, disk usage is a concern - particularly given the append-only property of logs!
The raw entries can't be de-duplicated - even if two logs contain the same certificate, it's unlikely that the entry timestamps will match. The monitor therefore parses the entries and de-duplicates certificates and precertificates. This is quite effective: many certificates are logged to several logs because of Chromium's quorum requirements, and even within the same log many entries use the same intermediate and root certificates.
All the data from each entry is stored such that the original
leaf_input
and extra_data
can be reconstructed if
required.
If an entry cannot be parsed or is of an unknown type it is treated as opaque input into the tree, as per section 4.6 of RFC 6962.