具体案例:UNABLE_TO_VERIFY_LEAF_SIGNATURE

a specific case: UNABLE_TO_VERIFY_LEAF_SIGNATURE

我一直在尝试测试服务器和客户端之间的 TLS 连接。 (SSL 客户端身份验证)

我有一个自签名密钥对。

如果我尝试使用 tls.connect() 连接我的 API 服务器,我的连接似乎是 unauthorized 并且 authorizationError 值是 UNABLE_TO_VERIFY_LEAF_SIGNATURE,如下所示截图。

但是,如果我尝试连接 https://api.twitter.com 而不是 https://hellolarim.club,则没有错误,并且 authorization 值为 true。此外,当我尝试使用 Twitter 时,我不必使用 rejectUnauthorized: false 参数。

我也添加了以下 server.js代码。

问题: 我想知道为什么我无法连接 authorized: true ?

我必须对我的 API 服务器实施 SSL 客户端身份验证。

尝试连接到我的 API 服务器


client.js

var tls = require('tls');
var fs = require('fs');

var options = {
  key: fs.readFileSync('client-private-key.pem'),
  cert: fs.readFileSync('client-certificate.pem'),

  rejectUnauthorized: false,
};

{
var cleartextStream = tls.connect(443, 'www.hellolarim.club', options, function() {

  console.log('\nclient connected', cleartextStream.authorized ? 'authorized' : 'unauthorized'); 
  if(!cleartextStream.authorized) {
    console.log("authorizationError: " + cleartextStream.authorizationError);
  }

  process.stdin.resume();
  process.stdin.pipe(cleartextStream);
});
cleartextStream.setEncoding('utf8');
cleartextStream.on('data', function(data) {
  console.log("\n" + data);
});
cleartextStream.on('end', function() {
  server.close();
});

尝试连接到 Twitter API 服务器



Server.js

var tls = require('tls');
var fs = require('fs');

var options = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem'),
  requestCert: true,
  rejectUnauthorized: true,

  ca: [ fs.readFileSync('../client/client-certificate.pem') ]
};

var server = tls.createServer(options, function(cleartextStream) {

  console.log(cleartextStream.getPeerCertificate());

  console.log('server connected',
              cleartextStream.authorized ? 'authorized' : 'unauthorized');
  cleartextStream.write("Hello from server to client!\n");
  cleartextStream.setEncoding('utf8');
  cleartextStream.pipe(cleartextStream);
});
server.listen(443, function() {
  console.log('server bound');
});

问题出在客户端。

尽管证书是从商业 CA 获得的,但客户端无法识别服务器的证书,因为客户端选项中没有 ca 参数!

如果我们有很多根证书,我们可以通过如下所示转换字符串数组或使用 node-ssl-root-cas 来安装它们。

var CAcerts = [ 
  // A Root CA cert.
  "-----BEGIN CERTIFICATE-----\n" +
  "MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE\n" +
  "BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG\n" +
  "tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW\n" +
  "sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp\n" +
  "7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I\n" +
  "LaZRfyHBNVOFBkpdn627G190\n" +
  "-----END CERTIFICATE-----\n",
  // Another Root CA cert.
  "-----BEGIN CERTIFICATE-----\n" +
  "MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE\n" +
  "BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG\n" +
  "tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW\n" +
  "sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp\n" +
  "7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I\n" +
  "LaZRfyHBNVOFBkpdn627G190\n" +
  "-----END CERTIFICATE-----\n"
  ];

var options = {
  key: fs.readFileSync('client-private-key.pem'),
  cert: fs.readFileSync('client-certificate.pem'),
  ca: CAcerts,
  requestCert: true,
  rejectUnauthorized: true,
};