c# - 证书库中证书的私钥不可读

标签 c# certificate uac custom-action private-key

我想我也遇到了同样的问题 like this guy ,但我没有他/她那么幸运,因为提供的解决方案对我不起作用。

提供的解决方案在 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys( 子目录)和 C:\Users\[用户名]\AppData\Roaming\Microsoft\Crypto\RSA(和子目录) 但是,由于我希望安装程序将应用程序安装给所有用户,因此自定义操作在 SYSTEM-User 下运行,这导致在 C:\ProgramData\Application Data 中实际创建的文件\Microsoft\Crypto\RSA\S-1-5-18

当以管理员身份运行“正常”应用程序(右键单击 -> 以管理员身份运行)执行完全相同的代码时,将在 C:\Users\[Username]\AppData\Roaming\Microsoft\创建一个文件加密\RSA\S-1-5-21-1154405193-2177794320-4133247715-1000

使用 WIX 自定义操作生成的证书似乎没有私钥(“ key 集不存在”),而“普通”应用程序生成的证书有。

当查看文件的权限时,它们似乎没问题,即使它们不同(工作的确实包括 SYSTEM 用户),即使在添加 SYSTEM 一个到(“非工作”)文件我无法读取私钥,这里有同样的错误。

然后我用了FindPrivateKey util 找到相应的文件,但我得到的只是 "Unable to obtain private key file name"

好的,这里发生了什么? Windows 在哪里存储由 SYSTEM 用户存储的证书的私钥?也许没有创建任何私钥文件?为什么?

最佳答案

我通过谷歌搜索了几乎所有的东西得到了一个解决方案......据我所知,有一些事情要做:

  1. 生成一个X509Certificate2
  2. Make sure the private key container is persistent (not temporary)
  3. Make sure to have acccess rules for authenticated users , 这样他们就可以看到私钥

所以a想出的最终代码如下:

X509Certificate2 nonPersistentCert = CreateACertSomehow();

// this is only required since there's no constructor for X509Certificate2 that uses X509KeyStorageFlags but a password
// so we create a tmp password, which is not reqired to be secure since it's only used in memory
// and the private key will be included (plain) in the final cert anyway
const string TMP_PFX_PASSWORD = "password";

// create a pfx in memory ...
byte[] nonPersistentCertPfxBytes = nonPersistentCert.Export(X509ContentType.Pfx, TMP_PFX_PASSWORD);

// ... to get an X509Certificate2 object with the X509KeyStorageFlags.PersistKeySet flag set
X509Certificate2 serverCert = new X509Certificate2(nonPersistentCertPfxBytes, TMP_PFX_PASSWORD,
    X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); // use X509KeyStorageFlags.Exportable only if you want the private key to tbe exportable

// get the private key, which currently only the SYSTEM-User has access to
RSACryptoServiceProvider systemUserOnlyReadablePrivateKey = serverCert.PrivateKey as RSACryptoServiceProvider;

// create cspParameters
CspParameters cspParameters = new CspParameters(systemUserOnlyReadablePrivateKey.CspKeyContainerInfo.ProviderType, 
    systemUserOnlyReadablePrivateKey.CspKeyContainerInfo.ProviderName, 
    systemUserOnlyReadablePrivateKey.CspKeyContainerInfo.KeyContainerName)
{
    // CspProviderFlags.UseArchivableKey means the key is exportable, if you don't want that use CspProviderFlags.UseExistingKey instead
    Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseArchivableKey,
    CryptoKeySecurity = systemUserOnlyReadablePrivateKey.CspKeyContainerInfo.CryptoKeySecurity
};

// add the access rules
cspParameters.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), CryptoKeyRights.GenericRead, AccessControlType.Allow));

// create a new RSACryptoServiceProvider from the cspParameters and assign that as the private key
RSACryptoServiceProvider allUsersReadablePrivateKey = new RSACryptoServiceProvider(cspParameters);
serverCert.PrivateKey = allUsersReadablePrivateKey;

// finally place it into the cert store
X509Store rootStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
rootStore.Open(OpenFlags.ReadWrite);
rootStore.Add(serverCert);
rootStore.Close();

// :)

关于c# - 证书库中证书的私钥不可读,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13231858/

相关文章:

windows-installer - 设置 UAC 提升时间太长

c# - "Requested URL cannot be found"在IIS上发布网站时

c# - 如何知道下载何时完成

c# - 您能否在与设置 out 参数的调用相同的表达式中将 out 参数的变量用作另一个函数的下一个参数?

java - 如何使用 BasicHttpBinding 和 BasicHttpSecurityMode.TransportWithCredential : 将 header 元素 "mustunderstand=0"设置到 SOAP 请求中

c# - 从c#读取文件需要时提示UAC

installation - NSIS:安装应用程序以始终以管理员身份运行

c# - 使用 Entity Framework 调用存储过程并从 WCF 安全返回的更好方法?

ios - 您已吊销您的证书,因此它不再有效

ssl - 删除或自动输入 haproxy ssl 的 pem 密码; Chrome 仍然警告 CA 未签名