import assert from 'node:assert/strict'; import fs from 'node:fs'; import tls from 'node:tls'; import { X509Certificate } from 'node:crypto'; import { pathToFileURL } from 'node:url'; const fingerprint = value => { assert.equal(typeof value, 'string', 'Fingerprint is required'); const normalized = value.replaceAll(':', '').toLowerCase(); assert(/^[a-f0-9]{64}$/.test(normalized), 'Expected SHA-256 fingerprint'); return normalized; }; export function compareRenewal(before, after) { for (const sample of [before, after]) { assert(/^mmt253-[a-f0-9]{8}\.pngs\.top$/.test(sample.fqdn), 'Only the prepared exact test domain is permitted'); assert.equal(sample.remoteAddress, '104.165.244.7'); assert.equal(sample.authorized, true); assert.equal(sample.hostnameMatched, true); assert.equal(sample.nativePrivateKey, true); assert.equal(sample.nativeName, sample.certName); assert.equal(sample.certName, sample.fqdn.replace('.pngs.top', '')); assert.equal(fingerprint(sample.nativeFingerprint256), fingerprint(sample.fingerprint256), 'Native leaf must match served TLS'); assert(Number.isFinite(Date.parse(sample.validUntil)), 'Expiry is required'); assert(Number.isFinite(Date.parse(sample.sampledAt)), 'Sample time is required'); assert(Date.parse(sample.validUntil) > Date.parse(sample.sampledAt), 'Certificate is expired'); } assert.equal(after.fqdn, before.fqdn); assert.equal(after.certName, before.certName); assert.notEqual(fingerprint(after.fingerprint256), fingerprint(before.fingerprint256), 'Old certificate is still being served'); assert(Date.parse(after.sampledAt) >= Date.parse(before.sampledAt)); assert(Date.parse(after.validUntil) > Date.parse(after.sampledAt), 'New certificate is expired'); // A second issuance on the same day need not extend expiry by a full day. return { fingerprintChanged: true, nativeAndTlsMatch: true, trustedHostnameMatch: true }; } async function sample(fixture) { assert(/^mmt253-[a-f0-9]{8}\.pngs\.top$/.test(fixture.fqdn)); assert.equal(fixture.certName, fixture.fqdn.replace('.pngs.top', '')); assert.equal(fixture.nativePrivateKey, true); fingerprint(fixture.nativeFingerprint256); return await new Promise((resolve, reject) => { const socket = tls.connect({ host: '104.165.244.7', port: 443, servername: fixture.fqdn, rejectUnauthorized: true }); socket.setTimeout(15000, () => socket.destroy(new Error('TLS acceptance timeout'))); socket.once('error', reject); socket.once('secureConnect', () => { try { assert.equal(socket.authorized, true); const cert = new X509Certificate(socket.getPeerCertificate().raw); assert(cert.checkHost(fixture.fqdn), 'Hostname mismatch'); assert(Date.parse(cert.validTo) > Date.now(), 'Certificate is expired'); assert.equal(fingerprint(cert.fingerprint256), fingerprint(fixture.nativeFingerprint256), 'Native leaf does not match TLS'); resolve({ sampledAt: new Date().toISOString(), fqdn: fixture.fqdn, certName: fixture.certName, remoteAddress: socket.remoteAddress, authorized: socket.authorized, hostnameMatched: true, protocol: socket.getProtocol(), fingerprint256: cert.fingerprint256, validFrom: cert.validFrom, validUntil: cert.validTo, nativeName: fixture.certName, nativePrivateKey: true, nativeFingerprint256: fixture.nativeFingerprint256 }); } catch (error) { reject(error); } finally { socket.end(); } }); }); } if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { const [mode, input, output] = process.argv.slice(2); assert(input && output && ['sample', 'compare'].includes(mode), 'Usage: sample native-summary.json output.json | compare samples.json output.json'); assert(!fs.existsSync(output), 'Never overwrite acceptance evidence'); const data = JSON.parse(fs.readFileSync(input, 'utf8')); const result = mode === 'sample' ? await sample(data) : compareRenewal(data.before, data.after); fs.writeFileSync(output, JSON.stringify(result, null, 2) + '\n', { flag: 'wx' }); console.log(mode === 'sample' ? 'Trusted TLS/native fingerprint sample saved' : 'Renewal fingerprint comparison passed'); }