Files
NetMesh/electron/bridges/boringSslDhCompat.cjs
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

84 lines
3.3 KiB
JavaScript

/**
* BoringSSL Diffie-Hellman group compatibility shim.
*
* Electron ships with BoringSSL, which no longer exposes some standard MODP
* groups through the *named* `crypto.createDiffieHellmanGroup()` API — notably
* the 1024-bit Oakley Group 2 ("modp2") that backs the SSH
* `diffie-hellman-group1-sha1` key exchange. ssh2 calls
* `createDiffieHellmanGroup('modp2')` for that kex, so on Electron it throws
* "Unknown DH group" and legacy network devices that only speak group1-sha1
* cannot be reached (issue #1035).
*
* The underlying DH math still works on BoringSSL via `createDiffieHellman()`
* with an explicit prime, so this shim wraps `createDiffieHellmanGroup` to fall
* back to the well-known prime constants when (and only when) the runtime can't
* resolve a group by name. On OpenSSL builds the original call succeeds and the
* fallback is never used, so behavior is unchanged there.
*
* IMPORTANT: ssh2 destructures `createDiffieHellmanGroup` at module load, so this
* must be installed BEFORE ssh2 (or any bridge that requires it) is loaded.
*/
const crypto = require("node:crypto");
// Standard MODP groups (RFC 2409 / RFC 3526), generator 2. These primes are
// public constants and are byte-identical to Node's built-in groups, so the
// fallback produces the exact same key exchange the named group would have.
// Only groups that a runtime might drop yet ssh2 still requests need to live
// here; modp14/16/18 remain available on BoringSSL so they are intentionally
// omitted.
const MODP_GROUP_PRIMES = {
// Oakley Group 2 — RFC 2409, 1024-bit. ssh2: diffie-hellman-group1-sha1.
modp2:
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" +
"FFFFFFFFFFFFFFFF",
};
const MODP_GENERATOR = Buffer.from([0x02]);
function createGroupFromPrime(name) {
const primeHex = MODP_GROUP_PRIMES[name];
if (!primeHex) return null;
return crypto.createDiffieHellman(Buffer.from(primeHex, "hex"), MODP_GENERATOR);
}
/**
* Wrap `target.createDiffieHellmanGroup` so missing named groups fall back to an
* explicit-prime DiffieHellman. Idempotent. Returns true if it installed the
* shim, false if it was already installed (or there was nothing to wrap).
* @param {{ createDiffieHellmanGroup?: Function }} [target] defaults to the crypto module
*/
function installBoringSslDhCompat(target = crypto) {
const original = target.createDiffieHellmanGroup;
if (typeof original !== "function" || original.__boringSslDhCompat) {
return false;
}
const wrapped = function createDiffieHellmanGroup(name) {
try {
return original(name);
} catch (err) {
const fallback = createGroupFromPrime(name);
if (!fallback) throw err;
return fallback;
}
};
wrapped.__boringSslDhCompat = true;
try {
target.createDiffieHellmanGroup = wrapped;
} catch {
// The property may be read-only on some runtimes; force it via defineProperty.
Object.defineProperty(target, "createDiffieHellmanGroup", {
value: wrapped,
configurable: true,
writable: true,
});
}
return true;
}
module.exports = { installBoringSslDhCompat, createGroupFromPrime, MODP_GROUP_PRIMES };