Some checks failed
Desktop Release / Bootstrap updater signing key (push) Has been cancelled
Desktop Release / Windows x64 NSIS (push) Has been cancelled
Desktop Release / Linux x64 DEB + AppImage (push) Has been cancelled
Desktop Release / Publish public desktop release (push) Has been cancelled
41 lines
2.4 KiB
JavaScript
41 lines
2.4 KiB
JavaScript
import { mkdtempSync, writeFileSync, readFileSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join, resolve } from 'node:path';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { createHash, createPublicKey, verify } from 'node:crypto';
|
|
|
|
const temp = mkdtempSync(join(tmpdir(), 'fieldlens-signing-'));
|
|
try {
|
|
if (!process.env.TAURI_SIGNING_PRIVATE_KEY) throw new Error('missing key');
|
|
const probe = join(temp, 'probe.txt');
|
|
writeFileSync(probe, 'FieldLens updater signing preflight\n', { mode: 0o600 });
|
|
const result = spawnSync(process.execPath, [resolve('node_modules/@tauri-apps/cli/tauri.js'), 'signer', 'sign', probe], {
|
|
env: process.env, stdio: 'pipe', timeout: 30000,
|
|
});
|
|
if (result.status !== 0) throw new Error('signing failed');
|
|
const config = JSON.parse(readFileSync('src-tauri/tauri.conf.json', 'utf8'));
|
|
const publicLines = Buffer.from(config.plugins.updater.pubkey, 'base64').toString().trim().split(/\r?\n/);
|
|
const signatureLines = Buffer.from(readFileSync(probe + '.sig', 'utf8').trim(), 'base64').toString().trim().split(/\r?\n/);
|
|
const pub = Buffer.from(publicLines[1], 'base64');
|
|
const sig = Buffer.from(signatureLines[1], 'base64');
|
|
if (pub.length !== 42 || sig.length !== 74 || !pub.subarray(2, 10).equals(sig.subarray(2, 10))) throw new Error('key mismatch');
|
|
const key = createPublicKey({
|
|
key: Buffer.concat([Buffer.from('302a300506032b6570032100', 'hex'), pub.subarray(10)]),
|
|
format: 'der', type: 'spki',
|
|
});
|
|
const algorithm = sig.subarray(0, 2).toString();
|
|
if (!['ED', 'Ed'].includes(algorithm)) throw new Error('unsupported signature');
|
|
const message = readFileSync(probe);
|
|
const signed = algorithm === 'ED' ? createHash('blake2b512').update(message).digest() : message;
|
|
if (!verify(null, signed, key, sig.subarray(10))) throw new Error('invalid signature');
|
|
if (!signatureLines[2].startsWith('trusted comment: ')) throw new Error('invalid comment');
|
|
const comment = Buffer.from(signatureLines[2].slice('trusted comment: '.length));
|
|
if (!verify(null, Buffer.concat([sig.subarray(10), comment]), key, Buffer.from(signatureLines[3], 'base64'))) throw new Error('invalid trusted comment');
|
|
console.log('Updater signing preflight passed: key, password and public key match.');
|
|
} catch {
|
|
console.error('Updater signing preflight failed: check the signing key/password and configured public key.');
|
|
process.exitCode = 1;
|
|
} finally {
|
|
rmSync(temp, { recursive: true, force: true });
|
|
}
|