简体   繁体   English

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

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

I think I've got the same issue like this guy , but I wasn't as lucky as him/her since the solution provided doesn't work for me. 我想我和这个人有同样的问题,但我没有他/她那么幸运,因为提供的解决方案对我不起作用。

The solution provided looks for files on the C:\\ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys ( not in sub directories) and C:\\Users\\[Username]\\AppData\\Roaming\\Microsoft\\Crypto\\RSA (and subdirectories) However since I want the setup to install the application to all users, the custom action is running under the SYSTEM -User, which leads the files beeing actually created in C:\\ProgramData\\Application Data\\Microsoft\\Crypto\\RSA\\S-1-5-18 . 提供的解决方案在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

When running an "normal" application as Admin (right click -> Run as Admin) executing exactly the same code, a file is created at 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创建一个文件C:\\Users\\[Username]\\AppData\\Roaming\\Microsoft\\Crypto\\RSA\\S-1-5-21-1154405193-2177794320-4133247715-1000

The certificate generated using the WIX custom action seems to not have a private key (" The key set does not exists "), while the cert generated by the "normal" application does. 使用WIX自定义操作生成的证书似乎没有私钥(“ 密钥集不存在 ”),而“正常”应用程序生成的证书具有。

When looking at the permissions of the files, they seem to be alright, even if they differ (the working one does include the SYSTEM user), even after adding the SYSTEM one to the ("non-working")file I am not able to read the private key, same error here. 在查看文件的权限时,它们似乎没问题,即使它们不同(工作者确实包括SYSTEM用户),即使将SYSTEM一个添加到(“非工作”)文件后我也无法在这里读取私钥,同样的错误。

Then I used the FindPrivateKey util the find the corresponding file but all I get is "Unable to obtain private key file name" . 然后我使用FindPrivateKey工具找到相应的文件,但我得到的是"Unable to obtain private key file name"

Ok whats going one here? 好的,这里有什么? Where does Windows store the private keys for certificates stored by the SYSTEM user? Windows在哪里存储SYSTEM用户存储的证书的私钥? Maybe there isn't any private key file created? 也许没有创建任何私钥文件? Why? 为什么?

I got a solution by googleing up nearly everything ... as I understand there are some things to do: 通过google几乎所有的东西我得到了一个解决方案...据我所知,有一些事情要做:

  1. Generate a X509Certificate2 生成X509Certificate2
  2. Make sure the private key container is persistent (not temporary) 确保私钥容器是持久的(不是临时的)
  3. Make sure to have acccess rules for authenticated users , so they can see the private key 确保对经过身份验证的用户具有访问规则 ,以便他们可以看到私钥

So the final code a came up with is the following: 因此,最终的代码是:

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