使用 node.js 验证带有 CA 证书的 X509 证书
Using node.js to verify a X509 certificate with CA cert
我正在寻找一种 node.js 方法来验证 X509 格式的客户端证书以及给我的 CA 证书(none 其中 created/managed 是我提供的,我的软件只需要验证发送给它的内容。
我为这项工作找到了几个模块,但是我对每个模块都有问题:
- X509 可以使用
x509.verify(cert, CABundlePath, cb)
来完成,但是它需要从 FS 读取证书,而我已经将它们保存在内存中。这很麻烦,因为它会在到达我的应用程序的每个 Web 请求中完成。
- 看起来 PKI.js 可以做到,但是他们的示例对我不起作用,但抱怨丢失文件,所以我什至无法尝试。
- 我试过 node-forge,但我不确定我是否正确使用它(他们没有任何 API 文档)它从 [=13] 抛出
forge.pki.BadCertificate
错误=].
- 尝试 pem 时,使用简单的
pem.verifySigningChain(cer, [ ca ], cb)
会引发一些错误,抱怨从 /var/...
加载文件。即使它可行,我也会避免使用此库,因为它依赖于 openssl 命令行工具,我想避免
现在我觉得很愚蠢,因为我没能用上述任何模块完成这个简单的任务。有人能给我指出一个简单的解决方案,让我可以使用给定的 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
我正在寻找一种 node.js 方法来验证 X509 格式的客户端证书以及给我的 CA 证书(none 其中 created/managed 是我提供的,我的软件只需要验证发送给它的内容。
我为这项工作找到了几个模块,但是我对每个模块都有问题:
- X509 可以使用
x509.verify(cert, CABundlePath, cb)
来完成,但是它需要从 FS 读取证书,而我已经将它们保存在内存中。这很麻烦,因为它会在到达我的应用程序的每个 Web 请求中完成。 - 看起来 PKI.js 可以做到,但是他们的示例对我不起作用,但抱怨丢失文件,所以我什至无法尝试。
- 我试过 node-forge,但我不确定我是否正确使用它(他们没有任何 API 文档)它从 [=13] 抛出
forge.pki.BadCertificate
错误=]. - 尝试 pem 时,使用简单的
pem.verifySigningChain(cer, [ ca ], cb)
会引发一些错误,抱怨从/var/...
加载文件。即使它可行,我也会避免使用此库,因为它依赖于 openssl 命令行工具,我想避免
现在我觉得很愚蠢,因为我没能用上述任何模块完成这个简单的任务。有人能给我指出一个简单的解决方案,让我可以使用给定的 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