191 lines
5.4 KiB
JavaScript
191 lines
5.4 KiB
JavaScript
// 批量生成证书测试脚本
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const forge = require('node-forge');
|
||
|
||
// 生成随机的序列号
|
||
const generateSerialNumber = () => {
|
||
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString();
|
||
};
|
||
|
||
// 生成根证书
|
||
const generateRootCert = () => {
|
||
try {
|
||
// 生成密钥对
|
||
const keys = forge.pki.rsa.generateKeyPair(2048);
|
||
|
||
// 创建证书
|
||
const cert = forge.pki.createCertificate();
|
||
|
||
// 设置版本
|
||
cert.version = 3;
|
||
|
||
// 设置序列号
|
||
cert.serialNumber = generateSerialNumber();
|
||
|
||
// 设置主题和颁发者(根证书自己颁发自己)
|
||
const attrs = [
|
||
{ name: 'commonName', value: 'Root CA' },
|
||
{ name: 'countryName', value: 'CN' },
|
||
{ shortName: 'ST', value: 'Beijing' },
|
||
{ name: 'localityName', value: 'Beijing' },
|
||
{ name: 'organizationName', value: 'Security Kit' },
|
||
{ shortName: 'OU', value: 'Root Certificate Authority' }
|
||
];
|
||
|
||
cert.setSubject(attrs);
|
||
cert.setIssuer(attrs);
|
||
|
||
// 设置公钥
|
||
cert.publicKey = keys.publicKey;
|
||
|
||
// 设置有效期
|
||
const notBefore = new Date();
|
||
const notAfter = new Date();
|
||
notAfter.setFullYear(notBefore.getFullYear() + 10); // 10年有效期
|
||
cert.validity.notBefore = notBefore;
|
||
cert.validity.notAfter = notAfter;
|
||
|
||
// 添加扩展
|
||
cert.setExtensions([
|
||
{
|
||
name: 'basicConstraints',
|
||
cA: true
|
||
},
|
||
{
|
||
name: 'keyUsage',
|
||
digitalSignature: true,
|
||
keyCertSign: true,
|
||
cRLSign: true
|
||
}
|
||
]);
|
||
|
||
// 使用私钥自签名
|
||
cert.sign(keys.privateKey, forge.md.sha256.create());
|
||
|
||
// 转换为PEM格式
|
||
const certPem = forge.pki.certificateToPem(cert);
|
||
|
||
return { certPem, privateKey: keys.privateKey };
|
||
} catch (error) {
|
||
throw new Error('Failed to generate root certificate: ' + (error instanceof Error ? error.message : error));
|
||
}
|
||
};
|
||
|
||
// 基于根证书生成应用证书
|
||
const generateAppCert = (commonName, rootCert, rootPrivateKey) => {
|
||
try {
|
||
// 解析根证书
|
||
const parsedRootCert = forge.pki.certificateFromPem(rootCert);
|
||
|
||
// 生成应用证书的密钥对
|
||
const appKeys = forge.pki.rsa.generateKeyPair(2048);
|
||
|
||
// 创建应用证书
|
||
const appCert = forge.pki.createCertificate();
|
||
|
||
// 设置版本
|
||
appCert.version = 3;
|
||
|
||
// 设置序列号
|
||
appCert.serialNumber = generateSerialNumber();
|
||
|
||
// 设置主题
|
||
const appAttrs = [
|
||
{ name: 'commonName', value: commonName },
|
||
{ name: 'countryName', value: 'CN' },
|
||
{ shortName: 'ST', value: 'Beijing' },
|
||
{ name: 'localityName', value: 'Beijing' },
|
||
{ name: 'organizationName', value: 'Security Kit' },
|
||
{ shortName: 'OU', value: 'Application' }
|
||
];
|
||
|
||
appCert.setSubject(appAttrs);
|
||
|
||
// 设置颁发者(根证书)
|
||
appCert.setIssuer(parsedRootCert.subject.attributes);
|
||
|
||
// 设置公钥
|
||
appCert.publicKey = appKeys.publicKey;
|
||
|
||
// 设置有效期
|
||
const notBefore = new Date();
|
||
const notAfter = new Date();
|
||
notAfter.setFullYear(notBefore.getFullYear() + 5); // 5年有效期
|
||
appCert.validity.notBefore = notBefore;
|
||
appCert.validity.notAfter = notAfter;
|
||
|
||
// 添加扩展
|
||
appCert.setExtensions([
|
||
{
|
||
name: 'basicConstraints',
|
||
cA: false
|
||
},
|
||
{
|
||
name: 'keyUsage',
|
||
digitalSignature: true,
|
||
keyEncipherment: true
|
||
}
|
||
]);
|
||
|
||
// 使用根证书的私钥签名
|
||
appCert.sign(rootPrivateKey, forge.md.sha256.create());
|
||
|
||
// 转换为PEM格式
|
||
const appCertPem = forge.pki.certificateToPem(appCert);
|
||
|
||
return appCertPem;
|
||
} catch (error) {
|
||
throw new Error('Failed to generate application certificate: ' + (error instanceof Error ? error.message : error));
|
||
}
|
||
};
|
||
|
||
// 主函数
|
||
async function main() {
|
||
console.log('开始生成证书...');
|
||
|
||
// 创建输出目录
|
||
const outputDir = path.join(__dirname, 'certs');
|
||
if (!fs.existsSync(outputDir)) {
|
||
fs.mkdirSync(outputDir, { recursive: true });
|
||
}
|
||
|
||
try {
|
||
// 生成根证书
|
||
console.log('1. 生成根证书...');
|
||
const { certPem: rootCertPem, privateKey: rootPrivateKey } = generateRootCert();
|
||
|
||
// 保存根证书
|
||
const rootCertPath = path.join(outputDir, 'root-cert.pem');
|
||
fs.writeFileSync(rootCertPath, rootCertPem);
|
||
console.log(`根证书已保存到: ${rootCertPath}`);
|
||
|
||
// 生成1000个用户证书
|
||
console.log('2. 生成1000个用户证书...');
|
||
for (let i = 1; i <= 1000; i++) {
|
||
const commonName = `user-${i}.example.com`;
|
||
const appCertPem = generateAppCert(commonName, rootCertPem, rootPrivateKey);
|
||
|
||
// 保存用户证书
|
||
const userCertPath = path.join(outputDir, `user-${i}-cert.pem`);
|
||
fs.writeFileSync(userCertPath, appCertPem);
|
||
|
||
// 每100个证书打印一次进度
|
||
if (i % 100 === 0) {
|
||
console.log(`已生成 ${i} 个用户证书`);
|
||
}
|
||
}
|
||
|
||
console.log('\n证书生成完成!');
|
||
console.log(`根证书路径: ${path.join(outputDir, 'root-cert.pem')}`);
|
||
console.log(`用户证书路径: ${outputDir}/user-*-cert.pem`);
|
||
console.log(`共生成 1 个根证书和 1000 个用户证书`);
|
||
|
||
} catch (error) {
|
||
console.error('生成证书失败:', error.message);
|
||
}
|
||
}
|
||
|
||
// 运行主函数
|
||
main();
|