У меня работает приложение C # с аутентификацией пользователя. Я шифрую пароли с помощью класса SHA1Managed, используя Encoding.Unicode. Сейчас мы разрабатываем новое веб-приложение на PHP, и кажется, что метод PHP sha1 использует ASCII, поэтому зашифрованные пароли немного отличаются.
Я не могу изменить свой код C #, так как он работает на нескольких разных серверах, и все пароли пользователей уже зашифрованы. Это нельзя изменить, поскольку это будет означать, что все пользователи будут спрашивать их пароли (что невозможно).
Я ознакомился со следующими решениями, однако не могу решить с ними свою проблему:
- C # SHA-1 против PHP SHA-1 ... Различные результаты? В этом они предлагают использовать ASCIIEncoding. Однако, как я уже говорил ранее, это нельзя изменить.
- SHA1: различные результаты для PHP и C # и Создание хеша PHP UTF-16 SHA1 для соответствия методу C # они используют кодировку base64, и это несовместимо с моей кодировкой C # (я думаю)
- php эквивалентно следующему коду шифрования sha1 c # этот код также использует ASCIIEncoding.
Это мой код C #, который НЕ МОЖЕТ быть изменен:
byte[] msgBytes = Encoding.Unicode.GetBytes(data);
SHA1Managed sha1 = new SHA1Managed();
byte[] hashBytes = sha1.ComputeHash(msgBytes);
StringBuilder hashRet = new StringBuilder("");
foreach (byte b in hashBytes)
hashRet.AppendFormat("{0:X}", b);
return hashRet.ToString();
Это код PHP, реализованный до сих пор:
$str=mb_convert_encoding($password.$SALT, 'UTF-16LE');
$result=strtoupper(sha1($str));
Результат, полученный для строки примера "1981 "в C # D4CEDCADB729F37C30EBF41BC8F2929AF526AD3
В PHP я получаю: D4CEDCADB729F37C30EBF41BC8F29209AF526AD3
Как можно видеть, единственная разница между каждым из 0 - это 0 символов. Это происходит во всех строках, но 0 появляется в разных местах.
РЕДАКТИРОВАТЬ
Как указано https://stackoverflow.com/users/1839439/dharman, результаты не могут быть воспроизведены точно так, какмоя строка имеет сольОднако результаты должны отличаться даже без соли.
РЕШЕНИЕ Пользователь дал предложение, которое решило мою проблему. К сожалению, он удалил ответ, прежде чем я смог опубликовать, что он работал. Проблема в C #, когда я анализирую байты в строку в StringBuilder. Формат: {0: X}, и любой начальный 0 в байте игнорируется. Например, 01 будет проанализирован как 1, 0D будет проанализирован как D.
Поэтому мне пришлось перебирать пары результатов, полученных в PHP, и удалять там начальные нули.
Окончательный код в PHP выглядит следующим образом:
$str=mb_convert_encoding($password.$SALT, 'UTF-16LE');
$result=strtoupper(sha1($str));
$array = str_split($result, 2);
foreach ($array as &$valor) {
$valor = ltrim($valor, '0');
}
unset($valor);
$result = implode($array);