繁体   English   中英

证书存储区中证书的私钥不可读

[英]Private key of certificate in certificate-store not readable

我想我和这个人有同样的问题,但我没有他/她那么幸运,因为提供的解决方案对我不起作用。

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

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

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

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

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

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

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

  1. 生成X509Certificate2
  2. 确保私钥容器是持久的(不是临时的)
  3. 确保对经过身份验证的用户具有访问规则 ,以便他们可以看到私钥

因此,最终的代码是:

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();

// :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM