Indy 10客户证书:全部集中在一个.pem文件中?

时间:2018-08-29 14:45:15

标签: openssl c++builder indy10

tl; dr:

TIdSSLIOHandlerSocketOpenSSL是否可以使用一个包含客户端证书的cert,root和key的.pem文件?


详细信息:

供应商合作伙伴要求我们使用mTLS身份验证。他们提供了一个证书,我以PEM格式导出了证书(包括我的证书,根证书和私钥)。

然后,我使用cURL在PHP中进行了一些简单的连接测试。

请注意,我能够使用包含所有内容的.pem文件。

$the_url = 'https://example.com/post-to-me';
$xml_payload = '<foo>bar</foo>';
$headers = array( "Content-type: text/xml",
                  "Content-length: ".strlen($xml_payload),
                  "Connection: close" );

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $the_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);            // Force curl_exec() to return server response string rather than true/false
curl_setopt($ch, CURLOPT_TIMEOUT, 10);                  // 10-second timeout
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSLCERT, 'all-in-one-cert.pem');
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, 'super-secret-password');

$result     = curl_exec($ch);

这产生了服务器的预期结果,因此我继续编写我的C ++ Builder代码:

FHTTP               = new TIdHTTP( 0 );
FSSLIOHandlerSocket = new TIdSSLIOHandlerSocketOpenSSL( 0 );

FLogFile            = new TIdLogFile( 0 );
FLogFile->LogTime   = true;

FSSLIOHandlerSocket->Intercept                  = FLogFile;
FSSLIOHandlerSocket->IPVersion                  = Id_IPv4;
FSSLIOHandlerSocket->MaxLineAction              = maException;
FSSLIOHandlerSocket->SSLOptions->Mode           = sslmClient;
FSSLIOHandlerSocket->SSLOptions->CertFile       = "all-in-one-cert.pem";
FSSLIOHandlerSocket->SSLOptions->RootCertFile   = "all-in-one-cert.pem";
FSSLIOHandlerSocket->SSLOptions->KeyFile        = "all-in-one-cert.pem";
FSSLIOHandlerSocket->OnGetPassword              = GetPassWord;
FSSLIOHandlerSocket->SSLOptions->Method         = sslvTLSv1_2;

FHTTP->IOHandler            = FSSLIOHandlerSocket;
FHTTP->ConnectTimeout       = 10000;
FHTTP->ReadTimeout          = 60000;
FHTTP->MaxAuthRetries       = 0;
FHTTP->Request->ContentType = "text/xml";

TStringStream * MsgStream = new TStringStream();
TStringStream * RspStream = new TStringStream();

MsgStream->WriteString( "<foo>bar</foo>" );

FHTTP->Post( "https://example.com/post-to-me", MsgStream, RspStream );

long StreamSize     = RspStream->Size;
RspStream->Position = 0;
FResponse           = RspStream->ReadString( StreamSize ).Trim();

这导致以下OpenSSL错误:

  

无法加载证书。   错误:00000000:lib(0):func(0):原因(0)

我也尝试过:

FSSLIOHandlerSocket->SSLOptions->CertFile       = "all-in-one-cert.pem";
FSSLIOHandlerSocket->OnGetPassword              = GetPassWord;

这产生了相同的错误。

我还尝试使用.pfx证书文件:

FSSLIOHandlerSocket->SSLOptions->CertFile       = "all-in-one-cert.pfx";
FSSLIOHandlerSocket->OnGetPassword              = GetPassWord;

这允许加载证书,但随后导致连接握手失败:

  

使用SSL连接时出错。   错误:14094410:SSL例程:SSL3_READ_BYTES:sslv3警报握手失败

我使用Wireshark验证了此握手错误是因为将0个证书传递到了握手中。

我通过将客户端证书,根目录和密钥分成三个单独的文件来解决了该问题,如下所示:

FSSLIOHandlerSocket->SSLOptions->CertFile       = "cert-only.pem";
FSSLIOHandlerSocket->SSLOptions->RootCertFile   = "root-only.pem";
FSSLIOHandlerSocket->SSLOptions->KeyFile        = "key-only.pem";

还是,我很好奇:有没有办法在单个.pem文件中对所有三个组件进行处理?还是我错过了什么?我是这个mTLS业务的新手,请原谅我的无知。

0 个答案:

没有答案