delphi - 如何验证服务器主机名

标签 delphi ssl openssl certificate indy

我正在使用 Indy TIdHTTP(随 XE2 提供)和 OpenSSL 库 DLL V1.0.1m 在通过 HTTPS 连接时验证证书。我已经为 TIdSSLIOHandlerSocketOpenSSL 组件的 OnVerifyPeer 事件实现了一个事件处理程序。

function TForm1.IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509;
  AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  (...)
end;

According to RFC 2818, chapter 3.1., if the hostname is available to the client, the client MUST check it against the server's identity as presented in the server's Certificate message, in order to prevent man-in-the-middle attacks.

现在我在验证服务器证书的主机名时遇到了问题:

虽然通用名称 (CN) 中存在通配符 服务器证书 (*.google.com) 中主题字段中的字段, OnVerifyPeer 事件的参数 Certificate.Subject.OneLine 返回不带任何通配符的 CN(即 google.com 而不是 *.google.com)。

As stated in RFC 2818, chapter 3.1. the wildcard character * is used to match any single domain name component or component fragment.

  1. 尽管有必要验证主机名,但任何人都可以确认通配符已被 Indy 或 OpenSSL 库删除吗?

  2. 有没有人想过在这种情况下验证主机名?

非常感谢任何帮助。感谢阅读。

最佳答案

Can anyone confirm that the wildcard character is removed by Indy or the OpenSSL libraries, although it is necessary to verify the hostname?

不,OpenSSL 不会删除它。

我不知道 Indy 库。


Can anyone confirm that the wildcard character is removed by Indy or the OpenSSL libraries, although it is necessary to verify the hostname?

我两次引用它是有原因的 :) IETF 和 CA/B 论坛都反对将服务器名称放在 Common Name (CN) 中(浏览器遵循)。

您可能遇到的情况类似于 CN=example.com。在这种情况下,example.com 不是服务器名称;相反,它一个域。因此,您不应该假设它意味着匹配 *.example.com

如果服务器在 https://example.com 响应,您应该只在 Subject Alternate Name 包含 example.com< 时接受证书 因为公共(public) CA 在 CN 中列出了域。公共(public) CA 将 DNS 名称放在 SAN 中,因为它们遵循 CA/B 论坛。


Has anyone an idea to verify the hostname under these circumstances?

1.1.0 之前的 OpenSSL 执行主机名匹配。开发人员必须这样做。 OpenSSL 1.1.0 及更高版本具有内置功能。参见 X509_check_host(3)和 friend 。

要匹配主机名,您应该从 Common Name (CN)Subject Alternate 中收集所有名称名称 (SAN)。然后,它通常就像正则表达式匹配一样简单。

IETF 是快速和松散的,它们允许主机名出现在 CN 或 SAN 中。 CA/B 论坛和浏览器更加严格:如果主机名在 CN 中,那么它也必须存在于 SAN 中(是的,它必须列出两次)。否则,CA/B 论坛和浏览器需要 SAN 中的所有主机名。

我相信 OpenSSL 和 CA/B 论坛只允许在最左边的标签中使用通配符。我相信 IETF 允许通配符出现在任何地方。

如果您想查看示例代码,请查看 cURL 的实现。 cURL 使用 OpenSSL,但不依赖于 1.1.0 的 X509_check_host(3)和 friend 。 cURL 有自己的实现。


快速警告。主机名匹配是一种魔法。例如....

IETF 允许匹配到全局顶级域 (gTLD),例如 *.com*.net;和国家顶级域名 (ccTLD),如 *.uk*.us。我认为这是一种攻击,因为我知道没有任何一个 CA 可以声称“拥有”或“证明”gTLD。如果我在野外遇到其中一个证书,那么我会拒绝它。

CA/B 论坛不允许通配符 gTLD 或 ccTLD。浏览器试图通过使用 Public Suffix List 来避免它。 (PSL)。虚荣域的情况只会变得更糟,例如 *.google

浏览器还试图用 PSL 做另一件事。他们试图在子域上划分行政边界。例如,亚马逊拥有 amazon.com 的全部,但他们将权限委托(delegate)给子域,例如 example.amazon.com。因此,PSL 试图让亚马逊控制他们的域 amazon.com,但不允许您的 example.amazon.com 的商家相关子域。

IETF 正试图解决 DBOUND Working Group 中的行政边界问题.但事情似乎在委员会中停滞不前。

关于delphi - 如何验证服务器主机名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30441377/

相关文章:

delphi - 在哪里定义使用 {$IFDEF} 测试的符号?

delphi - 将以null结尾的内存流转换为unicode字符串

php - 如何解决 ubuntu 中的 SSL 证书错误

ios - Firebase SSL 错误 Google API 证书

node.js - Godaddy 转发到 Heroku 会导致 SSL 问题

delphi - 如何使用 Delphi 对字符串进行哈希处理?

php - 如何安全地为 AES CBC 加密生成 IV?

tomcat - 如何使用 APR 和 OpenSSL 测试 Tomcat 正在缓存 SSL session ?

visual-studio - 在 Windows 7 64 位上构建 OpenSSL 时遇到问题

delphi - 检测过时的互斥体