php - 在 SSL 握手中,是否可以颠倒角色?

标签 php qt ssl

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

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

所以我为客户端提供了证书和私钥,而服务器只有对客户端进行身份验证的证书。

但是在上述情况下,我从服务器端收到 ssl 错误,由于缺少共享密码,握手失败。

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

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

/* $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);

如果我向服务器提供它自己的本地私钥和证书(取消上面两行的注释),那么握手就会成功。

最佳答案

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

也就是说,在您的情况下,TLS 服务器不必是 TCP 服务器。实际上,TLS 倾向于在 TCP 之上使用。在大多数情况下,TCP 客户端也是 TLS 客户端,一旦客户端建立了 TCP 连接,它也会通过它发送一个 TLS ClientHello,开始它作为 TLS 客户端的角色。

您可以使 TCP 服务器充当 TLS 服务器,方法是让服务器启动 TLS 握手并发送 ClientHello。事实上,TLS Glossary客户端定义为:

The application entity that initiates a TLS connection to a server. This may or may not imply that the client initiated the underlying transport connection. The primary operational difference between the server and client is that the server is generally authenticated, while the client is only optionally authenticated.

我已经在 J​​ava 中试过了,它运行良好。在 Java 中,哪个角色是客户端,哪个角色是服务器,只有在握手发生后才会确定。在此之前,您仍然可以使用 setUseClientMode 更改 SSLSocket 的角色。 ,尽管 SSLServerSocket(从 SSLServerSocketFactory 获得)将处于服务器模式,但从普通 Socket 转换而来的 SSLSocket (由服务器端的 accept 产生)可以用作客户端 TLS 套接字,反之亦然。

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

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

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

关于php - 在 SSL 握手中,是否可以颠倒角色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8234033/

相关文章:

php - 如何使用地址栏将值从 javascript 传递到 php

c++ - 我也应该连接到 QNetworkReply::error() 吗?

c++ - Vim C++(Qt,C)开发强大的插件

c++ - 在工作线程中取消操作时如何防止内存泄漏?

android - 应用认证

facebook-graph-api - Facebook Canvas 应用开发的 SSL 证书要求

php - codeigniter 3命名空间问题

javascript - 如何像php页面中的新闻提要一样在循环中垂直滚动div内容

php - HTML 表单和 PHP 脚本不起作用

iphone - Cocoa、Stomp、ActiveMQ、iPhone、SSL 和 AsyncSocket 需要帮助