首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SslStream AuthenticateAsClient方法获取“由于意外的数据包格式导致握手失败”错误

SslStream AuthenticateAsClient方法获取“由于意外的数据包格式导致握手失败”错误
EN

Stack Overflow用户
提问于 2021-11-26 05:49:46
回答 1查看 738关注 0票数 0

我们的代码在TcpClient和SslStream中使用C#,在调用AuthenticateAsClient方法时遇到一个错误The handshake failed due to an unexpected packet format.,SMTP服务器是smtp.office365.com,我们尝试了许多方法,但都无法工作。

  1. 尝试:System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  2. 尝试:ssl.AuthenticateAsClient(Server, null, System.Security.Authentication.SslProtocols.Tls12, true);
  3. 尝试了其他AuthenticateAsClient重载方法,但都不起作用。
  4. 另外,使用Microsoft网络监视器3.4工具,我们可以使用TSL1.2协议确认Client Hello握手。

有人遇到过类似的问题吗?

下面是使用.NET框架8的控制台中的完整代码

代码语言:javascript
运行
复制
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string Server = "smtp-legacy.office365.com";
                //This server raise error too
                Server = "smtp.office365.com";
                int port = 587;
                //tried this, not working
                //System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                //
                using (var tcp = new System.Net.Sockets.TcpClient())
                {
                    tcp.Connect(Server, port);

                    System.Net.Security.RemoteCertificateValidationCallback remoteCertCallback =
                        new System.Net.Security.RemoteCertificateValidationCallback((Object sender,
                               System.Security.Cryptography.X509Certificates.X509Certificate cert,
                               System.Security.Cryptography.X509Certificates.X509Chain chain,
                               System.Net.Security.SslPolicyErrors Errors) => true);

                    //System.Net.Security.SslStream ssl = 
                    //    new System.Net.Security.SslStream(tcp.GetStream(), false, remoteCertCallback, null);

                    //Try set LocalCertificateSelectionCallback
                    System.Net.Security.SslStream ssl =
                        new System.Net.Security.SslStream(tcp.GetStream(), false, remoteCertCallback, SelectLocalCertificate);

                    //Raise error: The handshake failed due to an unexpected packet format.
                    #region Try to specify the protocol, not working
                    ssl.AuthenticateAsClient(Server, null, System.Security.Authentication.SslProtocols.Tls12, true);
                    #endregion

                    #region Try to set local certificate, not working
                    //tried to set local certificate, not working
                    //X509CertificateCollection clientCertificates = GetLocalCertificates();
                    //ssl.AuthenticateAsClient(Server, clientCertificates, System.Security.Authentication.SslProtocols.Tls12, true);
                    #endregion

                    #region Default way, not working
                    //Raise error: The handshake failed due to an unexpected packet format.
                    //ssl.AuthenticateAsClient(Server);
                    #endregion


                }

            }
            //Raise error: The handshake failed due to an unexpected packet format.
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.Read();

        }


        public static X509Certificate2Collection GetLocalCertificates()
        {
            X509Certificate2Collection Certificates = null;
            // Read the certificate from the store
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            try
            {
                store.Open(OpenFlags.ReadOnly);
                //Certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
                //"CN=[YOUR DOMAIN]", false);
                Certificates = store.Certificates;
            }
            finally
            {
                store.Close();
            }

            return Certificates;
        }

        public static X509Certificate SelectLocalCertificate(
            object sender,
            string targetHost,
            X509CertificateCollection localCertificates,
            X509Certificate remoteCertificate,
            string[] acceptableIssuers)
        {
            if (acceptableIssuers != null &&
                acceptableIssuers.Length > 0 &&
                localCertificates != null &&
                localCertificates.Count > 0)
            {
                // Use the first certificate that is from an acceptable issuer.
                foreach (X509Certificate certificate in localCertificates)
                {
                    string issuer = certificate.Issuer;
                    if (Array.IndexOf(acceptableIssuers, issuer) != -1)
                        return certificate;
                }
            }
            if (localCertificates != null &&
                localCertificates.Count > 0)
                return localCertificates[0];

            return null;
        }

    }
EN

回答 1

Stack Overflow用户

发布于 2021-12-10 09:50:19

最后,我们找到了解决方案,在这里发布,以防任何人有同样的问题:

因此有两种情况:

案例1:用于TLS,需要在步骤5之后调用AuthenticateAsClient

案例2:用于SSL,需要在步骤1之后调用AuthenticateAsClient

我们的问题是,我们在步骤1之后调用了AuthenticateAsClient,正确的位置是,我们应该在发送StartTLS之后调用AuthenticateAsClient,在发送StartTLS之后,确保服务器返回支持StartTSL的信息。

步骤1.客户端: TCP握手/连接

(For SSL only) call AuthenticateAsClient before EHLO

步骤2.服务器: 200就绪

第三步客户:埃洛

步骤4.服务器:250个StartTLS(means support TLS)

步骤5. Client: StartTLS (发送StartTLS推荐)

(For TLS only) call AuthenticateAsClient after StartTLS

步骤6.服务器: 220 Go Head

步骤7.客户端:用加密发送数据/电子邮件(编辑)

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

https://stackoverflow.com/questions/70120066

复制
相关文章

相似问题

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