如何从X509Store加载受密码保护的证书?

26

我正在构建一个受ACS保护的Azure WCF服务,它将要求客户端通过证书进行身份验证。

我希望客户端(以及服务器)能够从X509Store而不是文件系统中加载它们各自的密码证书。

我正在使用这段代码:

private static X509Certificate2 GetCertificate(string thumbprint)
{
    var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    certStore.Open(OpenFlags.ReadOnly);

    X509Certificate2Collection certCollection = certStore.Certificates.Find(
        X509FindType.FindByThumbprint,
        thumbprint, false);

    certStore.Close();

    if (certCollection.Count == 0)
    {
        throw new System.Security.SecurityException(string.Format(CultureInfo.InvariantCulture, "No certificate was found for thumbprint {0}", thumbprint));
    }

    return certCollection[0]; 
}

问题是,它没有加载需要进行身份验证的私钥。我已尝试将返回语句修改为:

return new X509Certificate2(certCollection[0].Export(X509ContentType.Pfx, "password"));

然而,这会导致一个 CryptographicException 错误:"指定的网络密码不正确"。

编辑:如果您不传递密码参数,则 .Export() 方法可以正常工作。

这方面有什么帮助吗?


1
什么是密码保护证书? - paparazzo
一个带密码的pfx文件。我可以使用以下方式从文件系统加载它:new X509Certificate2(filename, password)。 - Pete Maroun
3个回答

11

当您导出时,提供的密码是要用于导出文件的密码,而不是源证书的密码。

我不确定您可以在X509Store和受密码保护的证书上执行什么操作,因为密码应该提供给X509Certificate构造函数,并且您从存储中获取已经实例化的对象。

我认为您可以只获取所需证书的原始数据,并使用所需的密码构造一个新证书。例如:

X509Certificate2 cert = new X509Certificate2(certCollection[0].GetRawCertData, password);

我也建议你在处理密码时尝试使用SecureString(但这是一个不同的问题...)


1
是的,我尝试过了。虽然certCollection [0]具有PrivateKey,但新证书没有(PrivateKey属性为null,HasPrivateKey属性返回false)。 - Pete Maroun
1
嗯,可能是托管证书存储(或存储一般)不支持它。我认为通常使用存储中的证书会导致提示出现,要求用户输入密码。也许这被隐藏了? - Peter Ritchie

2

我使用了不带“password”参数的导出功能,没有出现任何问题。


0

当证书被导入证书存储时,我认为必须将密钥标记为“可导出”,否则您无法导出私钥。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接