=MD5 -> <>MD5

serverokAsservelat
Дата: 20.02.2010 23:03:59
3 часо мучаюсь с функцией MD5 в SQL.
В коде исполняемого файла сайта вычисляется MD5 и отсылается в качестве параметра в хранимую процедуру. В хранимой процедуре беруться некоторые поля из таблицы, вычисляется их MD5 и сравнивается с входным параметром.

Проверил весь код C#. Ошибок нет. Добрался до хранимой процедуры.
PROCEDURE dbo.ConfirmRegistration
	
	(
	    @id int,
                 @hash char(32)
	)
	
AS
      UPDATE dbo.Table SET 
								Table.position = 'true'
								WHERE Table.id=@id 
								AND 
								UPPER(HashBytes('MD5',(Table.name + Table.password)))=@hash;
	RETURN
Тут вроде также нет проблем. Но, ожидаемый результат выполнения этой хранимой процедуры не тот. Процедура не срабатывает при заведомо верных параметрах.

Я и так, и эдак. А оно, блин, не работает.
Решил спросить на форуме здесь. Выдало подсказки и первый же пост дал решение проблемы - надо знак "=" заменить на "<>" что б получилось так
+ Table.password)))<>@hash;

Но, самое главное, почему это работает, а со знаком "=" - нет, не оговаривалось.
Подскажите, пожалуйста, почему так.
Что отличного в "<>" от "="?
Гавриленко Сергей Алексеевич
Дата: 20.02.2010 23:40:55
Есть подозрение, что вы upper и hashbytes местами перепутали.
serverokAsservelat
Дата: 21.02.2010 12:40:07
Да нет. Вычисляем хеш и только после этого приводим в верхний регистр.
Но даже без Upper не срабатывало.
Гавриленко Сергей Алексеевич
Дата: 21.02.2010 12:41:49
Зачем 16 непонятных байт приводить к верхнему регисту?
Ну и тогда, раз здесь правильно, ошибка в коде c#.
serverokAsservelat
Дата: 21.02.2010 13:36:14
Хорошо, не спорю.
А почему тогда
кусок кода процедуры
HashBytes('MD5', @inputParameter)
выдает результат

"6РJќt9,r{›щz{Л¬ "?

Или я неправильно работаю с функцией HashBytes?!
serverokAsservelat
Дата: 21.02.2010 14:05:17
Ну хорошо, задам вопрос по-другому.

В коде C# берем значение полей формы e-mail и password.
Вычисляем их хеш по алгоритму MD5.

string hash = GetHash(email.Text+password.Text);

public static string GetHash(string s)
    {
        string result = string.Empty;
        byte[] byteValue = Encoding.UTF8.GetBytes(s);

        MD5CryptoServiceProvider cз = new MD5CryptoServiceProvider();
        byte[] byteHash = cз.ComputeHash(byteValue);

        foreach (byte bе in byteHash)
        {
            result += string.Format("{0:x2}", bе);
        }
        return result;
    }

Теперь вызываем хранимую процедуру и передаем ей для сравнения входной параметр @input, значение которого устанавливаем в значение переменной hash (которое только что вычислили).

В хранимой процедуре нам надо сравнить этот параметр с полученным хешем из соответствующих полей. То есть, что-то вроде
...HashBytes('MD5', table.email+table.password)...
.

Вопрос такой теперь. Как мне в хранимой процедуре получить значение хеша такого же типа, который носит входной параметры?
Как вообще применить правильно функцию HashBytes?
serverokAsservelat
Дата: 21.02.2010 15:02:51
Вот, вро де бы нашел преобразование в строчный вид, но все равно выходной код хеша не тот,

SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5', table.email+table.password)), 3, 32)

Из строки "AAAAAA" процедура вычисляет код "c94ee213e7fa6887256d143e924227c4", а код C# из той же строки находит "36d04a9d74392c727b1a9bf97a7bcbac".

Как этих двух зверей помирить?
Antoshka
Дата: 21.02.2010 15:22:05
serverokAsservelat,

проблема в корявом поведении функции hashbytes в sql. И заключается она в неявном переводе хешируемого текста в байты с помощью текущего COLLATION. На C# вы явно конвертируете текст с помощью Encoding.UTF8.GetBytes(), MSSQL же, скорее всего (не знаю ваших настроек) конвертирует текст в ANSI-1251; в итоге хеш-функции получают разную входную последовательность, и, соответственно, генерируют различные дайджесты.

Ну и два способа решения:
1) на C# конвертировать строку в 1251 - чревато потерей данных;
2) передавать hashbytes байтовую строку типа varbinary, а для конвертации в UTF-8 и пр. кодировки написать свои UDF на C#.
Antoshka
Дата: 21.02.2010 15:32:38
Собственно, найти объяснение и решение это глюка удалось только после написания собственных UDF для преобразования UNICODE <-> BYTES
serverokAsservelat
Дата: 21.02.2010 15:34:17
А можно пример кода, если можно, конечно. И так спасибо за подсказку. А то голова уже вспухла.