【发布时间】:2021-11-26 05:49:46
【问题描述】:
我们的代码在C#中使用TcpClient and SslStream在调用AuthenticateAsClient方法时遇到错误The handshake failed due to an unexpected packet format.,SMTP服务器是smtp.office365.com,我们尝试了很多方法,但都不起作用。
-
试过了:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; -
试过了:
ssl.AuthenticateAsClient(Server, null, System.Security.Authentication.SslProtocols.Tls12, true); -
试过其他 AuthenticateAsClient 重载方法都不起作用。
-
同样使用Microsoft Network Monitor 3.4工具,我们可以确认
Client Hello握手使用的是TSL1.2协议。
有人遇到过类似的问题吗?
以下是 .NET Framework 8 控制台中的完整代码
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;
}
}
【问题讨论】: