Как явно преобразовать строку в securestring

Я хочу, чтобы текст, введенный в текстовое поле, был преобразован в securestring в C #.


person Indish Cholleti    schedule 27.03.2012    source источник
comment
Разве PasswordBox и свойство SecurePassword не были бы более подходящими, чем TextBox для ввода пароля? Использование SecureString на самом деле не поможет, если пароль хранится как строковое свойство TextBox ... PasswordBox, с другой стороны, использует SecureString (или аналогичный) для внутренних целей. .   -  person flindeberg    schedule 27.03.2012
comment
@hamad, как указывали другие, здесь лидирует Google. Учитывая, что SO является хорошим ресурсом для этих вещей, мы все сначала щелкаем здесь. Если вас спросят, возвращать людей к Google неконструктивно.   -  person BrainSlugs83    schedule 23.06.2016
comment
Для гуглеров самый лаконичный ответ, который я нашел в комментариях: var output = new SecureString(); input.ToList().ForEach(output.AppendChar);.   -  person BrainSlugs83    schedule 23.06.2016


Ответы (7)


Самый простой подход - перебрать исходную строку и добавлять по одному символу к защищенной строке, например:

var secure = new SecureString();
foreach (char c in textbox1.Text)
{
    secure.AppendChar(c);
}
person Balazs Tihanyi    schedule 27.03.2012
comment
Обратите внимание, что сохранение данных в простой строке перед преобразованием в SecureString превосходит весь смысл использования SecureString. - person Péter Török; 17.02.2014
comment
Здесь лидирует Google. Интернет-ответы, относящиеся к Google, - это самая круговая вещь, которую только можно вообразить. Если вопрос уже задавался по SO, это другое дело (и я уверен, что это так). - person Josh Sutterfield; 25.02.2016
comment
Неужели я единственный, кого сбивает с толку тот факт, что для наиболее распространенного SecureString варианта использования требуется цикл for? - person Jake; 19.08.2016
comment
@ PéterTörök Верно. Однако такие вещи, как конструктор SqlConnection, принимающий параметр SqlCredential, не имеет другого выбора, кроме передачи пароля в виде SecureString, поэтому вы вынуждены использовать небезопасную SecureString таким образом. - person Joe Dyndale; 23.05.2017
comment
@JoeDyndale, лучше сохранить параметр SqlCredential в My.Settings (Настройки приложения / Файл конфигурации) при шифровании файла настроек. так что есть другой вариант. Никогда не используйте закодированный пароль в любом случае, согласно MS, его можно восстановить с помощью некоторых инструментов после развертывания Примечание по безопасности. - person wpcoder; 05.08.2017
comment
@wpcoder Вы имеете в виду, что я изначально, перед развертыванием веб-приложения, должен сериализовать экземпляр SqlCredential в файл настроек, а затем десериализовать его оттуда в живом приложении? Это кажется очень странным. - person Joe Dyndale; 07.08.2017
comment
@JoeDyndale, пожалуйста, найдите время, чтобы прочитать эту статью, она длинная, но важная. Шифрование информации о конфигурации с помощью защищенной конфигурации. - person wpcoder; 07.08.2017
comment
@wpcoder Спасибо. Я бегло просмотрел и обязательно прочту эту статью. Однако на самом деле это не решает проблему, связанную с SecureString ... Когда пароль загружается из web.config, он все равно должен быть сохранен локально, скажем, в строковой переменной перед преобразованием в SecureString. Таким образом, проблема, о которой говорил Петер Торок, все еще актуальна. - person Joe Dyndale; 07.08.2017
comment
@ PéterTörök Не могли бы вы рассказать мне, как это сделать правильно? - person Ozkan; 28.08.2018

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

using System.Security;

/// <summary>
/// Returns a Secure string from the source string
/// </summary>
/// <param name="Source"></param>
/// <returns></returns>
public static SecureString ToSecureString(this string source)
{
    if (string.IsNullOrWhiteSpace(source))
        return null;
    else
    {
        SecureString result = new SecureString();
        foreach (char c in source.ToCharArray())
            result.AppendChar(c);
        return result;
    }
}

а затем позвоните следующим образом:

textbox1.Text.ToSecureString();
person Colin Gardner    schedule 10.07.2013
comment
Обратите внимание, что сохранение данных в простой строке перед преобразованием в SecureString превосходит весь смысл использования SecureString. - person Péter Török; 17.02.2014
comment
Я бы вернул пустой SecureString, если строка равна нулю или пробелу, чтобы представить нулевой или пустой SecureString. NullReferenceExceptions может быть жестоким. - person ; 25.09.2016

Вы должны сделать SecureString только для чтения. Итак, код должен выглядеть так:

static class SecureStringExtensions
{
    public static string ToUnsecureString(this SecureString secureString)
    {
        if (secureString == null) throw new ArgumentNullException("secureString");

        var unmanagedString = IntPtr.Zero;
        try
        {
            unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
            return Marshal.PtrToStringUni(unmanagedString);
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
        }
    }

