78 lines
2.7 KiB
JavaScript
78 lines
2.7 KiB
JavaScript
import { readFileSync, readdirSync } from "node:fs";
|
|
import { join, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import {
|
|
WINDOWS_UPDATE_MANIFEST_NAME,
|
|
WINDOWS_UPDATE_SIGNATURE_NAME,
|
|
verifyDownloadedWindowsUpdate,
|
|
verifyWindowsUpdateMetadata,
|
|
} from "../apps/desktop/src/main/windows-update-trust.mjs";
|
|
|
|
export const verifyWindowsUpdateRelease = async (directory) => {
|
|
const manifestBytes = readFileSync(join(directory, WINDOWS_UPDATE_MANIFEST_NAME));
|
|
const signatureBytes = readFileSync(join(directory, WINDOWS_UPDATE_SIGNATURE_NAME));
|
|
const untrustedManifest = JSON.parse(manifestBytes.toString("utf8"));
|
|
const expectedNames = [
|
|
untrustedManifest.file?.name,
|
|
"latest.yml",
|
|
WINDOWS_UPDATE_MANIFEST_NAME,
|
|
WINDOWS_UPDATE_SIGNATURE_NAME,
|
|
"SHA256SUMS-windows.txt",
|
|
].sort();
|
|
const actualNames = readdirSync(directory).sort();
|
|
if (JSON.stringify(actualNames) !== JSON.stringify(expectedNames)) {
|
|
throw new Error(`Windows update audit expected exactly: ${expectedNames.join(", ")}`);
|
|
}
|
|
const manifest = verifyWindowsUpdateMetadata({
|
|
manifestBytes,
|
|
signatureBytes,
|
|
expectedVersion: untrustedManifest.version,
|
|
updateInfo: {
|
|
version: untrustedManifest.version,
|
|
files: [{
|
|
url: untrustedManifest.file?.name,
|
|
size: untrustedManifest.file?.size,
|
|
sha512: untrustedManifest.file?.sha512,
|
|
}],
|
|
},
|
|
});
|
|
await verifyDownloadedWindowsUpdate({
|
|
path: join(directory, manifest.file.name),
|
|
manifest,
|
|
});
|
|
|
|
const latestYml = readFileSync(join(directory, "latest.yml"), "utf8");
|
|
const expectedLatestYml = [
|
|
`version: ${manifest.version}`,
|
|
"files:",
|
|
` - url: ${manifest.file.name}`,
|
|
` sha512: ${manifest.file.sha512}`,
|
|
` size: ${manifest.file.size}`,
|
|
`path: ${manifest.file.name}`,
|
|
`sha512: ${manifest.file.sha512}`,
|
|
`releaseDate: '${manifest.releaseDate}'`,
|
|
"",
|
|
].join("\n");
|
|
if (latestYml !== expectedLatestYml) {
|
|
throw new Error("latest.yml does not exactly match the signed manifest");
|
|
}
|
|
const checksum = readFileSync(join(directory, "SHA256SUMS-windows.txt"), "utf8");
|
|
if (checksum !== `${manifest.file.sha256} ${manifest.file.name}\n`) {
|
|
throw new Error("SHA256SUMS-windows.txt does not match the signed manifest");
|
|
}
|
|
return manifest;
|
|
};
|
|
|
|
const run = async () => {
|
|
const [directoryValue] = process.argv.slice(2);
|
|
if (!directoryValue) {
|
|
throw new Error("Usage: node scripts/verify-windows-update-release.mjs <directory>");
|
|
}
|
|
const manifest = await verifyWindowsUpdateRelease(resolve(directoryValue));
|
|
process.stdout.write(`Verified ${manifest.file.name} with ${manifest.keyId}\n`);
|
|
};
|
|
|
|
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
await run();
|
|
}
|