尝试在 C# 中设置 KeyContainer 的权限没有效果

发布于 2024-09-07 17:10:09 字数 1058 浏览 4 评论 0原文

我正在使用以下代码尝试以编程方式允许 NetworkService 帐户访问密钥:

var RSA = new RSACryptoServiceProvider(
   new CspParameters() { 
     KeyContainerName = "MyEncryptionKey", 
     Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore 
});

RSA.CspKeyContainerInfo.CryptoKeySecurity.AddAccessRule(
  new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null),
    CryptoKeyRights.GenericAll,
    AccessControlType.Allow
  )
);

此代码运行时没有错误,但对密钥容器的权限没有影响。

但是,使用命令行工具 aspnet_regiis 做同样的事情,效果很好:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService"

我正在以完全管理员权限运行 - 如果我不以这些权限运行,则会引发异常。我也以最初创建密钥的用户身份运行。

密钥容器始终具有以下访问规则:

S-1-5-18         -> LocalSystem
S-1-5-32-544     -> Administrators
S-1-5-5-0-135377 -> MyUser

对于 aspnet_regiis,SID S-1-5-20 将添加到此列表中。我无法通过代码影响它。

我尝试从 sid 以字符串格式创建安全标识符,并使用 SetAccessRule 而不是 AddAccessRule。

有什么想法如何从代码中实际影响此 ACL 列表吗?

I'm using the following code in an attempt to programatically allow the NetworkService account to have access to a key:

var RSA = new RSACryptoServiceProvider(
   new CspParameters() { 
     KeyContainerName = "MyEncryptionKey", 
     Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore 
});

RSA.CspKeyContainerInfo.CryptoKeySecurity.AddAccessRule(
  new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null),
    CryptoKeyRights.GenericAll,
    AccessControlType.Allow
  )
);

This code runs without error, but has no effect on the key container's permissions.

However, using the commandline tool aspnet_regiis to do the same thing, works perfectly:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService"

I'm running with full admin rights - if I don't run with those rights, then an exception is thrown. I'm also running as the user that initially created the key.

The key container always has the following access rules:

S-1-5-18         -> LocalSystem
S-1-5-32-544     -> Administrators
S-1-5-5-0-135377 -> MyUser

With aspnet_regiis, the SID, S-1-5-20 gets added to this list. I can't affect it from code.

I've tried creating the security identifier from the sid in string format, as well as using SetAccessRule instead of AddAccessRule.

Any ideas how to actually affect this ACL list from code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故事和酒 2024-09-14 17:10:16

我只是想正式确定 Jim T 在评论中所说的内容,因为它对我有用。

//Read the current settings
CspParameters csp = new CspParameters(PROVIDER_RSA_FULL)
{
    KeyContainerName = container,
    Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey
};
//Retrieve Current Settings
using (var rsa = new RSACryptoServiceProvider(csp))
{
    var ci = rsa.CspKeyContainerInfo;

    //Create new settings and copy values over
    CspParameters csp2 = new CspParameters(PROVIDER_RSA_FULL)
    {
        KeyContainerName = container,
        Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey,
        CryptoKeySecurity = ci.CryptoKeySecurity,
        ProviderName = ci.ProviderName,
        ProviderType = ci.ProviderType
    };
    //Add Permissions
    csp2.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(securityIdentifier, CryptoKeyRights.FullControl, AccessControlType.Allow));

    //Save settings
    using (var rsa2 = new RSACryptoServiceProvider(csp2))
    {
    }
}

I just wanted to formalize what Jim T stated in the comments since it worked for me.

//Read the current settings
CspParameters csp = new CspParameters(PROVIDER_RSA_FULL)
{
    KeyContainerName = container,
    Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey
};
//Retrieve Current Settings
using (var rsa = new RSACryptoServiceProvider(csp))
{
    var ci = rsa.CspKeyContainerInfo;

    //Create new settings and copy values over
    CspParameters csp2 = new CspParameters(PROVIDER_RSA_FULL)
    {
        KeyContainerName = container,
        Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey,
        CryptoKeySecurity = ci.CryptoKeySecurity,
        ProviderName = ci.ProviderName,
        ProviderType = ci.ProviderType
    };
    //Add Permissions
    csp2.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(securityIdentifier, CryptoKeyRights.FullControl, AccessControlType.Allow));

    //Save settings
    using (var rsa2 = new RSACryptoServiceProvider(csp2))
    {
    }
}
风和你 2024-09-14 17:10:15

你似乎没有呼叫“坚持”。您对 CryptoKeySecurity 所做的更改实际上不会立即保存。您需要使用 Persist(...) 方法之一来实际保存更改。

NativeObjectSecurity.Persist Method (String, AccessControlSections)

这些 API 似乎遵循一种相当复杂的修改方法。您需要首先创建 CspParameters,应用必要的更改,然后根据这些参数构造提供程序。构造会调用容器上的更新。

var params = new CspParameters
{
     KeyContainerName = "MyEncryptionKey", 
     Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore    
};

params.CryptoKeySecurity.AddAccessRule(
  new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null),
    CryptoKeyRights.GenericAll,
    AccessControlType.Allow
  )
);

var RSA = new RSACryptoServiceProvider(params);

You do not appear to be calling Persist. The changes you make to the CryptoKeySecurity do not actually get saved immediately. You need to use one of the Persist(...) methods to actually save the changes.

NativeObjectSecurity.Persist Method (String, AccessControlSections)

It seems these API's follow a rather convoluted approach to modification. You need to create a CspParameters first, apply the necessary changes, then construct the provider from those parameters. Construction invokes an update on the container.

var params = new CspParameters
{
     KeyContainerName = "MyEncryptionKey", 
     Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore    
};

params.CryptoKeySecurity.AddAccessRule(
  new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null),
    CryptoKeyRights.GenericAll,
    AccessControlType.Allow
  )
);

var RSA = new RSACryptoServiceProvider(params);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文