    public static SecureString ToSecureString(this string unsecureString)
    {
        if (unsecureString == null) throw new ArgumentNullException("unsecureString");

        return unsecureString.Aggregate(new SecureString(), AppendChar, MakeReadOnly);
    }

    private static SecureString MakeReadOnly(SecureString ss)
    {
        ss.MakeReadOnly();
        return ss;
    }

    private static SecureString AppendChar(SecureString ss, char c)
    {
        ss.AppendChar(c);
        return ss;
    }
}
person MovGP0    schedule 18.07.2015
comment
Небольшая настройка вашего кода - использовать nameof (securestring) и nameof (unsecureString) при выдаче исключений ArgumentNullExceptions. В своей реализации я использовал лямбды для AppendChar и MakeReadOnly, но это просто личный вкус;) - person SSX-SL33PY; 03.02.2016
comment
Это было полезно. Сделал кучу мелких исправлений в своей собственной версии, но я ничего не знал о Marshal.SecureStringToGlobalAllocUnicode. -- Спасибо! - person BrainSlugs83; 23.06.2016

Возможно, это немного поздно, но вы можете преобразовать SecureString в String таким образом

using System.Security;
.
.
.
/// <summary>
/// Converts String to SecureString
/// </summary>
/// <param name="input">Input in String</param>
/// <returns>Input in SecureString</returns>
public SecureString String2SecureString(String input) {
    SecureString _output = new SecureString();
    input.ToCharArray().ToList().ForEach((q) => _output.AppendChar(q));
    return _output;
}

хотя это все то же самое, что и ответ Балаша Тиханьи:

Google - ваш друг ...

var secure = new SecureString(); 
foreach(char c in textbox1.Text) 
{
secure.AppendChar(c); 
}
person ParsaG72    schedule 28.09.2015
comment
Вам не нужно .ToCharArray(), так что просто input.ToList().ForEach(q => _output.AppendChar(q)); - person knguyen; 22.10.2015
comment
Ничего себе не знал :) - person ParsaG72; 22.10.2015
comment
@knguyen или еще лучше: input.ToList().ForEach(_output.AppendChar); - person hypehuman; 26.10.2015

Я уверен, что никто не упомянул о конструкторе SecureString, принимающем указатель на массив char.

public static SecureString ToSecureString(this string source)
{
    char[] charArray = source.ToCharArray();
    unsafe
    {
        fixed (char* chars = charArray)
        {
            return new SecureString(chars, charArray.Length);
        }
    }
}

Обратите внимание, что этот код работает только с параметром компилятора /unsafe. Чтобы установить этот параметр, перейдите в свойства проекта, вкладку «Сборка» и установите флажок «Разрешить небезопасный код».

person Szybki    schedule 21.04.2017
comment
Не могу найти эту опцию! где это в Visual Studio 2017? что толку? - person wpcoder; 05.08.2017
comment
@wpcoder Какой у вас проект? Универсальная Windows, классический рабочий стол Windows или что-то еще? - person Szybki; 07.08.2017
comment
Формы Windows, я имею в виду, как добавить /unsafe в vs 2017, и каковы преимущества? - person wpcoder; 07.08.2017
comment
@wpcoder В VS2017 есть почти тот же способ добавления параметра /unsafe, что и в более ранних версиях VS - щелкните правой кнопкой мыши проект WinForms в Project Explorer и выберите Properties или дважды щелкните элемент Properties в проекте WinForms в Project Explorer. Затем выберите вкладку Build и установите флажок Allow unsafe code. Это позволит вам использовать контекст unsafe { }, который требуется для использования указателей в управляемом коде. - person Szybki; 07.08.2017
comment
Спасибо @Szybki, но я не могу найти его в VS2017 CE, в любом случае я получил, каковы преимущества. - person wpcoder; 07.08.2017
comment
@wpcoder what is the use?: если вы обращаетесь к памяти напрямую из кода C # с помощью указателей, вы всегда должны использовать ключевое слово unsafe, а ключевое слово fixed указывает, что его не следует перемещать в памяти. Все это используется, потому что конструктор SecureString ожидает char* (char pointer) - person Jordy van Eijk; 12.06.2018

Примерно то же самое, но короче:

SecureString secureString = new SecureString();
textbox1.Text.ToCharArray().ForEach(c => secureString.AppendChar(c));
person jr_gen    schedule 11.10.2018

используйте это для обработчика событий в текстовом поле:

private void textbox1_TextChanged(object sender, EventArgs e)
    {
    SecureString newSecureTextBox = new SecureString();
        foreach (char c in textbox1.Text.ToCharArray())
        {
        newSecureTextBox.AppendChar(c);
        }
    }

назовите вашу переменную обычно как newSecureTextBox

person superKing    schedule 19.06.2014
comment
Хорошая мысль, но я думаю, вы имели в виду LostFocus, а не TextChanged. Каждый раз, когда нажимается клавиша, срабатывает событие TextChanged, поэтому оно перестраивается каждый раз, как если бы они пытались ввести нажатие клавиши. А почему .ToCharArray()? Вы можете легко получить символы из .Text. - person vapcguy; 25.01.2017