【问题标题】:How do I avoid SELF_SIGNED_CERT_IN_CHAIN error in node.js TLS module?如何避免 node.js TLS 模块中的 SELF_SIGNED_CERT_IN_CHAIN 错误?
【发布时间】:2013-06-22 14:49:44
【问题描述】:

我正在尝试使用 node.js v0.10.5 和 einaros/ws (WebSockets) 模块创建 TLS/SSL 连接,但出现以下错误:

错误:SELF_SIGNED_CERT_IN_CHAIN

我从我自己的 CA 获得证书,这是一个 EJBCA 服务器,版本:EJBCA 4.0.15 (r16671),我在我的客户端中使用以下代码:

define(["ws", "fs"], function (WebSocket, fs) {
"use strict";
return function (jsonRequest) {
    var response,
        error,
        successCallback,
        errorCallback,
        HB_PFX = "server.domain.com.p12",
        HB_CA = "certs/my-ca.pem";

    var secureOptions = {
        passphrase: "the-passphrase",
        pfx: fs.readFileSync(HB_PFX),
        ca : [fs.readFileSync(HB_CA)]
    };

    var sendRequest = function () {
        var client = new WebSocket("wss://server.domain.com:8080/draft", secureOptions);

        client.on("open", function () {
            client.send(jsonRequest);
        });
            client.on("error", function (e) {
            error = e.toString();
            console.log(error);
            if (errorCallback) {
                errorCallback(error);
            }
        });

        client.on("message", function (message) {
            response = message;
            if (successCallback) {
                successCallback(message);
            }
        });

        client.on("close", function (code) {
            console.log("Connection closed with code: " + code);
        });
    };

    return {
        send: function (callback) {
            if (response && !error) {
                callback(response);
            } else {
                successCallback = callback;
            }

            sendRequest();

            return this;
        },
        ifError: function (callback) {
            if (error) {
                callback(response);
            } else {
                errorCallback = callback;
            }

            return this;
        }
    };
};

});

p12 存储(PKCS12)由 CA 生成,它包括密钥、我的服务器证书和 CA 证书。

我可以毫无问题地使用浏览器连接到服务器,我只是在第一次连接时收到提示接受证书。但是当我尝试与我的客户联系时,我总是会收到这个错误。我使用其 FQDN 连接到服务器,而不是 IP 地址。

如果我尝试使用自签名证书(在我的本地计算机中生成并使用的证书而不是 p12 文件),我会收到 DEPTH_ZERO_SELF_SIGNED_CERT 错误。

我在 Mac OS X 10.8.4 上运行。

我几乎尝试了所有排列,甚至将密钥和证书从 PKCS12 文件导出到 PEM 文件,但我得到了完全相同的错误。我还将 CA 证书添加到我可以在我的计算机中找到的所有 cacert 文件中,这些文件如下:

    /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/lib/security/cacerts
    /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts
    /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/security/cacerts
    /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts
    /System/Library/Java/Support/CoreDeploy.bundle/Contents/Home/lib/security/cacerts
    /System/Library/Java/Support/Deploy.bundle/Contents/Home/lib/security/cacerts

有人知道如何解决这个错误并在节点中创建安全连接吗?

【问题讨论】:

    标签: node.js ssl openssl


    【解决方案1】:

    以下是我作为示例创建的 https_server 和客户端,看看是否对您有帮助。

    https_server.js

    var https = require('https');
    var fs = require('fs');
    var url = require('url');
    
    var options = {
      key: fs.readFileSync('privkey.pem'),
      cert: fs.readFileSync('cacert.pem')
    };
    
    https.createServer(options, function (request, response) {
    
      var url_parts = url.parse(request.url, true);
      var query = url_parts.query;
      console.log("----------------------------------");
      console.log(request.method + "  method" + " and " + " timeout is "+  query.timeout);
      setTimeout(function () {
      console.log(" Executing setTimeout Function ");
        if(request.method=='POST') {
            console.log(" Inside post " );
            var body='';
            request.on('data', function (data) {
                body +=data;
            });
            response.setHeader("keyPOST","ValuePair");
            response.writeHead(200, {"Content-Type": "text/html"});
            response.write("<b>Hello World</b>");
            response.end(); 
            request.on('end',function(){
              var POST =  qs.parse(body);
              console.log("on request end " +POST);
              console.log("----------------------------------");
            });
    
        }
        else if(request.method=='GET') {
             console.log(" Inside get" );
             console.log("Query sent to the server is :" +query.name);
             response.setHeader("keyGET","ValuePair");
             response.writeHead(200, {"Content-Type": "text/html"});
             response.write("<b>Hello User, Response sent at "+query.timeout+" milli seconds from server</b>");
             response.end();
             request.on('end',function(){
                console.log("on request end");
                console.log("----------------------------------");
            });
        }
    
    }, query.timeout);
    }).listen(8000, "127.0.0.1",function() {
        console.log(' Server has been started at '+(new Date()) +' and running in https://127.0.0.1:8000/');
    });
    

    https_client.js:

    var https = require("https");
    var fs = require("fs");
    var querystring = require('querystring');
    var data = querystring.stringify({
          name: "Arun",
          timeout:5000
        });
    
    var options = {
      hostname: '127.0.0.1',
      port: 8000,
      path: '/saveText?name=Arun&timeout=5000',
      method: 'GET',
      key: fs.readFileSync('privkey.pem'),
      cert: fs.readFileSync('cacert.pem'),
      agent: false,
      rejectUnauthorized: false
    };
    
    
    var req = https.request(options, function(res) {
      console.log('STATUS: ' + res.statusCode);
      console.log('HEADERS: ' + JSON.stringify(res.headers));
      res.setEncoding('utf8');
      res.on('data', function (chunk) {
        console.log('BODY: ' + chunk);
      });
    });
    
    req.on('error', function(e) {
      console.log('problem with request: ' + e.message);
    });
    // write data to request body
    //req.write(data);
    req.end();
    

    使用 openssl 创建 privkey.pem 和 cacert.pem:

    1) command to create privkey.pem is : openssl genrsa  -out privkey.pem 2048
    2) command to create cacert.pem is  : openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095 
     (or) if the second command shows unable to locate openssl.cnf error use -config {openssl.cnf file path} option along with second command.
    

    【讨论】:

    • 您不应该在客户端级别需要 privkey.pem。事实上,在客户端应该只需要信任 CA。它应该如下所示: var options = { hostname: '127.0.0.1', port: 8000, path: '/saveText?name=Arun&timeout=5000', method: 'GET', ca: fs.readFileSync('cacert .pem'),代理:假,rejectUnauthorized:假};
    【解决方案2】:

    检查一下

    npm config set ca ""

    更多信息在这里 https://github.com/gootyfer/simple-ws-bradcast-server

    【讨论】:

      【解决方案3】:

      有人知道如何解决这个错误并在节点中创建安全连接吗?

      对于 Mac OS X,您需要将根证书(自签名,用于签名)放入您的钥匙串中。

      【讨论】:

        猜你喜欢
        • 2019-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多