Нужно ли шифровать SecureString при сохранении на диск?

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

Является SecureString лучший подход или я должен использовать ProtectedData просто зашифровать строку?

--EDIT-- Вот тестовый код, который я использовал, чтобы проверить, что SecureString может быть сохранен

        [global::System.Configuration.ApplicationScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public global::System.Security.SecureString Password
        {
            get
            {
                return ((global::System.Security.SecureString)(this["Password"]));
            }
            set { this["Password"] = value; }
        }

        static void Main(string[] args)
        {
            PersistPassword("A-Test-Password");
            Console.WriteLine(ReadPassword());
            Console.ReadLine();
        }

        static void PersistPassword(string Password)
        {
            SecureString ss = new SecureString();
            Password.ToCharArray().ToList().ForEach(ss.AppendChar);
            Settings.Default.Password = ss;
        }

        static string ReadPassword()
        {
            SecureString ss = Settings.Default.Password;
            IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(ss);
            return Marshal.PtrToStringUni(ptr);
        }

1 ответ

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

Если вам нужно, чтобы зашифрованные данные были сохраняемыми (дольше, чем ваша программа существует), вам нужен API защиты данных (DPAPI) и его функция CryptProtectData, которая предоставляется пользователям C# через класс ProtectedData.

SecureString имеет преимущество в том, что он эфемерный; полезный для:

  • пароли
  • номера кредитных карт
  • Номера социального страхования

пока они используются вашей программой, а затем удалены.

DPAPI лучше для длительного хранения. Но остерегайтесь уровней защиты, и вы выбираете тот, который соответствует тому, что вам нужно:

  • только расшифровывается мной
  • только расшифровывается на этом ПК
  • расшифровывается только кем-либо в домене

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

Четыре уровня

  • CryptProtectMemory (SecureString в.NET): полезно только в памяти вашего процесса
  • CryptProtectData (ProtectedData в.NET): шифрует большой массив данных, и вы можете хранить его где угодно (память, реестр, жесткий диск), но вы должны хранить его самостоятельно.
  • CredWrite: шифрует пароль с помощью CryptProtectData и сохраняет его для вас в хранилище паролей Windows (Пуск → Диспетчер учетных данных)
  • CredUIPromptForCredentials/CredUIConfirmCredentials: запрашивать у пользователя пароль, шифровать его и сохранять в хранилище паролей (Пуск → Диспетчер учетных данных) с помощью CredWrite.

Как говорится в MSDN,

Значение экземпляра SecureString автоматически защищается с помощью механизма, поддерживаемого базовой платформой, когда экземпляр инициализируется или когда значение изменяется.

Если вы хотите предоставить механизм, позволяющий хранить его только для чтения после сохранения пароля в securestring, вы можете вызвать метод MarkAsReadonly() в теме.

Для настойчивости вы можете также Hash SecureString и создать соль для этого. Вы можете получить соль для последующего использования, например, для сравнения. Проверьте этот фрагмент кода, который использует соль над Securestring,

Другие вопросы по тегам