Я пытаюсь хешировать строку с помощью SHA256, я использую следующий код:
using System;
using System.Security.Cryptography;
using System.Text;
public class Hash
{
public static string getHashSha256(string text)
{
byte[] bytes = Encoding.Unicode.GetBytes(text);
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
}
Однако этот код дает существенно разные результаты по сравнению с php моих друзей, а также с онлайн-генераторами (такими как This generator )
Кто-нибудь знает, в чем ошибка? Разные базы?
Ответы:
Encoding.Unicode
- вводящее в заблуждение название Microsoft для UTF-16 (кодировка с двойной шириной, используемая в мире Windows по историческим причинам, но не используемая кем-либо еще). http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspxЕсли вы проверите свой
bytes
массив, вы увидите, что каждый второй байт равен0x00
(из-за кодировки двойной ширины).Encoding.UTF8.GetBytes
Вместо этого вы должны использовать .Но также вы увидите разные результаты в зависимости от того, считаете ли вы завершающий
'\0'
байт частью данных, которые вы хешируете. Хеширование двух байтов"Hi"
даст другой результат от хеширования трех байтов"Hi"
. Вам нужно будет решить, что вы хотите сделать. (Предположительно вы хотите сделать то, что делает PHP-код вашего друга.)Для текста ASCII
Encoding.UTF8
определенно подойдет. Если вы стремитесь к идеальной совместимости с кодом вашего друга, даже для входных данных, отличных от ASCII, вам лучше попробовать несколько тестовых примеров с символами, отличными от ASCII, такими какé
и,家
и посмотреть, совпадают ли ваши результаты. Если нет, вам нужно выяснить, какую кодировку действительно использует ваш друг; это может быть одна из 8-битных «кодовых страниц», которые были популярны до изобретения Unicode. (Опять же, я думаю, что Windows - основная причина, по которой кому-то все еще нужно беспокоиться о «кодовых страницах».)источник
short
», но не «сортировка по байтам в кодировке UTF16», если только вы не используете систему с прямым порядком байтов, которой нет в Windows.) Однако «сортировка» в Юникоде действительно сложная тема, которую стоит отложить на другой день.У меня также была эта проблема с другим стилем реализации, но я забыл, где я ее взял, так как это было 2 года назад.
static string sha256(string randomString) { var crypt = new SHA256Managed(); string hash = String.Empty; byte[] crypto = crypt.ComputeHash(Encoding.ASCII.GetBytes(randomString)); foreach (byte theByte in crypto) { hash += theByte.ToString("x2"); } return hash; }
Когда я ввожу что-то вроде,
abcdefghi2013
по какой-то причине это дает разные результаты и приводит к ошибкам в моем модуле входа. Затем я попытался изменить код так же, как это было предложено Quuxplusone, и изменил кодировку сASCII
на,UTF8
после чего все заработало !static string sha256(string randomString) { var crypt = new System.Security.Cryptography.SHA256Managed(); var hash = new System.Text.StringBuilder(); byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString)); foreach (byte theByte in crypto) { hash.Append(theByte.ToString("x2")); } return hash.ToString(); }
Еще раз спасибо Quuxplusone за прекрасный и подробный ответ! :)
источник
hash += bit.ToString("x2");
у меня здесь вопрос: я использовалConvert.ToBase64String(byte[] encryptedBytes)
для обратного преобразования байтов в строку. это давало мне другой результат. так в чем разница между этими двумя методами преобразования байтов в строку ..?public static string ComputeSHA256Hash(string text) { using (var sha256 = new SHA256Managed()) { return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", ""); } }
Причина, по которой вы получаете разные результаты, заключается в том, что вы не используете одну и ту же кодировку строк. Ссылка, которую вы помещаете на интерактивный веб-сайт, который вычисляет SHA256, использует кодировку UTF8, а в вашем примере вы использовали кодировку Unicode. Это две разные кодировки, поэтому вы не получите одинаковый результат. В приведенном выше примере вы получаете тот же хэш SHA256 связанного веб-сайта. Вам необходимо использовать ту же кодировку и в PHP.
Абсолютный минимум. Каждый разработчик программного обеспечения должен абсолютно точно знать о Unicode и наборах символов (без оправданий!)
https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/
источник
public string EncryptPassword(string password, string saltorusername) { using (var sha256 = SHA256.Create()) { var saltedPassword = string.Format("{0}{1}", salt, password); byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword); return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes)); } }
источник
В версии PHP вы можете отправить «true» в последнем параметре, но по умолчанию это «false». Следующий алгоритм эквивалентен хеш-функции PHP по умолчанию при передаче sha256 в качестве первого параметра:
public static string GetSha256FromString(string strData) { var message = Encoding.ASCII.GetBytes(strData); SHA256Managed hashString = new SHA256Managed(); string hex = ""; var hashValue = hashString.ComputeHash(message); foreach (byte x in hashValue) { hex += String.Format("{0:x2}", x); } return hex; }
источник
ASCII
иbyte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)
вместо этого.Самый короткий и быстрый способ. Всего 1 строчка!
public static string StringSha256Hash(string text) => string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);
источник
Это работает для меня в .NET Core 3.1.
Но не в .NET 5 preview 7.
using System; using System.Security.Cryptography; using System.Text; namespace PortalAplicaciones.Shared.Models { public class Encriptar { public static string EncriptaPassWord(string Password) { try { SHA256Managed hasher = new SHA256Managed(); byte[] pwdBytes = new UTF8Encoding().GetBytes(Password); byte[] keyBytes = hasher.ComputeHash(pwdBytes); hasher.Dispose(); return Convert.ToBase64String(keyBytes); } catch (Exception ex) { throw new Exception(ex.Message, ex); } } } }
источник