You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firefox不认可自制自签名CA证书的解决方法咨询

解决Firefox不认可自制CA证书的问题

一、CA证书生成代码的核心错误

你的CA证书生成逻辑存在两处关键问题:

  1. 先设置了一组Subject属性,随后用新的attrs变量覆盖了Subject和Issuer,导致CA证书标识混乱;根CA必须是自签名,Issuer需与Subject完全一致。
  2. 错误地将CA公钥保存为证书文件,实际应保存CA证书本身,这可能是你导入错误证书的直接原因。

修正后的CA证书生成代码:

// 创建CA密钥对
const caKeys = forge.pki.rsa.generateKeyPair(4096);

// 创建CA证书
const cert = forge.pki.createCertificate();
cert.publicKey = caKeys.publicKey;
cert.signatureAlgorithm = forge.pki.oids.sha256WithRSAEncryption;
// 序列号使用十六进制格式,提升兼容性
cert.serialNumber = '01';

// 根CA的Subject与Issuer必须一致
const caSubject = [
    { name: "countryName", value: "SK" },
    { name: "commonName", value: "Primantro-Canny-Root-CA" },
];
cert.setSubject(caSubject);
cert.setIssuer(caSubject);

// 设置证书有效期
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);

// 配置CA证书扩展(核心是标记为CA并限制权限)
cert.setExtensions([
    { 
        name: "basicConstraints", 
        cA: true,
        pathLenConstraint: 0 // 禁止下级CA,符合根CA规范
    },
    {
        name: "keyUsage",
        keyCertSign: true, // CA必须具备签名证书的权限
        digitalSignature: false,
        nonRepudiation: false,
        keyEncipherment: false,
        dataEncipherment: false,
    },
    {
        name: "extKeyUsage",
        serverAuth: true,
        clientAuth: true,
    },
    {
        name: "subjectKeyIdentifier",
        hash: forge.md.sha256.create() // 自动生成密钥标识符
    },
]);

// 用CA私钥自签名证书
cert.sign(caKeys.privateKey, forge.md.sha256.create());

// 保存CA私钥
const caPrivateKeyPem = forge.pki.privateKeyToPem(caKeys.privateKey);
fs.writeFileSync(keyPath, caPrivateKeyPem);

// 保存CA证书(注意:这里是证书本身,不是公钥)
const caCertPem = forge.pki.certificateToPem(cert);
fs.writeFileSync(crtPath, caCertPem);

return { crt: caCertPem, key: caPrivateKeyPem };

二、服务器证书生成代码的优化

确保服务器证书的Issuer严格匹配CA证书Subject,同时扩展配置符合HTTPS服务器要求:

const ca = await localhostCA();

const caPrivateKeyPem = ca.key;
const caCertPem = ca.crt;

const caPrivateKey = forge.pki.privateKeyFromPem(caPrivateKeyPem);
const caCert = forge.pki.certificateFromPem(caCertPem);

// 创建服务器密钥对
const serverKeys = forge.pki.rsa.generateKeyPair(2048);
const serverCert = forge.pki.createCertificate();
serverCert.signatureAlgorithm = forge.pki.oids.sha256WithRSAEncryption;

// 设置服务器证书Subject
serverCert.publicKey = serverKeys.publicKey;
serverCert.setSubject([
    { name: "countryName", value: "SK" },
    { name: "stateOrProvinceName", value: "YourState" },
    { name: "localityName", value: "YourCity" },
    { name: "organizationName", value: "Example-Certificates" },
    { name: "commonName", value: "localhost" },
]);

// 绑定根CA作为颁发者
serverCert.setIssuer(caCert.subject.attributes);

// 设置服务器证书有效期
serverCert.validity.notBefore = new Date();
serverCert.validity.notAfter = new Date();
serverCert.validity.notAfter.setFullYear(serverCert.validity.notBefore.getFullYear() + 1);

// 配置服务器证书扩展
serverCert.setExtensions([
    {
        name: "subjectAltName",
        altNames: [
            { type: 2, value: "localhost" },
            { type: 2, value: "fake1.local" },
            { type: 2, value: "fake2.local" },
        ],
    },
    {
        name: "keyUsage",
        keyEncipherment: true,
        digitalSignature: true,
        keyAgreement: true,
        nonRepudiation: false, // 服务器证书无需此权限
    },
    {
        name: "extKeyUsage",
        serverAuth: true, // 明确指定用于服务器认证
    },
    {
        name: "authorityKeyIdentifier",
        authorityCertIssuer: caCert.subject.attributes,
        authorityCertSerialNumber: caCert.serialNumber
    },
]);

// 用CA私钥签名服务器证书
serverCert.sign(caPrivateKey, forge.md.sha256.create());

// 保存服务器私钥与证书
const serverPrivateKeyPem = forge.pki.privateKeyToPem(serverKeys.privateKey);
const serverCertPem = forge.pki.certificateToPem(serverCert);

return {
    cert: serverCertPem,
    key: serverPrivateKeyPem,
    ca: caCertPem,
};

三、Firefox正确导入CA证书的步骤

即使证书生成正确,Firefox导入时必须设置信任权限,否则会触发SEC_ERROR_UNKNOWN_ISSUER:

  • 打开Firefox,输入about:preferences#privacy进入隐私设置
  • 滚动到「证书」区域,点击「查看证书」
  • 切换到「证书颁发机构」标签,点击「导入」选择你的CA证书文件
  • 在信任窗口中务必勾选「信任该CA来识别网站」,其他选项按需勾选
  • 点击「确定」完成导入,重启Firefox后测试

四、额外排查点

  • 确认Node.js HTTPS服务器配置的是正确的证书:根CA场景下直接使用服务器证书即可
  • 检查证书有效期:确保当前时间在notBefore和notAfter范围内
  • 清除Firefox缓存:输入about:cache清除所有缓存,避免旧证书残留

内容的提问来源于stack exchange,提问作者Márius Rak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 15:54:56