8

我已经搜索了互联网,但没有找到关于在使用 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 读取服务器你好 A”

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

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

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

和 OnVerifyPeer,AOk = False。

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

感谢阅读,阿德里安

4

3 回答 3

11

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

来自 IdSSLOpenSSL.pas:

请注意,您确实应该始终实现 OnVerifyPeer,否则不会检查您正在连接的对等方的证书以确保其有效。

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

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

由于 Indy 首先检查证书的有效性,并在 Aok 参数中将其传递给您。最后一句话在您的代码中,因为您可能希望通过一些小的验证错误,例如过期,或者甚至询问用户证书是否被接受以防出现任何错误(轻微或不) .

要了解它为什么会这样工作,您可能还需要阅读 IdSSLOpenSSL.pas 文件顶部的所有注释:

{

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

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

这产生了一个问题,即即使链中的一个证书只有一个非常小的问题(对证书链中的每个证书调用一次 OnVerifyPeer),用户可能很乐意接受,SSL 协商会失败。但是,当用户为 OnVerifyPeer 返回 True 时更改代码以允许 SSL 连接将意味着依赖于自动拒绝无效证书的现有代码将接受无效证书,这将是不可接受的安全更改。

因此,OnVerifyPeer 被更改为通过添加 AOk 参数来故意破坏现有代码。要保留以前的功能,您的 OnVerifyPeer 事件应该执行“Result := AOk;”。如果您希望考虑接受 SSL 库认为无效的证书,那么在您的 OnVerifyPeer 中,确保您确信证书确实有效,然后将 Result 设置为 True。实际上,除了检查 AOk 之外,您还应该始终实现代码以确保您只接受有效的证书(至少从您的角度来看)。

Ciaran Costelloe, ccostelloe[_a_t_]flogas.ie

}

{

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

}

于 2012-11-27T06:17:08.790 回答
1

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

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

于 2017-01-23T12:01:30.370 回答
0

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

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

于 2013-11-25T15:02:29.367 回答