Delphi Indy验证服务器证书SSL

时间:2012-11-27 05:05:16

标签: delphi ssl indy

我已经浏览过互联网,但在使用TIdHTTP通过HTTPS连接时,没有找到解决方案或方法来验证证书。

我有挂钩​​一个IdSSLIOHandlerSocketOpenSSL成分作为IOHandler,设置SSLModes等,但是当我浏览到https://s3.amazonaws.com它不能验证该证书。

OpenSSL(Indy)给出了

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

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

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

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

SSL状态:“SSLv2 / v3写客户端问候A”

SSL状态:“SSLv3读取服务器问候语A”

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

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

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

OnVerifyPeer,AOk = False。

如何让它正确验证。发生了什么事?

感谢阅读, 阿德里安

3 个答案:

答案 0 :(得分:10)

您必须为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    或者为假,SSL连接会故意失败。

     

这造成了一个问题,即使只有一个非常小的问题    链中的一个证书的问题(OnVerifyPeer被调用    一次用于证书链中的每个证书),用户可以使用    我很高兴接受,SSL谈判将失败。然而,    当用户返回True时,更改代码以允许SSL连接    对于OnVerifyPeer而言,这意味着依赖于现有代码    然后,自动拒绝无效证书就会被接受    无效的证书,这将是一个不可接受的安全性    变化

     

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

     

Ciaran Costelloe,ccostelloe [_a_t_] flogas.ie

     

}

     

{

     

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

     

}

答案 1 :(得分:1)

我知道这是一个古老的帖子,但我能找到解决问题的全部内容。所以我想在其他人遇到同样问题时加入Marcus的答案: 当OpenSSL在PC上找不到根证书时,AError将返回#19(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN),并且根证书的AOK将为false。当您从文件手动加载根证书时,AOK应该始终返回true(并且您已经获得了某种类型的证书固定):

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

答案 2 :(得分:0)

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

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