В файлах Web.config часто содержатся данные, которые нежелательно оставлять в открытом доступе. Например, строки подключения к базе данных, данные регистрации приложения на сторонних ресурсах и т. д. Существует возможность шифровать секции с этими данными.

Для шифрования определенной части Web.config можно использовать как специализированную программу регистрации IIS для ASP.NET (aspnet_regiis.exe), так и шифрование файла прямо из приложения. Расшифровка внутри приложения производится автоматически (конечно, если на машине, производящей выполнение, есть требующиеся ключи).

Примечание. Шифрование Web.config полезно, только если существует вероятность похищения этого файла без доступа к машине. Если злоумышленник имеет доступ к машине, производившей шифрование (что эквивалентно доступу к закрытому ключу), такой способ становится бесполезен, так как становится возможным получить исходную строку с помощью aspnet_regiis.exe.

С помощью командной строки

Создание контейнера ключей

-pc контейнер — создает пару ключей «открытый/закрытый» RSA в заданном контейнере. Этот параметр может иметь следующие модификаторы:

  • -size keySize — задает размер ключа. Значение по умолчанию — 2048 байт
  • -pku —  заменяет пользовательский контейнер на используемый по умолчанию контейнер ключа
  • -exp —  задает, что для закрытых ключей должна быть предусмотрена возможность экспорта
  • -csp provider — задает используемый поставщик контейнера

Импорт ключей

-pi файл контейнера — импортирует пару ключей «открытый/закрытый» RSA в контейнер, заданный параметром container, из заданного XML-файла. Этот параметр может иметь следующие модификаторы:

  • -pku — заменяет контейнер компьютера, используемый по умолчанию пользовательским контейнером
  • -exp — определяет, что закрытые ключи могут быть экспортированы
  • -csp provider —  задает используемый поставщик контейнера

Экспорт ключей

-px файл контейнера — экспортирует пару ключей «открытый/закрытый» RSA из заданного контейнера в заданный XML-файл. Этот параметр может иметь следующие модификаторы:

  • -pku — заменяет контейнер компьютера, используемый по умолчанию пользовательским контейнером
  • -csp provider — задает используемый поставщик контейнера

Удаление ключей

-pz файл контейнера — удаляет указанный контейнер.

Шифрование

C:WindowsMicrosoft.NETFrameworkверсия_framework>aspnet_regiis.exe -pe "connectionStrings" -app "/siteName"

-pe раздел — шифрует указанный раздел конфигурации. Этот параметр может иметь следующие модификаторы:

  • -prov provider — определяет используемого поставщика функций шифрования
  • -app virtualPath — определяет, что шифрование должно выполняться на уровне включенного пути
  • -location subPath —  определяет подкаталог для шифрования
  • -pkm — определяет, что вместо файла Web.config должен шифроваться файл Machine.config

-pef раздел путь к папке проекта  — шифрует заданный раздел конфигурации файла Web.config в заданном физическом (не виртуальном) каталоге.

Расшифровка

C:WindowsMicrosoft.NETFrameworkверсия_framework>aspnet_regiis.exe -pd "connectionStrings" -app "/siteName"

-pd раздел — расшифровывает раздел конфигурации. Этот аргумент может принимать следующие параметры:

  • -app virtualPath — задает, что шифрование должно выполняться на уровне включенного пути
  • -location subPath — задает подкаталог для расшифровки
  • -pkm определяет, что вместо файла Web.config должен быть расшифрован файл Machine.config

-pdf раздел путь к папке проекта — расшифровывает заданный раздел конфигурации файла Web.config в заданном физическом (не виртуальном) каталоге.

Примечание. Следует понимать, что шифрование происходит с использованием закрытого и открытого ключа, которые хранятся в контейнере, поэтому шифрование этим методом либо должно происходить прямо на удаленном сервере, либо после шифрования на локальном компьютере контейнер ключей должен быть экспортирован.

Далее представлен процесс шифрования Web.config из командной строки с последующим экспортированием ключей.

Создаем наш контейнер ключей CustomKeys и разрешаем его экспортирование:

C:...версия_framework>aspnet_regiis -pc “CustomKeys” -exp

Чтобы .NET мог расшифровать файл, следует дать доступ к контейнеру ключей пользователю, от которого производится выполнение приложения:

C:...версия_framework>aspnet_regiis -pa “CustomKeys” "NT AUTHORITYNETWORK SERVICE"

Далее изменяем web.config, добавив в него секцию configProtectedData, где CustomProvider — имя экземпляра класса RSAProtectedConfigurationProvider, которое будет использовано при шифровании:

