Попытка установить разрешения для KeyContainer в C # не имеет никакого эффекта - PullRequest
7 голосов
/ 29 июня 2010

Я использую следующий код в попытке программно разрешить учетной записи 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 из кода?

Ответы [ 2 ]

10 голосов
/ 29 июня 2010

Похоже, вы не звоните 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);
1 голос
/ 19 февраля 2019

Я просто хотел формализовать то, что сказал Джим Т в комментариях, так как это работало на меня.

//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))
    {
    }
}
...