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

Jim*_*m T 7 .net c# cryptography rsacryptoserviceprovider dpapi

我正在使用以下代码尝试以编程方式允许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
  )
);
Run Code Online (Sandbox Code Playgroud)

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

但是,使用命令行工具aspnet_regiis做同样的事情,完美地工作:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService"
Run Code Online (Sandbox Code Playgroud)

我正在运行完全管理员权限 - 如果我没有运行这些权限,则抛出异常.我也是最初创建密钥的用户.

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

S-1-5-18         -> LocalSystem
S-1-5-32-544     -> Administrators
S-1-5-5-0-135377 -> MyUser
Run Code Online (Sandbox Code Playgroud)

使用aspnet_regiis,SID,S-1-5-20将添加到此列表中.我无法从代码中影响它.

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

任何想法如何从代码实际影响此ACL列表?

jri*_*sta 10

您似乎没有调用Persist.您对CryptoKeySecurity所做的更改实际上并未立即保存.您需要使用其中一种Persist(...)方法来实际保存更改.

NativeObjectSecurity.Persist方法(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);
Run Code Online (Sandbox Code Playgroud)

  • 这让我走上正轨.上面使用的CryptoKeySecurity属性为null,因此抛出.你可以创建一个新的,但它会删除已经存在的任何权限(这是它的第一个实际效果,所以现在我被锁定在我的主密钥库之外;).但是......如果从密钥库中获取密钥,则通过复制RSA.CspKeyContainerInfo(包括提供程序名称和类型,容器名称和CryptoKeySecurity)中的值来创建新的CspParamters,然后您可以修改它,创建另一个RSA密钥使用cspparameters的对象,瞧,都完成了.简单......? (6认同)