我有一个我自己签名生成的证书,然后由供应商签名。我必须连接到此供应商并使用证书进行身份验证。当我执行AuthenticateAsClient时,将调用我的LocalCertificateSelection回调,并将validIssuers参数设置为签署证书的参数。我应该从回调中返回什么证书?当我返回供应商颁发的证书时,我收到错误,因为证书未发送到服务器。我使用以下代码。
namespace TestClientAuthenticateHttps {
using System;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
class Program {
private readonly X509Certificate2Collection _certs;
private TcpClient _client;
private SslStream _sslStream;
private const string Host = "smr-staging.surescripts.net";
private const string SsSerial = "40 1f c1 ea 00 00 00 00 02 44";
private const SslProtocols EnabledSslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
private static void Main() {
var program = new Program();
program.Execute();
}
private Program() {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
_certs = certStore.Certificates.Find(X509FindType.FindBySerialNumber, SsSerial, false);
certStore.Close();
}
private void Execute() {
ConnectToHost();
try {
OpenSslConnection();
DoAuthentication();
} catch (Exception e) {
do {
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
e = e.InnerException;
} while (e != null);
} finally {
_sslStream.Close();
}
Console.ReadLine();
}
private void DoAuthentication() {
try {
_sslStream.AuthenticateAsClient(Host, _certs, EnabledSslProtocols, true);
} catch (Exception) {
Console.WriteLine($"Host is ({Host})");
Console.WriteLine($"_certs = ");
_certs.Cast<X509Certificate>().ToList().ForEach(Console.WriteLine);
throw;
}
}
private void OpenSslConnection() {
_sslStream = new SslStream(_client.GetStream(), false, RemoteCertificateValidate,
LocalCertificateSelection, EncryptionPolicy.AllowNoEncryption);
}
private static bool RemoteCertificateValidate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
return true;
}
private static X509Certificate LocalCertificateSelection(object sender, string host,
X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) {
Console.WriteLine($"Selecting certificate for ({host})");
var acceptable = acceptableIssuers.Select(s => new X500DistinguishedName(s).Name?.Trim()).Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
Console.WriteLine("Acceptable issuers.");
acceptable.ForEach(Console.WriteLine);
Console.WriteLine("Local certificate Selected");
var result = acceptableIssuers.Length == 0 ? localCertificates[0] : localCertificates?.Cast<X509Certificate2>().First(
c => acceptable.Any(n => n.Equals(c.IssuerName.Name?.Trim(), StringComparison.InvariantCultureIgnoreCase))
);
Console.WriteLine(result);
return result;
}
private void ConnectToHost() {
_client = new TcpClient(Host, 443);
}
}
}
答案 0 :(得分:0)
只需确保从回调中返回的证书具有私钥。 您可以通过将证书的PrivateKey属性设置为相应自签名密钥的PrivateKey属性来完成此操作。 如果从证书存储中读取CA颁发的密钥,请确保打开存储ReadWrite而不是ReadOnly。