Обновление поля в DataTable при обновлении TextBox

Мне нужно обновить поле в приложении DataTable в С#, когда пользователь изменяет данные.

DataTable — это DataTable в памяти — я сохраняю и загружаю в него любые данные в файл XML (метод writeXML), поэтому базовая база данных отсутствует. Я использую это для хранения некоторой информации о входах в систему, и поэтому у меня есть поле пароля, которое я хочу зашифровать. Это важно, поскольку, когда я запускаю сохранение в XML, в противном случае пароль будет записан в незашифрованном виде.

Я смотрю на это двумя разными способами и был бы признателен за отзыв.

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

    foreach (DataRow row in tmp.Rows)
    {
        row["PW"] = EncryptIt(row["PW"].ToString());
    }
    

    Однако это выглядит несколько небезопасно. Это дало бы мне DataTable в памяти с расшифрованными паролями. Но я полагаю, ничем не отличается от расшифровки паролей по одному при использовании...

  2. Храните пароли в DataTable в памяти в зашифрованном виде. Но когда пользователь использует экран для редактирования записей, я мог бы зашифровать значение, введенное в TextBox после того, как пользователь ввел его. Затем я мог бы также расшифровать значение из DataTable всякий раз, когда мне нужно его использовать. Это позволит сохранить пароли в зашифрованном виде в DataTable, но мне придется расшифровывать их, когда мне нужно их использовать, поэтому я не уверен, что это действительно более безопасно, чем более простой метод, описанный выше.

Что вы думаете о методе 1 и 2 выше?

Метод № 2 выше также вводит некоторые дополнительные вопросы о том, как лучше всего шифровать данные — под этим я подразумеваю использование какого события?

Я играл с EditValueChanged и TextChanged, но они оба срабатывают при каждом изменении символа. Мне также пришлось бы учитывать различные случаи, такие как выход из поля и не выход из поля в случае, когда пользователь меняет поле, а затем просто нажимает кнопку «Сохранить», не выходя из поля.

Как вы собираетесь обновлять базовое поле DataTable, когда пользователь изменяет TextBox, связанный данными с этим полем (через источник привязки)?

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


person G Bradley MacDonald    schedule 01.06.2017    source источник
comment
Не ответ на ваш вопрос, но если вы новичок в хранении паролей, вам обязательно следует указать это и это чтение.   -  person marcushobson    schedule 01.06.2017


Ответы (2)


Я собирался прокомментировать, но решил, что будет лучше ответить, так как я отправляю пример кода.

Гораздо лучший метод обработки хранилища паролей — создать соль, затем использовать ее для хеширования пароля, а затем сохранить соль и хешированный проход в базе данных. Когда пользователь входит в систему, вы получаете соль, хешируете ее ввод, а затем сравниваете с хэшем в базе данных.

    public static string CreateSalt(int size)
    {
        // Generate a cryptographic random number using the cryptographic
        // service provider
        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
        byte[] buff = new byte[size];
        rng.GetBytes(buff);
        // Return a Base64 string representation of the random number
        return Convert.ToBase64String(buff);
    }

    public static string CreatePasswordHash(string pwd, string salt)
    {
        string saltAndPwd = String.Concat(pwd, salt);
        string hashedPwd =
              FormsAuthentication.HashPasswordForStoringInConfigFile(
                                                   saltAndPwd, "SHA1");
        hashedPwd = String.Concat(hashedPwd, salt);
        return hashedPwd;
    }

Это два помощника, которые вам понадобятся. Чтобы создать хешированный пароль (для нового пользователя), вы делаете что-то вроде этого:

var salt = CreateSalt(24);
var passHash = CreatePasswordHash(password, salt);

Опять же, сохраните соль и хешированный проход в базе данных.

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

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

Однако следует отметить, что согласно https://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.hashpasswordforstoringinconfigfile(v=vs.110).aspx метод FormsAuthentication.HashPasswordForStoringInConfigFile устарел, и вы должны проверить http://go.microsoft.com/fwlink/?LinkId=252463 однако у меня нет для вас примера кода (который я могу придумать...). Конечно, если вы используете приложение для настольных компьютеров / Windows Forms, это вам не поможет, но главное:

Хэш-пароль с помощью соли. Никогда не расшифровывайте сохраненный пароль.

person Para    schedule 01.06.2017

Из двух методов, которые вы предлагаете, я бы выбрал второй, если вас беспокоит открытый текст в памяти. Вы также можете рассмотреть возможность хеширования паролей в базе данных. Хеширование — это своего рода одностороннее шифрование, при котором вы всегда сравниваете «зашифрованный» результат и не сможете восстановить исходный пароль.

Есть хорошая статья здесь о хешировании

Объявление для второй части, когда пользователь нажимает кнопку «Сохранить», поле редактирования сначала теряет фокус, поэтому, если вы подписываетесь на событие leave текстового поля, вы должны быть в безопасности.

person Henrik Clausen    schedule 01.06.2017
comment
Здравствуйте, Хенрик, спасибо за быстрый ответ. Вы правы насчет события "Выход"... Теперь, когда я думаю об этом - это очевидно :) - person G Bradley MacDonald; 02.06.2017