The padlock
TLS encrypts the connection — but encryption to the *wrong* server is worthless. So the server presents a certificate chain: its own certificate, signed by an intermediate, signed by a root CA your device already trusts. The browser checks the name, the dates and every link of the chain.
The checks
function matchesHost(pattern, host) {
if (pattern.startsWith("*.")) {
const i = host.indexOf(".");
return i > 0 && host.slice(i) === pattern.slice(1); // a wildcard covers exactly one label
}
return pattern === host;
}
function verifyChain(chain, roots, host, now) {
const leaf = chain[0];
if (!leaf.names.some((n) => matchesHost(n, host))) return { ok: false, reason: "hostname mismatch" };
for (const cert of chain) {
if (now < cert.notBefore) return { ok: false, reason: `not yet valid: ${cert.subject}` };
if (now > cert.notAfter) return { ok: false, reason: `expired: ${cert.subject}` };
}
for (let i = 0; i + 1 < chain.length; i++) {
if (chain[i].issuer !== chain[i + 1].subject) return { ok: false, reason: `broken chain at ${chain[i].subject}` };
}
const last = chain[chain.length - 1];
if (!roots.includes(last.issuer) && !roots.includes(last.subject)) return { ok: false, reason: "untrusted root" };
return { ok: true };
}