Лучший способ получить значение SecureString

Я пытаюсь создать автоматизированный инструмент, который выходит и проверяет последние транзакции на моем текущем счете (следя за покупками моей жены, смеется). Инструмент отправляет мое имя пользователя и пароль по SSL, а затем очищает содержимое банковской страницы для транзакций. Конечно, все отправляется по SSL, но для того, чтобы автоматизировать его, мне нужно где-то хранить имя пользователя и пароль для банка.

Итак, я начал с кроличьей норы.NET-строк, безопасности и SecureString. Я сделал форму для ввода моего имени пользователя и пароля в SecureString (символ за символом), убедившись, что не использовать ЛЮБЫЕ System.String. Затем я извлекаю char[] из SecureString, получаю из него байт [], обнуляю char[], шифрую байт [] с помощью встроенного в DPAPI и солт-строки, преобразую зашифрованный байт [] в Base64. System.String, обнулить байты [] и сохранить криптостроку в настройках приложения.

Вопрос был в том, как мне вернуть его обратно в данные POST в HttpWebRequest, не делая его System.String. Я придумал следующую функцию (которая также URL кодирует символы без создания строк).

/// <summary>
/// Retrieves, (and then zero's,) a character array from the SecureString.
/// Then optionally URL encodes the characters and returns an encoded byte array.
/// Make sure to zero out the byte array when you're done with it.
/// </summary>
/// <param name="secure">The SecureString to be retrieved.</param>
/// <param name="encodingFormat">The encoding format used to retrieve the byte array. The default is UTF-8.</param>
/// <param name="urlEncode">If true will URL encode characters which are invalid for URL's.</param>
/// <returns></returns>
public static byte[] ToByteArray(this SecureString secure, System.Text.Encoding encodingFormat, bool urlEncode)
{
    if (secure == null) throw new ArgumentNullException("secure");

    if (encodingFormat == null)
        encodingFormat = System.Text.Encoding.UTF8;

    char[] chars = new char[secure.Length];
    byte[] bytesToReturn;

    // copy the SecureString data into an unmanaged char array and get a pointer to it
    IntPtr ptr = Marshal.SecureStringToCoTaskMemUnicode(secure);

    try
    {
        // copy the unmanaged char array into a managed char array
        Marshal.Copy(ptr, chars, 0, secure.Length);
    }
    finally
    {
        Marshal.ZeroFreeCoTaskMemUnicode(ptr);
    }

    if (false == urlEncode)
    {
        bytesToReturn = encodingFormat.GetBytes(chars);
    }
    else
    {
        List<int> unsafeUrlCharIntValues = new List<int>();
        unsafeUrlCharIntValues.AddRange(Enumerable.Range(32, 16)); //   32-47   Reserved Characters:    ' '!?#$%&'()*+,-./
        unsafeUrlCharIntValues.AddRange(Enumerable.Range(58, 7)); //    58-64   Reserved Characters:    :;<=>?@
        unsafeUrlCharIntValues.AddRange(Enumerable.Range(91, 6)); //    91-96   Reserved Characters:    [\]^_`
        unsafeUrlCharIntValues.AddRange(Enumerable.Range(123, 4)); //   123-126 Reserved Characters:    {|}~

        // Get a count of the unsafe URL characters to see if any processing is required and how many extra char's we'll need in the array.
        int unsafeCharCount = 0;
        for (int i = 0; i < chars.Length; i++)
            if (unsafeUrlCharIntValues.Contains((int)chars[i]))
                unsafeCharCount++;

        if (unsafeCharCount < 1)
        {
            bytesToReturn = encodingFormat.GetBytes(chars);
        }
        else
        {
            char[] encodedChars = EncodeChars(chars);
            bytesToReturn = encodingFormat.GetBytes(encodedChars);

            // zero out encoded chars for security
            for (int i = 0; i < encodedChars.Length; i++)
                encodedChars[i] = '\0';
        }
    }

    // zero out chars
    for (int i = 0; i < chars.Length; i++)
        chars[i] = '\0';

    return bytesToReturn;
}

Я обнуляю char[] после того, как я закончу с ними. Я также обнуляю возвращенный байт [] после того, как записал их в поток HttpWebRequest. Это безопасно или GC будет делать копии объектов char[] и byte[]? Это лучше, чем использовать System.String? Я читал другие посты, в которых говорилось, что нужно использовать небезопасный код и делать все в неуправляемой памяти, но мне все же нужно в конце получить байт [] для моего запроса HttpWebRequest.

0 ответов

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