如何通过浏览器或服务器验证 ssl 证书

Max*_*kyi 1 javascript ssl https node.js

我创建了一个自签名证书

$ openssl genrsa -out key.pem 1024
$ openssl req -new -key key.pem -out request.csr
$ openssl x509 -req -in request.csr -signkey key.pem -out cert.pem
Run Code Online (Sandbox Code Playgroud)

并创建了一个 HTTPS 服务器:

var server = https.createServer({
    key: fs.readFileSync(__dirname + "/key.pem"),
    cert: fs.readFileSync(__dirname + "/cert.pem")
}
Run Code Online (Sandbox Code Playgroud)

然后我请求了页面。预期的结果是浏览器抱怨连接不安全。我的问题是浏览器如何知道这一点?验证证书并通知浏览器是服务器工作还是浏览器工作?

Jos*_*man 5

SSL 证书由客户端验证。

服务器通常会在启动时验证证书没有损坏或损坏,但大多数服务器实际上并不验证其证书的合法性。

为什么要验证证书?

服务器证书的验证很重要,否则客户端无法真正知道它正在与谁通信。MITM(中间人)攻击可能发生在第三方拦截通信双方的情况下,他们可以向您提供他们的数据,而不是您认为收到的来自服务器的数据。

关于证书类型的一些知识

大多数证书由 CA 签署,也有自签名证书和固定证书。我建议尽可能使用由 CA 签署的证书。第二个最佳选择(通常只能在组织内使用)将使用您自己的内部 CA,然后使用您的 CA 证书对您的服务器证书进行自签名,这称为自签名证书,它不会被信任由接收它的任何客户端或浏览器自动执行。

在自签名选项中,您必须将您的 CA 公钥导入您的 CA 密钥库,以便您的服务器证书获得信任。最后有一个简单的固定证书,您只需告诉浏览器信任其他不受信任的证书(不要这样做)。

警告- 您应该避免固定证书,因为它们在攻击期间几乎不可能被替换,并且证书应该安排在合理的期限内到期,并定期轮换。在某些情况下,即使几乎不可能,固定也会使这变得非常困难。

证书类型

  • CA 签名(需要在 WWW 上运行安全站点)
  • 自签名(适合内部组织使用,例如公司内部维基)
  • 固定(避免)

发生什么样的验证?

所以你有一个证书,首先你配置你的服务器以使用该证书。

现在,当客户端出现并请求安全连接到您的站点时(如在 HTTPS 的情况下连接到端口 443 所示)。您的服务器发送它的公共(非私有)证书并开始安全握手。一种这样的握手称为Diffie-Hellman 密钥交换握手本身超出了这个问题的范围。

在参与密钥交换之前,浏览器会首先检查服务器提供的证书。要使其有效,必须进行多项检查。

执行了一些检查。

  • 此证书是否包含与我们连接的主机名匹配的主机名?

    • 如果否,证书是否包含通配符 CN(通用名称)?
      • 如果是,该 CN 是否具有与我们连接的主机名匹配的有效“通配符”?是/否
  • 证书是否包含 CRL(证书撤销列表)?如果是,该 CRL 是否表明该证书仍然有效?是/否

  • 此证书是否由已知的证书颁发机构 (CA) 签署?是/否

    • 仅当否,此客户端(浏览器)是否具有已标记为受信任的公共证书(与此服务器提供的证书匹配)?是/否*这也称为固定证书,因为您不依赖 CA 来验证其真实性。

让浏览器信任证书,并通过代理服务器。然后我们必须选中上面的每个 Yes 框

其他让世界更安全的安全措施

现在还有其他一些不“特定”于证书的东西也得到了验证。

例如,客户端和服务器必须就握手方法、使用的密码、使用的散列算法以及其他事项达成一致。

服务器还可以传递特殊的 HTTPS 安全标志,指示浏览器在一段时间内不要信任此服务的其他证书(这称为证书锁定)。像“严格传输安全”中使用的证书固定(不要与上面提到的固定证书混淆)可以帮助防止 MITM(中间人)攻击。这是HTTPS Strict Transport Security提供的众多额外安全功能之一。

一旦所有的安全检查都得到认证,浏览器就会向服务器发送它所拥有的任何请求,服务器会做出适当的响应。