3

我正在尝试自动部署证书,包括管理私钥的权限。使用这个问题,我拼凑了一些应该更新证书权限的代码:

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 does not exist"

我从经验中知道,这通常意味着当前的安全上下文没有访问主键的权限。为了解决这种可能性,我做了以下事情:

  1. System.Security.Principal.WindowsIdentity.GetCurrent()在“立即”窗口中找出当前用户的状态
  2. 确保该用户在 MMC 管理单元中对证书具有完全控制权限(并仔细检查我正在查看它的正确存储)
  3. 授予Everyone用户完全控制权。
  4. 尝试使用和不使用 KeyPassword 创建 CspParameters 对象(您可以在那里看到它的评论)。

我没主意了。该证书是伪造的自签名测试证书,因此与链中的其他证书缺少权限无关。任何帮助,将不胜感激。

更新:

我已经能够通过在此步骤之前修改一些用于安装证书的标志来执行此代码。现在,代码显然成功执行了,但我在 MMC 中看不到任何可见的效果。

4

1 回答 1

4

我或多或少地解决了这个问题。上面列出的管理权限的代码是正确的。有问题的是在添加证书之前启动证书的代码。对此的常识方法如下所示:

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 并重新打开会强制刷新。

于 2016-02-17T15:16:50.780 回答