#!/usr/bin/env node // 生成 minisign 密钥对 (ota-package/hotswap.{key,pub}) // 首次跑一遍: node scripts/ota-genkey.mjs // - hotswap.key: 私钥, 不要提交, 部署时由 CI 注入 (环境变量 / secret) // - hotswap.pub: 公钥, 写到 src-tauri/tauri.conf.json 的 plugins.hotswap.pubkey // // 依赖: minisign (https://jedisct1.github.io/minisign/) // - Windows: scoop install minisign 或 choco install minisign (或下载官方 win64 二进制) // - macOS: brew install minisign // - Linux: apt install minisign import fs from 'node:fs' import path from 'node:path' import { spawnSync } from 'node:child_process' import { fileURLToPath } from 'node:url' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const ROOT = path.resolve(__dirname, '..') const OUT_DIR = path.join(ROOT, 'ota-package') fs.mkdirSync(OUT_DIR, { recursive: true }) const KEY = path.join(OUT_DIR, 'hotswap.key') const PUB = path.join(OUT_DIR, 'hotswap.pub') if (fs.existsSync(KEY) || fs.existsSync(PUB)) { console.error('[ota-genkey] 已存在密钥, 如需重新生成请先删除 ota-package/hotswap.{key,pub}') console.error(' 注意: 重新生成密钥会导致旧 bundle 无法被客户端验证, 慎用!') process.exit(1) } // 检查 minisign 是否存在 const which = spawnSync('minisign', ['-v'], { stdio: 'pipe' }) if (which.status !== 0 && which.error) { console.error('[ota-genkey] 未找到 minisign 命令, 请先安装:') console.error(' Windows: scoop install minisign') console.error(' macOS: brew install minisign') console.error(' Linux: apt install minisign') process.exit(1) } // -G: 生成 -W: 无密码 -p: 公钥输出 -s: 私钥输出 const r = spawnSync('minisign', ['-G', '-W', '-p', PUB, '-s', KEY], { stdio: 'inherit' }) if (r.status !== 0) { console.error('[ota-genkey] minisign 生成失败') process.exit(1) } console.log('\n=== 密钥生成完成 ===') console.log('私钥: ' + KEY + ' (不要提交到 git!)') console.log('公钥: ' + PUB) const pubText = fs.readFileSync(PUB, 'utf8') const lines = pubText.split(/\r?\n/) const pubB64 = lines.find((l) => l.startsWith('RWR') || l.startsWith('RWT') || l.startsWith('RWQ')) console.log('\n请把下面这一行 pubkey 写到 src-tauri/tauri.conf.json -> plugins.hotswap.pubkey:') console.log(' ' + (pubB64 || '').trim()) // 自动写 .gitignore 提醒 const gitignore = path.join(ROOT, '.gitignore') if (fs.existsSync(gitignore)) { let txt = fs.readFileSync(gitignore, 'utf8') if (!txt.includes('ota-package/hotswap.key')) { if (!txt.endsWith('\n')) txt += '\n' txt += '\n# OTA 升级私钥, 不要提交\nota-package/hotswap.key\n' fs.writeFileSync(gitignore, txt) console.log('\n[ota-genkey] 已把 ota-package/hotswap.key 加入 .gitignore') } }