This commit is contained in:
cheney
2026-06-30 23:00:35 +08:00
commit 80e72745f6
10 changed files with 694 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
const fs = require('fs');
const path = require('path');
const forge = require('node-forge');
const rootDir = path.resolve(__dirname, '..');
const rawConfigText = fs.readFileSync(path.join(rootDir, 'config.json'), 'utf8');
const configText = rawConfigText.charCodeAt(0) === 0xfeff ? rawConfigText.slice(1) : rawConfigText;
const config = JSON.parse(configText);
const certDir = path.resolve(rootDir, config.certDir || 'certs');
const keyPath = path.join(certDir, 'rootCA.key.pem');
const certPath = path.join(certDir, 'rootCA.cert.pem');
const certDerPath = path.join(certDir, 'rootCA.cert.cer');
fs.mkdirSync(certDir, { recursive: true });
if (fs.existsSync(keyPath) || fs.existsSync(certPath) || fs.existsSync(certDerPath)) {
console.error('Root CA already exists. Delete certs/rootCA.* first if you intentionally want to regenerate it.');
process.exit(1);
}
console.log('Generating 2048-bit RSA root CA...');
const keys = forge.pki.rsa.generateKeyPair(2048);
const cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16)).replace(/^00/, '01');
cert.validity.notBefore = new Date(Date.now() - 60 * 1000);
cert.validity.notAfter = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000);
cert.setSubject([
{ name: 'commonName', value: 'Local Node MITM Proxy Root CA' },
{ name: 'organizationName', value: 'Local Development' },
{ shortName: 'OU', value: 'Debug Proxy' },
]);
cert.setIssuer(cert.subject.attributes);
cert.setExtensions([
{ name: 'basicConstraints', cA: true, critical: true },
{ name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },
{ name: 'subjectKeyIdentifier' },
]);
cert.sign(keys.privateKey, forge.md.sha256.create());
const keyPem = forge.pki.privateKeyToPem(keys.privateKey);
const certPem = forge.pki.certificateToPem(cert);
const certDer = Buffer.from(forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes(), 'binary');
fs.writeFileSync(keyPath, keyPem, 'utf8');
fs.writeFileSync(certPath, certPem, 'utf8');
fs.writeFileSync(certDerPath, certDer);
console.log(`Created private key: ${keyPath}`);
console.log(`Created PEM cert: ${certPath}`);
console.log(`Created DER cert: ${certDerPath}`);
console.log('Keep rootCA.key.pem private. Anyone with it can mint trusted certificates on this machine.');
+9
View File
@@ -0,0 +1,9 @@
param()
$ErrorActionPreference = 'Stop'
$certPath = Join-Path $PSScriptRoot '..\certs\rootCA.cert.cer'
$resolved = Resolve-Path $certPath
Write-Host "Installing root CA into CurrentUser\Root: $resolved"
Import-Certificate -FilePath $resolved -CertStoreLocation Cert:\CurrentUser\Root | Out-Null
Write-Host 'Installed. Restart browsers/apps that cache trust settings.'
+36
View File
@@ -0,0 +1,36 @@
param(
[switch]$Enable,
[switch]$Disable,
[string]$ProxyServer = '127.0.0.1:8888',
[string]$Override = '<local>'
)
$ErrorActionPreference = 'Stop'
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings'
if ($Enable -eq $Disable) {
throw 'Pass exactly one of -Enable or -Disable.'
}
if ($Enable) {
Set-ItemProperty -Path $key -Name ProxyEnable -Type DWord -Value 1
Set-ItemProperty -Path $key -Name ProxyServer -Type String -Value $ProxyServer
Set-ItemProperty -Path $key -Name ProxyOverride -Type String -Value $Override
Write-Host "Enabled Windows proxy: $ProxyServer"
} else {
Set-ItemProperty -Path $key -Name ProxyEnable -Type DWord -Value 0
Write-Host 'Disabled Windows proxy.'
}
$source = @"
using System;
using System.Runtime.InteropServices;
public static class WinInetNative {
[DllImport("wininet.dll", SetLastError = true)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
}
"@
Add-Type -TypeDefinition $source -ErrorAction SilentlyContinue | Out-Null
[WinInetNative]::InternetSetOption([IntPtr]::Zero, 39, [IntPtr]::Zero, 0) | Out-Null
[WinInetNative]::InternetSetOption([IntPtr]::Zero, 37, [IntPtr]::Zero, 0) | Out-Null
+20
View File
@@ -0,0 +1,20 @@
param()
$ErrorActionPreference = 'Stop'
$subject = 'CN=Local Node MITM Proxy Root CA'
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store('Root', 'CurrentUser')
$store.Open('ReadWrite')
try {
$matches = @($store.Certificates | Where-Object { $_.Subject -eq $subject })
if ($matches.Count -eq 0) {
Write-Host "No matching certificate found: $subject"
exit 0
}
foreach ($cert in $matches) {
Write-Host "Removing $($cert.Subject) thumbprint=$($cert.Thumbprint)"
$store.Remove($cert)
}
Write-Host 'Removed matching root CA certificate(s).'
} finally {
$store.Close()
}