【问题标题】:Delphi Indy verify server certificate SSLDelphi Indy 验证服务器证书 SSL
【发布时间】:2012-11-14 16:31:48
【问题描述】:

我已经搜索了互联网,但没有找到关于如何在使用 TIdHTTP 通过 HTTPS 连接时验证证书的解决方案或方法。

我已将 IdSSLIOHandlerSocketOpenSSL 组件连接为 IOHandler,设置 SSLModes 等,但是当我浏览到 https://s3.amazonaws.com 时,它无法验证证书。

OpenSSL (Indy) 提供

“使用 SSL 连接时出错。SSL3_GET_SERVER_CERTIFICATE:证书验证失败”

OpenSSL 库已成功加载(通过 WhichFailedToLoad 进行检查)。 OnStatusInfo 事件写入以下内容:

SSL 状态:“之前/连接初始化”

SSL 状态:“之前/连接初始化”

SSL 状态:“SSLv2/v3 写入客户端 hello A”

SSL 状态:“SSLv3 读取服务器 hello A”

SSL 状态:“SSLv3 读取服务器证书 B”

SSL 状态:“SSLv3 读取服务器证书 B”

SSL 状态:“SSLv3 读取服务器证书 B”

而 OnVerifyPeer,AOk = False。

我怎样才能让它正确验证。怎么回事?

感谢阅读, 阿德里安

【问题讨论】:

    标签: delphi ssl indy


    【解决方案1】:

    您必须为您的 TIdSSLIOHandlerSocketOpenSSL 组件的 OnVerifyPeer 事件实现事件处理程序。

    来自 IdSSLOpenSSL.pas:

    请注意,您确实应该始终 实现OnVerifyPeer,否则你是peer的证书 未检查连接以确保其有效。

    如果您只想考虑图书馆认为有效的相同证书也有效,您只需以这种方式实现它:

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

    因为 Indy 首先检查证书的有效性,并在 AOk 参数中将其传递给您。最后一句话在您的代码中,因为您可能希望通过某些类型的次要验证错误,例如过期,或者甚至询问用户证书是否被接受,以防万一任何错误(无论是否轻微)。

    要了解它为何如此工作,您可能还需要阅读 IdSSLOpenSSL.pas 文件顶部的所有 cmets:

    {

    关于 OnVerifyPeer 的重要信息: 2005 年 2 月的 Rev 1.39 故意破坏了 OnVerifyPeer 接口, 哪个(显然?)只影响实现该回调的程序 作为 SSL 协商的一部分。请注意,您确实应该始终 实现OnVerifyPeer,否则你是peer的证书 未检查连接以确保其有效。

    在此之前,如果 SSL 库检测到证书有问题 或深度不足(即 VerifyCallback 中的“Ok”参数 为 0 / FALSE),则无论您的 OnVerifyPeer 是否返回 True 或 False,SSL 连接会故意失败。

    这造成了一个问题,即使只有一个非常小的 链中的证书之一出现问题(调用 OnVerifyPeer 证书链中的每个证书一次),用户可以 已经乐于接受,SSL 协商将失败。然而, 当用户返回 True 时更改代码以允许 SSL 连接 对于 OnVerifyPeer 将意味着依赖于的现有代码 自动拒绝无效证书将被接受 无效的证书,这将是一种不可接受的安全性 改变。

    因此,OnVerifyPeer 被更改为故意破坏现有代码 通过添加 Aok 参数。为了保留以前的功能,您的 OnVerifyPeer 事件应该执行“Result := Aok;”。如果你想考虑 接受 SSL 库认为无效的证书,然后 在您的 OnVerifyPeer 中,确保您对证书感到满意 真的是有效的,然后将结果设置为真。实际上,除了 检查 Aok,你应该始终实现确保你只 接受有效的证书(至少从您的角度来看)。

    Ciaran Costelloe,ccostelloe[_a_t_]flogas.ie

    }

    {

    RLebeau 1/12/2011:再次打破 OnVerifyPeer 事件,这次添加了一个额外的事件 AError 参数(补丁由“jvlad”提供,dmda@yandex.ru)。这 帮助用户代码区分自签名和无效 证书。

    }

    【讨论】:

      【解决方案2】:

      我知道这是一篇古老的帖子,但我只能找到解决问题的方法。所以我想为其他有同样问题的人补充马库斯的答案: 当 OpenSSL 在 PC 上找不到根证书时,AError 将返回 #19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN),并且根证书的 AOK 将为 false。当您从文件手动加载根证书时,AOK 应该始终返回 true(并且您也实现了某种证书固定):

      FSSLIOHandlerSocketOpenSSL.SSLOptions.RootCertFile := 'MyRoot.cer';

      【讨论】:

        【解决方案3】:

        如果您收到类似SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 的错误,请继续阅读:

        似乎在 Indy 10 中,如果您将 VerifyDepth 设置为 0,则 0 实际上意味着 all

        【讨论】:

          猜你喜欢
          • 2015-06-24
          • 1970-01-01
          • 1970-01-01
          • 2017-02-15
          • 2015-01-27
          • 2010-09-09
          • 1970-01-01
          • 2021-12-16
          • 1970-01-01
          相关资源
          最近更新 更多