Отладка сбоя хеширования на стороне SQL

c# asp.net sql-server

59 просмотра

1 ответ

Я пытаюсь заставить хеширование работать для паролей. Они в настоящее время несоленые для целей отладки.

В настоящее время я использую алгоритм хэширования SHA1.

Моя таблица (называется Users) состоит из:

  • [phone] varchar(32)
  • [password] binary(20)

Чтобы заполнить мою базу данных, я использую этот запрос:

DELETE FROM Users

INSERT INTO Users (phone, password)
VALUES ('0526487612', HASHBYTES(SHA1, 'admin123'))

Когда я вхожу, я делаю это:

command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Users WHERE phone=@UName AND password=HASHBYTES('SHA1', @PWord)";

command.Parameters.AddWithValue("@UName", username);
command.Parameters.AddWithValue("@PWord", password);

reader = command.ExecuteReader();

if (reader.HasRows)
{
    // ...
}

Когда я пытаюсь войти в систему (с именем пользователя 0526487612и паролем admin123), он никогда не вводится if(...)(то есть читатель не находит строк, соответствующих запросу).

Все работает, если я не хеширую пароль - значит, проблема не в другом месте.

Я попытался использовать другой алгоритм хеширования ( SHA2_256) и соответственно изменить тип данных SQL Server ( binary(32)), но результат тот же.

Я использую Microsoft SQL Server 2014; и я понятия не имею, как отладить это дальше.

Автор: Ivan Rubinson Источник Размещён: 08.11.2019 11:06

Ответы (1)


3 плюса

Решение

Моя личная ставка заключается в том, что когда вы запускаете свой запрос непосредственно из SQL Server Management Studio и запускаете следующую инструкцию:

DELETE FROM Users;
INSERT INTO Users (phone, password)
VALUES ('0526487612', HASHBYTES('SHA1', 'admin123'));

Ваш пароль ( admin123) является VARCHAR. Теперь, когда вы выполняете свой код, он не выполняется так:

SELECT * FROM Users WHERE phone=@UName AND password=HASHBYTES('SHA1', @PWord);

Вместо этого он выполняет этот оператор (ваш параметр отправляется как NVARCHAR):

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';

Кастинг @p1(ваш пароль) так же VARCHARрешает проблему.

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';

Выполнение этого доказывает, что NVARCHARвыводит другой двоичный файл:

SELECT HASHBYTES('SHA1', 'admin123') AS VarcharSHA1
    , HASHBYTES('SHA1', N'admin123') AS nVarcharSHA1;

Результат:

VarcharSHA1                                 nVarcharSHA1
--------------------------------------------------------------------------------------
0xF865B53623B121FD34EE5426C792E5C33AF8C227  0xB7BC3A1B04D9E165C6762B0A1CDE5226DF5B6A6A

Полный пример:

IF OBJECT_ID('Users', 'U') IS NOT NULL
    DROP TABLE Users;

CREATE TABLE Users
(
    [phone] VARCHAR(30)
    , [password] BINARY(20)
);

INSERT INTO Users ([phone], [password])
VALUES ('0526487612', HASHBYTES('SHA1', 'admin123'));

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';
-- Doesn't bring result back

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';
-- Brings results back

TRUNCATE TABLE Users;
INSERT INTO Users ([phone], [password])
VALUES ('0526487612', HASHBYTES('SHA1', N'admin123'));
                                  --    ^
                                  --    |
                                  -- Notice this

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', @p1)'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';
-- Brings results back

EXEC sp_executesql N'SELECT * FROM Users WHERE phone=@p0 AND password=HASHBYTES(''SHA1'', CAST(@p1 AS VARCHAR(30)))'
    , N'@p0 NVARCHAR(100), @p1 NVARCHAR(100)'
    , @p0 = N'0526487612'
    , @p1 = N'admin123';
-- Doesn't bring result back

Итак, я указал на проблему, теперь вам решать, как ее исправить. Либо всегда VARCHARприменяйте свой пароль как, либо просто используйте юникод-эквивалент при его хешировании.

Обновить

Таким образом, очевидно, что вам не нужно так вставлять свой пароль и хэшировать его как NVARCHAR, но вы должны слегка изменить свой код на c #, чтобы передать желаемый тип данных значения, а не тип данных, который ADO.NET выбирает сам по себе. Пожалуйста, прочитайте эту статью: Можем ли мы прекратить использовать AddWithValue () уже? для дополнительной информации.

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

command = connection.CreateCommand();
command.CommandText = @"
  SELECT *
  FROM Users
  WHERE phone = @UName
    AND password = HASHBYTES('SHA1', @PWord)";

//Add parameters like that and it will pass in correct data type
command.Parameters.Add("@UName", SqlDbType.VarChar, 50).Value = username;
command.Parameters.Add("@PWord", SqlDbType.VarChar, 50).Value = password;

//command.Parameters.AddWithValue("@UName", username);
//command.Parameters.AddWithValue("@PWord", password);

reader = command.ExecuteReader();

if (reader.HasRows)
{
    // ...
}
Автор: Evaldas Buinauskas Размещён: 20.08.2016 09:39
Вопросы из категории :
32x32