我正在尝试自动化证书的部署,包括管理私钥上的权限。使用此question,我整理了一些应更新证书权限的代码:
public static SetPermissionsResult SetPermissions(X509Certificate2 certificate, string userName)
{
var account = new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null);
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.MaxAllowed);
var newCertificate = store.Certificates.Find(X509FindType.FindBySerialNumber, certificate.SerialNumber, false)[0];
var rsa = newCertificate.PrivateKey as RSACryptoServiceProvider;
if (rsa == null)
{
return SetPermissionsResult.Failure;
}
rsa.PersistKeyInCsp = true;
var cspParams = new CspParameters(
rsa.CspKeyContainerInfo.ProviderType,
rsa.CspKeyContainerInfo.ProviderName,
rsa.CspKeyContainerInfo.KeyContainerName)
{
Flags =
CspProviderFlags.UseExistingKey
| CspProviderFlags.UseMachineKeyStore,
CryptoKeySecurity =
rsa.CspKeyContainerInfo.CryptoKeySecurity,
KeyNumber = (int)rsa.CspKeyContainerInfo.KeyNumber/*,
KeyPassword = password*/
};
cspParams.CryptoKeySecurity.AddAccessRule(
new CryptoKeyAccessRule(account, CryptoKeyRights.GenericRead, AccessControlType.Allow));
using (var rsa2 = new RSACryptoServiceProvider(cspParams))
{
}
return SetPermissionsResult.Success;
}
}
在读取
using (var rsa2 = new RSACryptoServiceProvider(cspParams))
的行上(实例化新的加密提供程序以保留新的访问规则),我得到了CryptographicException“ Keyset不存在”。从经验中我知道,这通常意味着当前的安全上下文没有访问主键的权限。为了解决这种可能性,我做了以下工作:
在“即时”窗口中使用
System.Security.Principal.WindowsIdentity.GetCurrent()
找出当前用户是什么确保用户在MMC管理单元中具有证书的“完全控制”权限(并再次确认我正在为其寻找合适的存储区)
授予对所有人用户的完全控制权限。
尝试创建带有和不带有KeyPassword的CspParameters对象(您可以在此处看到注释)。
我没主意。该证书是伪造的自签名测试证书,因此与链中缺少权限的其他证书无关。任何帮助,将不胜感激。
更新:
通过修改此步骤之前的证书安装标志,我已经能够执行此代码。现在,代码可以成功执行,但是在MMC中看不到可见的效果。
最佳答案
我或多或少地解决了这个问题。上面列出的用于管理权限的代码是正确的。有问题的是在添加证书之前启动证书的代码。常识性的方法如下所示:
var certificate = new X509Certificate2(bytes, password);
这样做的问题是,它不会导致私钥在存储中持久保存,这是权限代码所依赖的(duh)。为此,您需要像这样实例化要添加到商店的证书:
var certificate = new X509Certificate2(bytes, "password123", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
并像这样添加它:
using (var store = new X509Store(storeName, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.MaxAllowed);
store.Add(certificate);
}
最终要点:MMC管理单元在显示更新的权限方面比较简单,即,即使实际上已更改,它也可能不显示新的权限。我到达了一切都能正常运行的地步,但没有意识到,因为MMC向我展示了与众不同。如果您怀疑自己所看到的内容,则关闭MMC并重新打开会强制刷新。