<configProtectedData>
 <providers>
    <add name="CustomProvider"
    type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration,    Version=2.0.0.0,
    Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
    processorArchitecture=MSIL"
    keyContainerName="CustomKeys"
    useMachineContainer="true" />
 </providers>
</configProtectedData>

Собственно, шифруем:

C:...версия_framework>aspnet_regiis.exe -pef "connectionStrings" "C:Путь_к_папке_с_web.config" -prov "CustomProvider"

Данные в приложении, как мы помним, расшифровываются автоматически.

Далее экспортируем наш файл ключей:

C:...версия_framework>aspnet_regiis.exe -px "CustomKeys" "C:ПутьCustomKeys.xml"-pri

Параметр -pri здесь используется, чтобы убедиться, что информация о закрытом ключе была экспортирована.

Примечание. Чтобы проверить принцип работы на локальном компьютере, можно просто удалить файл ключей командой aspnet_regiis.exe -pz «CustomKeys».

Для импорта копируем на удаленный компьютер наш CustomKeys.xml и выполняем команду:

C:...версия_framework>aspnet_regiis.exe -pi "CustomKeys" "C:ПутьCustomKeys.xml"

Примечание. В примерах секция connectionStrings зашифрована с помощью этого метода, файл ключей CustomKeys.xml находится в папке проекта, импортировать его перед запуском проекта будет хорошей идеей.

Примечание. aspnet_regiis не умеет подгружать сборки самостоятельно, поэтому при попытке зашифровать собственную секцию этим способом будет выдано сообщение об ошибке:

Encrypting configuration section...
Ошибка при создании обработчика раздела конфигурации для socialSettings: Невозможно загрузить файл или сборку "Test" или один из зависимых от них компонентов. Не удается найти указанный файл. (C:ProjectsTestTestweb.config line 8)

Что делать? Применить один из «грязных хаков»:

  1. Скопировать dll-файл в папку, где находится aspnet_regiis
  2. Или добавить сборку в GAC (для этого сборка должна обладать строгим именем — strongly named assemblies):
    gacutil –i C:projectsTestTestbinDebugTest.dll

С помощью приложения

Для шифрования на стороне приложения используем класс WebConfigurationManager.

Пример класса для шифрования секции connectionStrings:

namespace TsSoft.WebSamples.Helpers
{
    using System;
    using System.Configuration;
    using System.Web.Configuration;

    public class EncryptHelper
    {
        private Configuration config;
        private string pathWebConfig;

        public EncryptHelper(string pathWebConfig = "~/")
        {
            this.pathWebConfig = pathWebConfig;
            config = WebConfigurationManager.OpenWebConfiguration(pathWebConfig);
        }

        public string PathWebConfig
        {
            get
            {
                return pathWebConfig;
            }
            set
            {
                pathWebConfig = value;
                config = WebConfigurationManager.OpenWebConfiguration(pathWebConfig);
            }
        }

        public void Encrypt(string encryptSection, string providerName = "RsaProtectedConfigurationProvider")
        {
            var section = GetSection(encryptSection);
            if (section.SectionInformation.IsProtected == true)
            {
                throw new Exception("Section " + encryptSection + " already encrypted.");
            }
            section.SectionInformation.ProtectSection(providerName);
            config.Save();
        }

        public void Decrypt(string decryptSection)
        {
            var section = GetSection(decryptSection);
            if (section.SectionInformation.IsProtected == false)
            {
                throw new Exception("Section " + decryptSection + " already decrypted.");
            }
            section.SectionInformation.UnprotectSection();
            config.Save();
        }

        private ConfigurationSection GetSection(string sectionName)
        {
            if (string.IsNullOrWhiteSpace(sectionName))
            {
                throw new Exception("Section name is null");
            }
            var section = config.GetSection(sectionName);
            if (section == null)
            {
                throw new Exception("Section " + sectionName + " is not defined. Check your Web.config");
            }
            if (section.ElementInformation.IsLocked)
            {
                throw new Exception("Section " + sectionName + " is locked.");
            }
            return section;
        }
    }
}

Использование:

var encryptHelper = new EncryptHelper();
encryptHelper.Encrypt("connectionStrings");
encryptHelper.Decrypt("connectionStrings");

С примерами можно ознакомиться в нашем тестовом приложении на GitHub

В моей предыдущей статье рассмотрены инструменты, автоматизирующие процесс преобразования файлов Web.config для используемой среды.

Источники

Программа регистрации IIS на MSDN
Пошаговое руководство на MSDN
ASP.NET. Сборник рецептов