简体   繁体   English

Delphi Indy验证服务器证书SSL

[英]Delphi Indy verify server certificate SSL

I have scoured the internet and haven't found a solution or method on how to verify the certificate when connecting over HTTPS using TIdHTTP. 我已经浏览了互联网,但在使用TIdHTTP通过HTTPS连接时,没有找到关于如何验证证书的解决方案或方法。

I have hooked up a IdSSLIOHandlerSocketOpenSSL component as the IOHandler, set the SSLModes, etc. but when I browse to https://s3.amazonaws.com it cannot verify the certificate. 我已经将IdSSLIOHandlerSocketOpenSSL组件连接为IOHandler,设置SSLModes等,但是当我浏览到https://s3.amazonaws.com时,它无法验证证书。

OpenSSL (Indy) gives OpenSSL(Indy)给出

"Error connecting with SSL. SSL3_GET_SERVER_CERTIFICATE: Certificate verify failed" “使用SSL连接时出错.SSL3_GET_SERVER_CERTIFICATE:证书验证失败”

The OpenSSL libraries have successfully loaded (checked with WhichFailedToLoad). 已成功加载OpenSSL库(使用WhichFailedToLoad进行检查)。 The OnStatusInfo event writes the following: OnStatusInfo事​​件写入以下内容:

SSL status: "before/connect initialization" SSL状态:“在/初始化之前”

SSL status: "before/connect initialization" SSL状态:“在/初始化之前”

SSL status: "SSLv2/v3 write client hello A" SSL状态:“SSLv2 / v3写客户端问候A”

SSL status: "SSLv3 read server hello A" SSL状态:“SSLv3读取服务器问候A”

SSL status: "SSLv3 read server certificate B" SSL状态:“SSLv3读取服务器证书B”

SSL status: "SSLv3 read server certificate B" SSL状态:“SSLv3读取服务器证书B”

SSL status: "SSLv3 read server certificate B" SSL状态:“SSLv3读取服务器证书B”

And OnVerifyPeer, AOk = False. 并且OnVerifyPeer,AOk = False。

How can I get it to verify correctly. 我怎样才能让它正确验证。 What's going on? 这是怎么回事?

Thanks for reading, Adrian 感谢阅读,阿德里安

You have to implement a event handler for the OnVerifyPeer event of your TIdSSLIOHandlerSocketOpenSSL component. 您必须为TIdSSLIOHandlerSocketOpenSSL组件的OnVerifyPeer事件实现事件处理程序。

From IdSSLOpenSSL.pas: 来自IdSSLOpenSSL.pas:

Note that you really should always implement OnVerifyPeer, otherwise the certificate of the peer you are connecting to is NOT checked to ensure it is valid. 请注意,您确实应该始终实现OnVerifyPeer,否则不会检查您要连接的对等方的证书以确保它是有效的。

If you just want to consider valid the same certificates the Library considers also valid, you just have to implement it this way: 如果您只想考虑库认为有效的相同证书,您只需要以这种方式实现它:

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

As Indy first checks for the validity of the certificate and pass you if it is Ok or not in the AOk parameter. 因为Indy首先检查证书的有效性,如果在AOk参数中是否正常则通过。 The last word is in your code, as you may want to let pass some kinds of minor validation errors , like being out of date, or even ask the user if the certificate is accepted or not in case of any error (minor or not). 最后一个词是在你的代码中,因为你可能想要传递某些类型的小验证错误 ,比如过时,或者甚至询问用户是否接受证书是否有任何错误(次要或不是) 。

To understand why it works this way, you may also want to read all the comments at the top of the IdSSLOpenSSL.pas file: 要了解它为何如此工作,您可能还想阅读IdSSLOpenSSL.pas文件顶部的所有注释:

