Add an integrity footer to chat.html, zebra-audio.html, and how-it-works.html showing the build date (2026-05-28) and the page's own MD5 + SHA-256. A file can't hold its own hash, so web/stamp.js (make stamp) computes the hashes with the two hash fields zeroed, then writes the real values back — self-consistent and idempotent. To verify a served page: blank the two fields and re-hash; confirmed it reproduces the stamped value with plain sha256sum.
35 lines
1.7 KiB
JavaScript
35 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/* Stamp each given HTML page with today's date + its own MD5 and SHA-256.
|
|
*
|
|
* A file can't contain its own hash directly (writing the hash changes the
|
|
* hash). So the hashes are computed over the page with the two hash fields
|
|
* ZEROED, then the real values are written back (same length, so the file the
|
|
* verifier hashes-after-zeroing is exactly what we hashed). Self-consistent and
|
|
* idempotent.
|
|
*
|
|
* Verify a served page: sed the md5 field to 32 zeros and the sha256 field to
|
|
* 64 zeros, then `md5sum` / `sha256sum` — must match the printed values.
|
|
*
|
|
* node web/stamp.js web/chat.html web/zebra-audio.html web/how-it-works.html
|
|
*/
|
|
const { readFileSync, writeFileSync } = require('fs');
|
|
const { createHash } = require('crypto');
|
|
|
|
const date = process.env.STAMP_DATE || new Date().toISOString().slice(0, 10);
|
|
const Z32 = '0'.repeat(32), Z64 = '0'.repeat(64);
|
|
let bad = 0;
|
|
|
|
for (const f of process.argv.slice(2)) {
|
|
let s = readFileSync(f, 'utf8');
|
|
if (!/class="stamp-md5"/.test(s)) { console.error(`! ${f}: no integrity footer, skipped`); bad++; continue; }
|
|
s = s.replace(/(<span class="stamp-date">)[^<]*(<\/span>)/, `$1${date}$2`);
|
|
s = s.replace(/(<span class="stamp-md5">)[0-9a-fA-F]*(<\/span>)/, `$1${Z32}$2`)
|
|
.replace(/(<span class="stamp-sha">)[0-9a-fA-F]*(<\/span>)/, `$1${Z64}$2`);
|
|
const md5 = createHash('md5').update(s).digest('hex');
|
|
const sha = createHash('sha256').update(s).digest('hex');
|
|
s = s.replace(`<span class="stamp-md5">${Z32}</span>`, `<span class="stamp-md5">${md5}</span>`)
|
|
.replace(`<span class="stamp-sha">${Z64}</span>`, `<span class="stamp-sha">${sha}</span>`);
|
|
writeFileSync(f, s);
|
|
console.log(`${f}\n date ${date}\n md5 ${md5}\n sha256 ${sha}`);
|
|
}
|
|
process.exit(bad ? 1 : 0);
|