我正在寻找一种节点.js方法来验证X509格式的客户端证书,并使用提供给我的CA证书(这些都不是由我创建/管理的,我的软件只需要验证发送给它的是什么)。
我为这项工作找到了几个模块,但是每个模块都遇到了问题:
- X509 能够使用
x509.verify(cert, CABundlePath, cb)
做到这一点,但是它需要从 FS 读取证书,而且我已经将它们放在内存中。这很麻烦,因为它将与到达我的应用程序的每个 Web 请求一起完成。 - 似乎 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
[编辑] 基本上我需要openssl verify -verbose -CAfile ca-crt.pem client1-crt.pem
Node.js
但不依赖于 openssl 命令行工具,也无需临时将证书保存到磁盘。
[编辑2] 是否可以只使用 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 格式/js 字符串提供。
verifyCertificateChain
检查证书的有效性(notBefore
/notAfter
)以及验证给定的CA链。
我不是 100% 确定这是否是最好的方法,或者这个库是否做得很好,因为他们的verifyCertificateChain
源代码充满了#TODO
s,所以也许这还没有准备好生产? 但至少我有一个可行的解决方案。可能最好创建一个包装libssl
c 调用的节点模块,但对于这个小任务来说,这只是很多努力。
如果您想直接检查使用来自 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
这对我有用:
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)。