{ {

Important information concerning OnVerifyPeer: Rev 1.39 of February 2005 deliberately broke the OnVerifyPeer interface, which (obviously?) only affects programs that implemented that callback as part of the SSL negotiation. 有关OnVerifyPeer的重要信息:2005年2月的Rev 1.39故意破坏了OnVerifyPeer接口,这显然只会影响作为SSL协商的一部分实现该回调的程序。 Note that you really should always implement OnVerifyPeer, otherwise the certificate of the peer you are connecting to is NOT checked to ensure it is valid. 请注意,您确实应该始终实现OnVerifyPeer,否则不会检查您要连接的对等方的证书以确保它是有效的。

Prior to this, if the SSL library detected a problem with a certificate or the Depth was insufficient (ie the "Ok" parameter in VerifyCallback is 0 / FALSE), then irrespective of whether your OnVerifyPeer returned True or False, the SSL connection would be deliberately failed. 在此之前,如果SSL库检测到证书有问题或者深度不足(即VerifyCallback中的“Ok”参数为0 / FALSE),则无论您的OnVerifyPeer是返回True还是False,SSL连接都将是故意失败了。

This created a problem in that even if there was only a very minor problem with one of the certificates in the chain (OnVerifyPeer is called once for each certificate in the certificate chain), which the user may have been happy to accept, the SSL negotiation would be failed. 这就产生了一个问题,即使链中的一个证书(证书链中的每个证书都调用一次OnVerifyPeer)只有一个非常小的问题,用户可能乐于接受,SSL协商会失败的。 However, changing the code to allow the SSL connection when a user returned True for OnVerifyPeer would have meant that existing code which depended on automatic rejection of invalid certificates would then be accepting invalid certificates, which would have been an unacceptable security change. 但是,当用户为OnVerifyPeer返回True时,更改代码以允许SSL连接将意味着依赖于自动拒绝无效证书的现有代码将接受无效证书,这将是不可接受的安全性更改。

Consequently, OnVerifyPeer was changed to deliberately break existing code by adding an AOk parameter. 因此,OnVerifyPeer被更改为通过添加AOk参数故意破坏现有代码。 To preserve the previous functionality, your OnVerifyPeer event should do "Result := AOk;". 要保留以前的功能,OnVerifyPeer事件应该执行“Result:= AOk;”。 If you wish to consider accepting certificates that the SSL library has considered invalid, then in your OnVerifyPeer, make sure you satisfy yourself that the certificate really is valid and then set Result to True. 如果您希望考虑接受SSL库认为无效的证书,那么在您的OnVerifyPeer中,确保您确信证书确实有效,然后将Result设置为True。 In reality, in addition to checking AOk, you should always implement code that ensures you are only accepting certificates which are valid (at least from your point of view). 实际上,除了检查AOk之外,您应该始终实现代码,以确保您只接受有效的证书(至少从您的角度来看)。

Ciaran Costelloe, ccostelloe[_a_t_]flogas.ie Ciatel Costelloe,ccostelloe [_a_t_] flogas.ie

} }

{ {

RLebeau 1/12/2011: Breaking OnVerifyPeer event again, this time to add an additional AError parameter (patch courtesy of "jvlad", dmda@yandex.ru). RLebeau 2011年1月12日:再次打破OnVerifyPeer事件,这次添加一个额外的AError参数(补丁由“jvlad”提供,dmda @ yandex.ru)。 This helps user code distinquish between Self-signed and invalid certificates. 这有助于用户代码区分自签名证书和无效证书。

} }

I know this is an ancient post, but it is all I could find to solve the problem. 我知道这是一个古老的帖子,但我能找到解决问题的全部内容。 So I would like to add to Marcus's answer for others with the same problem: When OpenSSL cannot find the root certificate on the PC, AError will return #19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN), and the AOK will be false for the Root certificate. 所以我想在其他人遇到同样问题时添加Marcus的答案:当OpenSSL在PC上找不到根证书时,AError将返回#19(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN),并且根证书的AOK将为false。 When you manually load the root certificate from file, AOK should always return true (and you have achieved certificate pinning of some sort too): 当您从文件手动加载根证书时,AOK应该始终返回true(并且您已经实现了某种类型的证书固定):

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

If you get an error like SSL3_GET_SERVER_CERTIFICATE:certificate verify failed , then keep reading: 如果您收到类似SSL3_GET_SERVER_CERTIFICATE:certificate verify failed的错误SSL3_GET_SERVER_CERTIFICATE:certificate verify failed ,请继续阅读:

It seems in Indy 10, that if you set a VerifyDepth of 0 , the 0 actually means all . 在Indy 10中,如果将VerifyDepth设置为0 ,则0实际上意味着all

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM