使用 node.js 验证带有 CA 证书的 X509 证书

Using node.js to verify a X509 certificate with CA cert

我正在寻找一种 node.js 方法来验证 X509 格式的客户端证书以及给我的 CA 证书(none 其中 created/managed 是我提供的,我的软件只需要验证发送给它的内容。

我为这项工作找到了几个模块,但是我对每个模块都有问题:

现在我觉得很愚蠢,因为我没能用上述任何模块完成这个简单的任务。有人能给我指出一个简单的解决方案,让我可以使用给定的 CA 证书验证 X509 证书的 signature/validity 吗? :s

[编辑] 基本上我需要 Node.js 中的 openssl verify -verbose -CAfile ca-crt.pem client1-crt.pem 但是 没有 对 openssl 命令的依赖行工具和 without 暂时将证书保存到磁盘。

[edit2] 是否可以只使用 https://nodejs.org/api/crypto.html#crypto_verify_verify_object_signature_signatureformat

我终于用 node-forge 做到了。这是一个工作代码示例:

let pki = require('node-forge').pki;
let fs = require('fs');

let caCert;
let caStore;

try {
    caCert = fs.readFileSync('path/to/ca-cert.pem').toString();
    caStore = pki.createCaStore([ caCert ]);
} catch (e) {
    log.error('Failed to load CA certificate (' + e + ')');
    return....;
}

try {
    pki.verifyCertificateChain(caStore, [ cert ]);
} catch (e) {
    return handleResponse(new Error('Failed to verify certificate (' + e.message || e + ')'));
}

两个证书都应以 base64 编码的 PEM format/js 字符串形式提供。

verifyCertificateChain 检查证书有效性 (notBefore/notAfter) 并验证给定的 CA 链。

我不是 100% 确定这是否是最好的方法,或者这个库是否做得很好,因为他们的 verifyCertificateChain 源代码充满了 #TODO,所以也许这还没有准备好生产? 但至少我有一个可行的解决方案。创建一个包装 libssl c 调用的节点模块可能会更好,但这只是完成这个小任务的大量工作。

这对我有用:

const fs = require('fs'), pki = require('node-forge').pki
var ca = pki.certificateFromPem(fs.readFileSync('ca.pem', 'ascii'))
var client = pki.certificateFromPem(fs.readFileSync('client.pem', 'ascii'))
try {
    if (!ca.verify(client)) throw 'verify failed'
} catch (err) {
    console.log(err)
}

try/catch 是必需的,因为 .verify 在我的例子中抛出了一个错误(而不是返回 false)。

如果您想直接检查使用来自 http 请求的客户端证书,您也可以这样做:

// retrieve certificates from the request ( in der format )
clientCert = req.connection.getPeerCertificate(true).raw.toString('base64'))

将der证书转换为pem并对照castore进行验证的方法。

  const caCert = fs....
  const ca = pki.certificateFromPem(caCert)
  const caStore = pki.createCaStore([ ca ])

  const verify = (clientCert, next) => {
    try {
      const derKey = forge.util.decode64(clientCert)
      const asnObj = forge.asn1.fromDer(derKey)
      const asn1Cert = pki.certificateFromAsn1(asnObj)
      const pemCert = pki.certificateToPem(asn1Cert)
      const client = pki.certificateFromPem(pemCert)
      return pki.verifyCertificateChain(caStore, [ client ], cb)
    } catch (err) {
      next(new Error(err))
    }
  }

我没有找到更好的方法来验证来自 request 的客户端 "der" 证书。

fas3r