我已经浏览过互联网,但在使用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。
如何让它正确验证。发生了什么事?
感谢阅读, 阿德里安
答案 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
。