2016-04-26 54 views
3

在我的应用程序,为客户端身份验证的证书被编程使用下面的代码添加到MY -store的影响:什么是'PersistKeySet`-StorageFlag在C#中导入证书时

//certData is a byte[] 
//password is a SecureString 
X509Certificate2 certificate = new X509Certificate2(certData, password, X509KeyStorageFlags.Exportable); 
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
try 
{ 
    store.Open(OpenFlags.ReadWrite); 
    store.Add(certificate); 
} 
finally 
{ 
    store.Close(); 
} 

使用此代码,证书已正确导入MY-在我测试的所有机器上的存储(指纹和认证链也正确)。 (“无法为SSL/TLS安全通道建立信任关系”)。 在具有域用户帐户的Windows 8.1企业计算机上,身份验证有时会但并非总是有效。

我绝对尝试了几件事,终于找到了将X509KeyStorageFlags.PersistKeySet添加到存储标志的解决方案。 所以,第一行是现在:

X509Certificate2 certificate = new X509Certificate2(certData, password, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); 

有了这些标志,证书可以在所有设备上使用。 即使我很高兴我的应用程序现在能以预期的方式工作,但我想了解为什么? PersistKeySet-Flag究竟做了什么以及它为什么会影响何时以及由谁来使用证书?

MSDN在这种情况下不是很有帮助。

+1

可能与安装在临时容器中而不是永久容器中的密钥相关。详情请看这里:https://support.microsoft.com/en-gb/kb/950090 – momar

回答

6

当导入一个PFX时,公共证书元素被加载到内存中,并且私钥材料被转移到密钥存储提供程序中。 .NET中的默认行为是在X509Certificate2对象被Disposed(或其资源正在通过垃圾收集定稿)时删除私钥材料。 PersistKeySet标志防止发生这种清理。

如果要添加到持久性证书存储区,则始终需要设置PersistKeySet。如果不添加到持久存储中,您很可能不希望将其设置。

如果您的导入过程是长期存在的,那么您将看到的行为是在导入新私人密钥开始失败后的任意时间。如果它很短暂,那么它可能总是失败。

+0

这很有帮助,谢谢!你有我的可靠来源吗? – GuyMontag

+1

https://support.microsoft.com/zh-cn/kb/950090描述未能使用PersistKeySet,https://github.com/dotnet/corefx/issues/8186描述了两种当前的导入模式,可以在https://github.com/dotnet/corefx上搜索.NET Core实现(.NET Framework版本在VM内处理,因此不在ReferenceSource上)。 – bartonjs

0

根据我的理解,PersistKeySet标志(如果指定的话)会将导入的PFX的私钥保存在与导出的PFX源(用户键或机器键集)源证书相同的位置。如果PFX由工具生成(例如pvk2pfx.exe),则不存在源并使用默认值(userkeyset)。

在这种情况下,如果作为导出PFX源的证书的私钥存储在machinekeyset中,则私钥将以machinekeyset的形式导入,这里是:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

否则,它将被存储在userkeyset中,在这里: \Users\user\AppData\Roaming\Microsoft\Crypto\RSA\S-1-...

如果您希望您的证书在机器上可用,不考虑PFX的原始位置,您可能需要考虑使用MachineKeySet