首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >统一TlsException:握手失败UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED

统一TlsException:握手失败UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED
EN

Stack Overflow用户
提问于 2020-01-28 09:25:07
回答 3查看 12.3K关注 0票数 7

我试图更新我的应用程序的TcpClient,使其与SslStream一起使用TLS,而不是普通的Stream,我为此使用的代码似乎在Unity2019.1.8(2018年和2017年也进行了测试)项目中集成时失败了。

要建立一个连接并打开一个新的SslStream,我使用以下代码:

代码语言:javascript
运行
复制
public static void InitClient(string hostName, int port, string certificateName)
{
    client = new TcpClient(hostName, port);

    if (client.Client.Connected)
    {
        Debug.LogFormat("Client connected succesfully");
    }
    else
    {
        Debug.LogErrorFormat("Client couldn't connect");
        return;
    }

    stream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

    try
    {
        stream.AuthenticateAsClient(certificateName);
    }
    catch (AuthenticationException e)
    {
        Debug.LogErrorFormat("Error authenticating: {0}", e);
        if (e.InnerException != null)
        {
            Debug.LogErrorFormat("Inner exception: {0}", e);
        }
        Debug.LogErrorFormat("Authentication failed - closing connection");
        stream.Close();
        client.Close();
    }
}

和验证证书

代码语言:javascript
运行
复制
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None)
        return true;

    Debug.LogErrorFormat("Certificate error: {0}", sslPolicyErrors);
    return false;
}

在Unity2019.1.8中,客户端连接并尝试验证远程证书,该证书在错误的TlsException: Handshake failed - error code: UNITYTLS_INTERNAL_ERROR, verify result: UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED.中失败

使ValidateServerCertificate始终返回true,让我的客户端能够毫无问题地连接。

我尝试使用完全相同的代码在独立的C#控制台应用程序中复制这个问题,目标是.net框架4.7.1。在此应用程序中启动客户端将从true检查中从ValidateServerCertificate返回sslPolicyErrors == SslPolicyErrors.None

我知道证书是一个有效的证书,由一个受信任的CA颁发(这是通过控制台应用程序接受证书,并且它在浏览器中有一个挂锁的事实来验证的)。

为什么统一中的验证失败了,而在其他地方却是如此?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-28 09:25:07

统一为什么不能验证选项1:

尽管证书是有效和正确的(例如,它在web浏览器中使用它时工作),但它不包括到根CA的中间证书链。其结果是无法形成信任链(Unity /检索中间层),从而设置UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED标志。

为了解决这个问题,我需要将证书链附加到我的叶证书中,以便Unity可以验证整个链直到根CA。要查找证书的证书链,可以使用"TLS证书链编写器“。

根据您使用的软件,您可能需要将链包含在证书中,或者将其保存在单独的文件中。来自何物链 (我根本不附属于这个网站,只是使用它):

注意:有些软件要求您将站点的证书(例如example.com.crt)和链证书(例如example.com.chain.crt)放在单独的文件中,而其他软件则要求您在站点证书之后将链证书放在同一个文件中。

统一为什么不能验证选项2:

当服务器的SSL证书过期时,统一将抛出完全相同的UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED错误,而不提供证书已过期的附加信息,因此请确保“有效到”日期是未来的(这也会导致在web浏览器中使用时拒绝证书)。

为什么浏览器/控制台应用程序可以验证:

软件在处理不完全链的方式上可以有不同的实现。它可以抛出一个错误,说明链被破坏,因此不能被信任(就像团结一样),或者缓存并保存中间层,以便以后使用/从以前的会话中检索它(就像浏览器和微软的.net(核心)一样)。

正如在这个答案 (强调地雷)中所解释的那样

通常,SSL/TLS客户端将尝试验证从服务器接收到的服务器证书链。如果客户端不满意该链,则客户端的行为取决于实现:一些客户端干脆放弃;其他客户端(特别是Windows/Internet )将尝试使用本地已知的中间CA构建另一个链,并从其他证书(“权威信息访问”扩展)中下载证书。

在没有提供链的情况下,不信任证书是团结公司出于跨平台可压缩性而作出的故意决定,如对1115214问题的答复中所述:

我们可以通过系统特定的TLS进行验证来解决这个问题,而不是像今天这样使用OpenSSL/MbedTLS对根证书进行验证,但是这个解决方案将不能跨平台工作。因此,我们今天不想实现它,因为它会在某些平台(但不是所有平台)上向用户隐藏配置错误的服务器。

当我问这个问题的时候,我发现这是一个解决我的特殊情况的方法,所以我决定自己回答它,作为将来的参考。然而,UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED可以有各种原因,这只是其中之一。

票数 12
EN

Stack Overflow用户

发布于 2020-11-11 20:28:12

对于那些偶然发现使用让我们加密UnityWebRequest的人来说

关于团结的问题跟踪器有一个已知的问题中,您会发现它只在某些版本中得到了修复:

  • 修正了2020.1.0a11
  • 固定在2019.3.3f1
  • 固定在2018.4.18f1

更改现有项目的统一版本并不是一项简单的任务,因此我们选择购买合法的SSL证书,这虽然不便宜,但是最简单的解决方案。

票数 1
EN

Stack Overflow用户

发布于 2020-12-10 22:57:05

我的解决办法是:

代码语言:javascript
运行
复制
> Public class ForceAcceptAll : CertificateHandler {
>     protected override bool ValidateCertificate(byte[] certificateData)
>     {
>         return true;
>     } }

//?

代码语言:javascript
运行
复制
var cert = new ForceAcceptAll();
 
// www is a UnityWebRequest
www.certificateHandler = cert;

Nota:如果使用不当(并且被Google发现,您的构建可能会被拒绝)。

所以要小心使用它。

更多信息,这里

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59945581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档