SecureString для хранения в памяти и представления паролей? Или что-то другое?

Я пишу небольшую программу для себя, используя С#, которую я могу использовать для хранения моих паролей, а затем извлекать их для просмотра/редактирования.

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

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

Будет ли более безопасный способ сделать это, чем использовать класс SecureString, или SecureString соответствует его имени?

Ответ 1

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

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

Ответ 2

SecureString имеет какой-то способ защитить экземпляр памяти в памяти, но вы должны знать о некоторых существенных недостатках.

  • SecureString может быть извлечен без ключа дешифрования, поэтому любой хакер, достаточно опытный, чтобы получить этот кусок памяти, который можно смело предположить, может легко выполнить эту второстепенную операцию для извлечения строки обычного текста. Рассмотрим простоту SecureStringToBSTR(input);
  • SecureString нужно заполнять символом символьным способом, так как нет свойства .Text Get или Set accessor для использования. В блогах, в том числе MSDN, вы часто увидите код, похожий на следующий:

    public static SecureString StringToSecureString(string input)
    {
        SecureString output = new SecureString();
        int l = input.Length;
        char[] s = input.ToCharArray(0, l);
        foreach (char c in s)
        {
            output.AppendChar(c);
        }
        return output;
    }
    

Значительная проблема с этим кодом заключается в том, что разработчик разрешил строку input когда-либо существовать в памяти в первую очередь. Пользовательский элемент управления или WinForm TextBox PasswordBox, используемый для сбора этого пароля от пользователя, никогда не должен собирать весь пароль за одну операцию, поскольку

  • Хакеры могут получить доступ к памяти напрямую и получить пароль непосредственно из элемента управления в стеке или ввести код для извлечения пароля при создании этого метода.
  • Если ваш последний Dump памяти все еще находится на вашем компьютере с вашего последнего синего экрана, и этот элемент управления был заполнен вашим текстовым паролем, тогда пароль находится в аккуратном маленьком файле, готовом для вашего Hacker, чтобы забрать и использовать на его/ее досуге.

Вместо этого рассмотрите опции, в которых KeyPress используется для извлечения каждого символа от пользователя, иначе WPF PasswordBox поддерживается SecureString по умолчанию, я полагаю (кто-то еще может подтвердить это).

Наконец, есть гораздо более простые способы сбора паролей от таких пользователей, как Key Loggers. Моя рекомендация состоит в том, чтобы рассмотреть ваш демографический, риск воздействия и определить, действительно ли что-то столь же тривиальное, как SecureString.

Ответ 3

SecureString - это именно то, что имя говорит, и вы поняли: он сохраняет строку, также зашифрованную в памяти, так что да, это правильный путь. См. ЗДЕСЬ:

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

Ответ 4

Вы, ребята, делаете этот ПУТЬ слишком сложным. Никто не спросил, был ли это лучший способ решить проблему. Они просто хотят увидеть какой-то рабочий код. Jeez. В этом примере passwordPre - это строка, которая была расшифрована из ресурса (например, файла конфигурации), используя ваш собственный алгоритм дешифрования.

    string passwordPre = DecryptProprietary(objectReferringToPassword);
    char[] passwordChars = passwordPre.ToCharArray();        
    System.Security.SecureString securePassword = new System.Security.SecureString(); // in production, this should probably be a global variable
    foreach (char c in passwordChars)
        securePassword.AppendChar(c);

    string decryptedPassword = new System.Net.NetworkCredential(string.Empty, securePassword).Password; // this is how to convert it to a string for quick usage to access the protected resource

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