我正在开发非常简单的桌面(win窗体)应用程序,它通过HTTPS协议上的WCF服务与服务器通信。 每个使用此应用程序的客户端都可以上传客户端证书(每个客户端都是唯一的),用于通信。
我想要实现的目标是什么: 1.用户将“上传”证书到我的桌面应用程序,应用程序获取证书并以编程方式将证书保存到Windows证书库,这是我的代码:
[SecurityCritical]
public CertificateInfoDto GetCertificateInfoAndImportToStore(string fullPath, SecureString password)
{
if (string.IsNullOrEmpty(fullPath))
{
throw new ArgumentNullException("fullPath");
}
if (!File.Exists(fullPath))
{
throw new ArgumentException(string.Concat("No file present on ", fullPath));
}
try
{
byte[] rawBytes = this.GetCertificateContent(fullPath);
var certificate = new X509Certificate2(rawBytes, password, X509KeyStorageFlags.Exportable);
this.EnsureImport(certificate);
}
// some error handling etc, and end of method.
[SecurityCritical]
private void EnsureImport(X509Certificate2 certificate)
{
X509Store store = null;
try
{
store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
}
在我的应用程序设置文件中,我只存储证书序列号。 2.现在,当我将证书上传到Windows商店时,我想将它用于wcf通信,所以我的代码如下:
var client = new SomeWcfServiceProxy();
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySerialNumber,
certificateSerialNumber);
最后,这是我的问题,当我尝试在代理上调用某个方法时,生病得到一个异常: System.ServiceModel.Security.SecurityNegotiationException:无法为具有权限'url(我更改此项)'的SSL / TLS建立安全通道。 ---> System.Net.WebException:请求已中止:无法创建SSL / TLS安全通道。
但令我困惑的是,当我创建这样的代理客户端时:
var client = new SomeWcfServiceProxy();
var clientCertificate = new X509Certificate2(@"C:\U\BB\certificate.pfx", "password");
client.ClientCredentials.ClientCertificate.Certificate = clientCertificate;
一切都像魅力一样! 所以有我的问题:我不希望在任何地方存储客户端证书密码,我想通过Windows证书存储区上传它,然后只从Windows证书存储区使用它。这可能吗?或者我必须在某处存储证书密码(我不知道在哪里,因为我认为它不是很安全,而且这个证书非常非常机密)。 感谢您的帮助:))
答案 0 :(得分:1)
毕竟,我需要这个:
var certificate = new X509Certificate2(rawBytes, password, X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
现在证书导入恰到好处,可以毫无问题地用于通信