SecureString из PasswordBox WPF отличается от созданного вручную - PullRequest
0 голосов
/ 06 мая 2018

У меня есть два приложения:

  1. приложение WPF, которое захватывает пароль с помощью элемента PasswordBox и шифрует строку C #, используя его, и
  2. приложение ASP.NET, которое получает тот же пароль через конфигурацию в виде открытого текста и использует его для расшифровки строки из # 1.

Приложение WPF может прекрасно расшифровывать строку, а приложение ASP.NET - нет. Я убедился, что открытые тексты и соли, используемые при шифровании / дешифровании в обоих приложениях, одинаковы.

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

string Encrypt(string value, SecureString password, string salt)
{
    var temp = Marshal.SecureStringToBSTR(password);
    var lengthInBytes = Marshal.SizeOf(temp);

    // The rest of the encryption code...
}

string Decrypt(string value, SecureString password, string salt)
{
    var temp = Marshal.SecureStringToBSTR(password);
    var lengthInBytes = Marshal.SizeOf(temp);

    // The rest of the decryption code...
}

Здесь нет ошибки: показанные строки в обеих функциях действительно одинаковы, как они, ИМХО, должны быть.

И все же, переменная lengthInBytes внутри Decrypt отличается между приложениями. Это равно 8 в ASP.NET (где он не может расшифровать) и 4 в WPF (где обе функции работают правильно). Открытый текст тестового пароля был «test», если это имеет значение.

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

Приложение WPF захватывает SecureString непосредственно из свойства PasswordBox.SecurePassword. OTOH, ASP.NET создает его, вызывая AppendChar в цикле на свежем SecureString экземпляре. Я знаю, что это не так безопасно, но не было никакой жизнеспособной неинтерактивной альтернативы для этого сценария. Хотя это не относится к делу, я подозреваю, что это может быть частью проблемы. Я просто пока не вижу, как.

Что я пропустил?

FWIW, приложение WPF в настоящее время использует инструмент Obfuscar в своем исполняемом файле ввода. Я еще не пытался отключить это, чтобы увидеть, если это имеет какое-либо значение.

ОБНОВЛЕНИЕ : Вот код, который я использую на стороне ASP.NET для создания SecureString из открытого текста System.String:

using (var secure = new SecureString())
{
    for (var i = 0; i < plaintext.Length; i++)
    {
        secure.AppendChar(plaintext[i]);
    }

    return Decrypt(encrypted, secure, salt);
}

1 Ответ

0 голосов
/ 06 мая 2018

Вы неправильно используете Marshal.SizeOf, чтобы попытаться получить длину строки, но это вернет размер структуры IntPtr. Кроме того, я бы рекомендовал использовать кодировку Unicode, чтобы избежать каких-либо изменений данных из-за кодировки системы:

string Encrypt(string value, SecureString password, string salt)
{
    try
    {

        var temp = Marshal.SecureStringToGlobalAllocUnicode(password);
        var lengthInBytes = sizeof(char) * password.Length;

        // The rest of the encription code...
    }
    finally
    {
        //Cleanup
        Marshal.ZeroFreeGlobalAllocUnicode(temp);
    }
}

string Decrypt(string value, SecureString password, string salt)
{

    try
    {

        var temp = Marshal.SecureStringToGlobalAllocUnicode(password);
        var lengthInBytes = sizeof(char) * password.Length;

        // The rest of the decryption code...
    }
    finally
    {
        //Cleanup
        Marshal.ZeroFreeGlobalAllocUnicode(temp);
    }
}

Всегда не забывайте обнулять память и освобождать ее, иначе цель SecureString будет побеждена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...