在C#中导入证书时,`PersistKeySet`-StorageFlag的影响是什么

在我的应用程序中,使用以下代码以编程方式将客户端身份validation证书添加到MY -Store:

 //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 -Store(指纹和认证链也正确)。

但是在某些计算机(Windows 7 Professional SP1和带有本地用户帐户的Widnows Server 2008 R2)上,证书之后可能不会用于客户端身份validation( “无法为SSL / TLS安全通道建立信任关系” )。 在具有域用户帐户的Windows 8.1 Enterprise计算机上,身份validation有时会起作用,但并非总是如此。

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

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

使用这些标志,证书可以在所有设备上使用。 即使我很高兴我的应用程序现在以预期的方式工作,我想明白为什么 ? PersistKeySet-Flag究竟做了什么?为什么它会影响证书的使用时间和人员?

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

导入PFX时,公共证书元素将加载到内存中,私钥材料将被转移到密钥存储提供程序中。 .NET中的默认行为是在X509Certificate2对象为Disposed时删除私钥材料(或其资源通过Garbage Collection完成)。 PersistKeySet标志可防止发生此清理。

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

如果您的导入过程是长期存在的,那么您看到的行为是在导入新访问私钥后的任意时间开始失败。 如果它是短暂的,那么它可能总是无法工作。

根据我的理解, PersistKeySet标志(如果指定)在磁盘上保留导入的PFX的私钥,该私钥位于导出的PFX(userkeyset或machinekeyset)源的证书所在的位置。 如果PFX是由工具生成的(例如pvk2pfx.exe),则没有源和默认值(userkeyset)。

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

否则,它将存储在userkeyset,此处: \Users\user\AppData\Roaming\Microsoft\Crypto\RSA\S-1-...

如果您希望证书在整个计算机上可用,忽略PFX的原始位置,您可能需要考虑使用MachineKeySet