65 lines
2.7 KiB
JavaScript
Executable File
65 lines
2.7 KiB
JavaScript
Executable File
#!/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);
|