#!/usr/bin/env node 'use strict'; /** * Generates a new BridgeSwarm extension ID pair and updates: * - extension/manifest.json (Chrome key + gecko id) * - extension/manifest_firefox.json (gecko id only; no key) * - com.bridgeswarm.json (allowed_origins / allowed_extensions) * * Also prints the IDs so installers/docs can be synced. * Do NOT reuse holesail-browser's Chrome key/ID — they must stay unique. */ const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); const repoRoot = path.join(__dirname, '..'); const manifestPath = path.join(repoRoot, 'extension', 'manifest.json'); const manifestFirefoxPath = path.join(repoRoot, 'extension', 'manifest_firefox.json'); const nativeManifestPath = path.join(repoRoot, 'com.bridgeswarm.json'); const { publicKey } = crypto.generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'der' }, privateKeyEncoding: { type: 'pkcs8', format: 'der' }, }); // Chrome extension ID: first 16 bytes of SHA256(publicKey), each nibble → a–p const hash = crypto.createHash('sha256').update(publicKey).digest(); const chromeId = Array.from(hash.slice(0, 16)) .map((b) => String.fromCharCode(97 + (b >> 4)) + String.fromCharCode(97 + (b & 0x0f))) .join(''); const firefoxId = 'bridgeswarm-' + crypto.randomBytes(8).toString('hex') + '@example.org'; const keyBase64 = publicKey.toString('base64'); const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); manifest.key = keyBase64; if (manifest.browser_specific_settings?.gecko) { manifest.browser_specific_settings.gecko.id = firefoxId; } fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n'); // Firefox manifest: same as Chrome but without the Chrome-only "key" if (fs.existsSync(manifestFirefoxPath)) { const manifestFx = JSON.parse(fs.readFileSync(manifestFirefoxPath, 'utf8')); if (manifestFx.browser_specific_settings?.gecko) { manifestFx.browser_specific_settings.gecko.id = firefoxId; } delete manifestFx.key; fs.writeFileSync(manifestFirefoxPath, JSON.stringify(manifestFx, null, 2) + '\n'); } else { const fx = { ...manifest }; delete fx.key; fs.writeFileSync(manifestFirefoxPath, JSON.stringify(fx, null, 2) + '\n'); } const nativeManifest = JSON.parse(fs.readFileSync(nativeManifestPath, 'utf8')); nativeManifest.allowed_origins = ['chrome-extension://' + chromeId + '/']; nativeManifest.allowed_extensions = [firefoxId]; fs.writeFileSync(nativeManifestPath, JSON.stringify(nativeManifest, null, 2) + '\n'); console.log('Generated extension ID:', chromeId, '(' + firefoxId + ')'); console.log('CHROME_EXT_ID=' + chromeId); console.log('FIREFOX_EXT_ID=' + firefoxId);