在 Node JS 中为 WebSocket (ws) 使用自签名 CA 证书

Using a Self-Signed CA Certificate for WebSocket (ws) in Node JS

我需要使用 Node JS 中的 ws 客户端连接到单独的 WebSocket 服务器。

我能够使用 Chrome 中的示例程序进行连接,因为我在计算机的受信任根证书颁发机构商店中安装了自签名根 CA。

我知道 Node JS 使用硬编码的根 CA 列表(愚蠢),但我希望有一些方法可以导入我自己的。

我试过了:

        export NODE_EXTRA_CA_CERTS=C:\Users\IT1\Documents\security\rootCA.pem
        // Using just ca
        var test = new WebSocket(uri, {
            ca: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.pem")
        });

        // Using cert and key
        var test = new WebSocket(uri, {
            cert: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.crt"),
            key: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.key")
        });

        // Using ca, cert and key
        var test = new WebSocket(uri, {
            ca: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.pem"),
            cert: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.crt"),
            key: fs.readFileSync("C:\Users\IT1\Documents\security\rootCA.key")
        });

无论如何,我总是收到以下错误消息:

events.js:200
      throw er; // Unhandled 'error' event
      ^

Error: unable to verify the first certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1321:34)
    at TLSSocket.emit (events.js:223:5)
    at TLSSocket._finishInit (_tls_wrap.js:794:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:608:12)
Emitted 'error' event on WebSocket instance at:
    at ClientRequest.<anonymous> (C:\Users\IT1\source\repos\WebSocketTest\WebSocketTest\node_modules\ws\lib\websocket.js:554:15)
    at ClientRequest.emit (events.js:223:5)
    at TLSSocket.socketErrorListener (_http_client.js:406:9)
    at TLSSocket.emit (events.js:223:5)
    at emitErrorNT (internal/streams/destroy.js:92:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}

此外,我无法使用 rejectUnauthorized: true。我需要它被授权,所以请不要建议作为解决方案。

请帮忙,我真的在这个问题上摸不着头脑。

经过将近一两天的摸索,我决定在 OpenSSL 中验证证书。结果证明该证书使用了不同的加密算法(SHA 256 与 DES3 或类似算法)。它在浏览器中运行良好的原因是因为我之前已经为该域安装了不同的证书。

故事的寓意:

  1. 在您的代码中尝试使用 SSL 证书之前,请始终使用 OpenSSL 测试它们。与 NodeJS、Java 或任何运行时环境相比,OpenSSL 始终会提供更多有关您的证书为何不起作用的信息。
  2. 在测试根证书之前,从受信任的根存储中删除域的所有证书。
  3. 我一直在关注关于在 Windows 中生成自签名根 CA 的在线教程,我发现的教程并没有提供很多关于我在做什么的信息,更多的是“这就是你如何去做”。这是我出错的地方,因为我遵循了几个教程并结合了信息以找到解决方案。这意味着我使用一个教程生成了根证书和私钥,然后使用另一个教程签署了其他证书(该教程指定了不同的算法,但没有解释算法必须与根 CA 和签名证书匹配)。
  4. 在深入制作自签名根 CA 之前,对 SSL 和根证书的工作原理有一个很好的理解会很有帮助。不是从技术角度,而是从为什么有根 CA、它们在现实世界中如何使用以及它如何应用于您作为开发人员的应用程序的角度。 I found this article extremely helpful.