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业务的新手,请原谅我的无知。