在SSL握手中,是否可以使用反向角色?

时间:2011-11-22 21:26:38

标签: php qt ssl

我有一个php ssl客户端和一个C ++ Qt ssl服务器,我需要对客户端进行身份验证而不是服务器。

原因是C ++ Qt ssl服务器实际上在桌面应用程序上运行,并且出于安全原因我不想为桌面应用程序提供私钥,也因为服务器不需要自己进行身份验证。

所以我为客户端提供了证书和私钥,而服务器只有证书来验证客户端。

但是在上面的场景中,我从服务器端得到了ssl错误,由于缺少共享密码,握手失败。

如果我为服务器提供了自己的本地私钥和证书,则握手成功完成。

下面的一些php代码设置ssl:

/* $local_cert_path is a file containing a complete certificate
 * verification chain and the private key
 */
if (! is_file($local_cert_path))
{
    throw new Exception(sprintf('cannot find certificate path: %s', $local_cert_path));
}
$this->ctx = stream_context_create();
stream_context_set_option($this->ctx, 'ssl', 'verify_peer', FALSE);
stream_context_set_option($this->ctx, 'ssl', 'allow_self_signed', TRUE);
stream_context_set_option($this->ctx, 'ssl', 'local_cert', $local_cert_path);

和C ++(Qt):

QList<QSslCertificate> certs = cacerts(); 
socket->setCaCertificates(certs); // loading the CA
// socket->setLocalCertificate(":/res/cert.pem", QSsl::Pem);
// socket->setPrivateKey(":/res/key.pem");
socket->setPeerVerifyMode(QSslSocket::VerifyPeer);
socket->setProtocol(QSsl::TlsV1);

如果我为服务器提供了自己的本地私钥和证书(取消注释上面的两行),那么握手就可以了。

2 个答案:

答案 0 :(得分:1)

通常,是的,SSL允许这样做 - 客户端验证服务器提供的任何证书,并且服务器要求使用客户端身份验证,因此客户端必须使用其证书进行身份验证。另一方面,您的SSL库可能不够灵活,无法做到这一点。

答案 1 :(得分:1)

验证SSL / TLS服务器的身份是防止MITM攻击所必需的。即使您使用客户端证书身份验证(例如,相互身份验证),客户端也需要检查服务器的身份(通常通过检查它是否信任其X.509证书并且它与证书中的预期服务器身份相匹配)。为此,需要使用此类证书(及其关联的私钥)配置TLS服务器。 如果没有这个,客户端可以很好地使用客户端证书进行身份验证,除了它不知道它的身份验证(因此可能导致MITM攻击)。

这就是说,在您的情况下,TLS服务器不需要是TCP服务器。实际上,TLS倾向于在TCP之上使用。在大多数情况下,TCP客户端也是TLS客户端,只要客户端建立了TCP连接,它就会在其上发送一个TLS ClientHello,从而开始充当TLS客户端。

通过使servre启动发送ClientHello的TLS握手,您可以使TCP服务器充当TLS服务器。实际上,TLS Glossary客户端定义为:

  

启动到a的TLS连接的应用程序实体         服务器。这可能会或可能不会暗示客户发起了         底层运输连接。主要业务         服务器和客户端之间的区别在于服务器         通常经过身份验证,而客户端只是可选的         认证

我在Java中尝试过,它运行正常。在Java中,其作用是客户端,而服务器的作用只有在握手发生后才能修复。在此之前,您仍然可以使用setUseClientMode更改SSLSocket的角色,但SSLServerSocket(从SSLServerSocketFactory获取的服务器模式为SSLSocket从普通Socket转换(由服务器端的accept生成)可以用作客户端TLS套接字,反之亦然。

TLS允许这样做,但我不知道你使用的框架是否可行。

将普通TCP套接字转换为TLS套接字通常是通过STARTTLS (available in SMTP, IMAP and LDAP, for example)等机制升级套接字的协议所做的。

您需要从“真实”客户端到“真实”服务器建立纯TCP连接,将TCP客户端套接字转换为TLS套接字并将其设置为服务器模式,将TCP服务器套接字转换为TLS套接字,将其设置为客户端模式并启动握手。