使用 node.js 验证带有 CA 证书的 X509 证书
Posted
技术标签:
【中文标题】使用 node.js 验证带有 CA 证书的 X509 证书【英文标题】:Using node.js to verify a X509 certificate with CA cert 【发布时间】:2018-06-30 20:33:56 【问题描述】:我正在寻找一种 node.js 方法来验证 X509 格式的客户端证书和给我的 CA 证书(这些都不是我创建/管理的,我的软件只需要验证发送的内容给它)。
我已经为这项工作找到了几个模块,但是每个模块都有问题:
X509 可以使用x509.verify(cert, CABundlePath, cb)
来做到这一点,但是它需要从 FS 读取证书,并且我已经将它们保存在内存中。这很麻烦,因为每个到达我的应用程序的网络请求都会这样做。
似乎PKI.js 能够做到这一点,但是他们的示例对我不起作用,但抱怨缺少文件,所以我什至无法尝试。
我尝试了 node-forge,但我不确定我是否正确使用它(他们没有任何 API 文档),但它从 forge.pki.verifyCertificateChain(caStore, [ cer ], cb)
引发了 forge.pki.BadCertificate
错误。
尝试pem 时,使用简单的pem.verifySigningChain(cer, [ ca ], cb)
会引发一些错误,抱怨从/var/...
加载文件。即使它可以工作,我也会避免使用这个库,因为它依赖于 openssl 命令行工具,我想避免这种情况
现在我觉得自己很愚蠢,因为我无法使用上述任何模块完成这个简单的任务。有人能指出一个简单的解决方案,它允许我使用给定的 CA 证书验证 X509 证书的签名/有效性吗? :s
[edit] 基本上我需要Node.js
中的openssl verify -verbose -CAfile ca-crt.pem client1-crt.pem
但没有 依赖于openssl 命令行工具并且没有 em> 暂时将证书保存到磁盘。
[edit2] 可以只使用https://nodejs.org/api/crypto.html#crypto_verify_verify_object_signature_signatureformat吗?
【问题讨论】:
这是一个写得很好的问题。谢谢。 【参考方案1】:我终于设法使用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 格式/js 字符串给出。
verifyCertificateChain
检查证书有效性 (notBefore
/notAfter
) 并验证给定的 CA 链。
我不能 100% 确定这是否是最好的方法,或者这个库是否做得很好,因为它们的源代码 verifyCertificateChain
充满了 #TODO
s,所以也许这还没有准备好投入生产?
但至少我有一个可行的解决方案。可能最好创建一个包装libssl
c 调用的节点模块,但这对于这个小任务来说只是很多努力。
【讨论】:
cert
定义在哪里?
它是您要验证的证书。它由您提供。
为我工作,但我必须将 PEM 编码(字符串)证书转换为伪造证书对象:const cert = pki.certificateFromPem(certificate.data);
(certificate.data 在我的 Electron 应用程序中的 certificate-error
事件中提供.)【参考方案2】:
如果您想直接从 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
【讨论】:
【参考方案3】:这对我有用:
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)。
【讨论】:
以上是关于使用 node.js 验证带有 CA 证书的 X509 证书的主要内容,如果未能解决你的问题,请参考以下文章
在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书
Nginx 配置HTTPS 与Node.js 配置HTTPS方法
基于 Azure AD 证书的身份验证:如何在 Node JS 中指定证书路径?