У меня есть строковое поле данных из 12 буквенно-цифровых символов (буквы и цифры). Мне нужно выполнить одностороннее хеширование в этом поле по соображениям безопасности. Какой алгоритм мне следует использовать, чтобы избежать коллизий (разные значения хешируются в одно и то же значение) для точной отчетности? Это поможет?
Edit: Here is the code based on suggestions in comments so far:
public static string GetHashedValue(string Input)
{
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(Input);
bytes = new System.Security.Cryptography.SHA512Managed().ComputeHash(bytes);
String output = Convert.ToBase64String(bytes);
return output;
}
Достаточно для чего? Только вы можете сказать нам это, поэтому, боюсь, этот вопрос здесь не по теме.
Достаточно, чтобы избежать столкновений, как я сказал @DavidG
Вероятно, вам следует преобразовать эти байты в строку base64, а не просто в ASCII.Encoding, что приведет к потере данных и, следовательно, вероятность столкновения будет высокой.
Какое значение System.Text.Encoding было бы правильным, чтобы этого избежать, если не ASCII @CetinBasoz? Есть и другие, такие как UTF8, UTF16 и т. д. Мои исходные данные все же буквенно-цифровые. Вот возможные кодировки: ASCII UTF-16 UTF-32 UTF-7 UTF-8
В качестве ответа я добавил, что кодировка base64 предотвратит потерю, и вы можете вернуть байты в том виде, в каком они есть.
хеширование - это больше, чем просто обфускация. Это необратимый, что означает, что после хеширования ни один. Никто больше знает исходное значение.
SHA256 (или лучше SHA512) - это Достаточно, чтобы избежать столкновений, да, но он используется для хеширования, а не для обфускации. Хеширование и обфускация - это разные вещи. Вы не можете восстановить исходное значение из хеша.
Извините, я знаю только термины C# @CetinBasoz. Одна из этих базовых 64? ASCII UTF-16 UTF-32 UTF-7 UTF-8
BitConverter.ToString(bytes).Replace("-", string.Empty) для получения шестнадцатеричного строкового представления, вероятно, тоже подойдет.
Спасибо за информацию @RacilHilan. Мне не нужно восстанавливать значение, поэтому я предполагаю, что технически мне нужен хеш, а не просто обфускация. Хотя технически разве не все хэши тоже будут обфускациями? Хотя не все обфускации - это хеши?
Извините, @JonathonChase ... какую проблему вы решаете с помощью этого кода?
base64 также является термином C# (не только C#, но в любом языке программирования это хорошо известный термин). Вы только посмотрите на мой ответ. Кстати, вы сбили с толку людей, говоря «обфукация». Это термин, который используется для разных целей (например, для запутывания кода).
Обновил мой заголовок @CetinBasoz. Мне все еще нужно знать из этого списка, что будет подходящим: ASCII UTF-16 UTF-32 UTF-7 UTF-8
Никакой алгоритм хеширования не сможет избежать коллизий с помощью отлично. Все, на что вы можете надеяться, - это снизить вероятность. Если вы абсолютно, положительно, должен избегаете коллизий любой ценой, вам необходимо сохранять хеш-значения и проверять их на соответствие тому, что вы сохранили после каждого генерируемого вами хэша, а затем, возможно, добавить уникальный указатель в тех случаях, когда коллизия действительно происходит.
Как насчет этого кода: общедоступная статическая строка GetObfuscatedValue (строка Input) {byte [] bytes = System.Text.Encoding.UTF32.GetBytes (Input); байты = новый System.Security.Cryptography.SHA512Managed (). ComputeHash (байты); Строковый вывод = System.Text.Encoding.UTF32.GetString (байты); возвратный вывод; }
Почему бы вам не прочитать мой ответ и не использовать base64 :)
@CetinBasoz, Джоэл Кохорн в своем ответе показал мне, где использовать Base64.
Храните ли вы пароль или какие-либо конфиденциальные данные (SSN и т. д.)?





Я предлагаю вам получить строку base64, чтобы предотвратить потерю данных, чтобы избежать высокой вероятности столкновения. то есть:
public static string GetHashedValue(string Input)
{
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(Input);
bytes = new System.Security.Cryptography.SHA512Managed().ComputeHash(bytes);
string output = Convert.ToBase64String(bytes);
return output;
}
Обновлено: хеширование является односторонним и идеально подходит, скажем, для хранения паролей. Если вы хотите вернуть исходное значение с помощью ключа, используйте симметричный алгоритм.
Более того, значения bytes могут содержать кучу непечатаемых символов ascii. Base64 определенно подходит.
@JoelCoehoorn, да, говоря "потеря", я имел в виду именно это.
Ооооо, так что вот где использовать Base64. Итак ... Convert.ToBase64String (byte []) лучше, чем System.Text.Encoding.UTF32.GetString (byte []) ??? Прохладный!
@ Infin8Loop, да, конечно. Когда вам нужно сохранить некоторые двоичные данные в виде «строки» (а затем преобразовать их обратно в байты), используйте base64. Все эти кодировки ASCII, UTF8, ... вызовут потерю данных (например, один из байтов в начале может быть шестнадцатеричным 0x0, и вы потеряете остальные байты, если не используете base64).
Как насчет этого для супер-пупер финального кода? общедоступная статическая строка GetHashedValue (строка Input) {byte [] bytes = System.Text.Encoding.UTF32.GetBytes (Input); байты = новый System.Security.Cryptography.SHA512Managed (). ComputeHash (байты); Строковый вывод = Convert.ToBase64String (байты); возвратный вывод; }
@ Infin8Loop, выглядит нормально. Я бы предпочел Unicode, UTF8 или ASCII, но если вы согласны, все должно быть в порядке (кодирование - сложная тема - не уверен, что UTF8 является наиболее универсальным и кроссплатформенным, над моей головой).
UTF8 Должен быть очень надежным. Если вам абсолютно необходима кроссплатформенная языковая и системно-независимая кодировка, вам следует использовать UTF16.
@ErikPhilips, спасибо за информацию. Я подумал, что UTF8 может быть лучше, поскольку многие другие языки, работающие также на других платформах, похоже, отдают предпочтение UTF8. Возможно, я ошибался.
Все благосклонность UTF8, потому что он обратно совместим с ascii и потенциально может быть меньше (вероятно, чаще, чем не на неазиатских языках). Честно говоря, в вашем случае все должно быть хорошо. Если вам интересно, рекомендую прочитать en.wikipedia.org/wiki/Comparison_of_Unicode_encodings
Избежать столкновений - проблема века. Но решения зависят только от того, что вам подходит. Если ваша входная строка является паролем для приложения со списком задач, тогда Sha256 будет достаточно, но если вам нужна действительно надежная защита, вы должны изучить свою проблему и рассказать нам об этом больше.
Я думаю, вы не знакомы с концепцией криптографических хешей.
Крипто-хеш имеет несколько свойств, в том числе (1) устойчивость к прообразу, т. Е. вы не можете эффективно найти исходное значение из хэша и (2) сопротивления столкновениям, т.е. вы не можете эффективно найти пару входов с одним и тем же хешем, а также с учетом входа с хешем, вы не можете эффективно найти другой вход с тем же хешем (слабое и сильное сопротивление столкновениям).
Однако это не означает, что столкновений нет вообще. Должны быть входы с одинаковым хеш-значением, потому что выходные данные имеют конечную длину (256 или 512 бит для sha256 и 512), но входы конечны, но не ограничены, т.е. сколь угодно долго. Вы можете легко увидеть, что входов намного больше, чем выходов, поэтому должны быть конфликты.
Просто их действительно сложно найти, а это значит, что в идеале в случае крипто-хеша лучший метод найти коллизию - это грубая сила, которая невозможна для 256-битного вывода, не говоря уже о 512.
Итак, ответ на ваш вопрос заключается в том, что в случае sha256 или даже sha512 на самом деле В самом деле вряд ли когда-либо обнаружит столкновение пока нет известных атак на эти алгоритмы.
Сейчас есть атаки на sha2, но на самом деле все еще очень маловероятно, что вы обнаружите столкновение. Подробнее см. здесь.
Для многих целей sha2 все еще хорош, для других может и нет.
Обратите внимание, что вопреки другому ответу, одна вещь, для которой sha2 НЕ подходит, - это хеширование паролей.
Можете ли вы объяснить, почему хеширование не подходит для хеширования паролей?
Интересно, потому что это слишком быстро. Слишком легко предварительно вычислить и построить радужные таблицы - на самом деле, радужные таблицы уже доступны, так что вы можете попытаться сломать сопротивление прообразу для многих различных типов входных данных. Например, вы можете просто загрузить базу данных хэшей для всех строк с максимальной длиной 9 символов, содержащих буквенно-цифровые символы. Теперь это неплохо для взлома пароля. :)
О нет, это то, что пароль надежный. Увеличьте количество символов и используйте любые печатные формы, которые вы можете, а также добавьте соли. Для меня это выглядит довольно безопасно. И не только то, что атакованное место могло задушить испытания. В противном случае, что вы предлагаете для паролей? Симметричный алгоритм?
Конечно, нет. Лучшей практикой является функция получения ключа с множеством раундов, например bcrypt или pbkdf2 с таким количеством раундов, что одно вычисление хэша занимает около 0,2-0,3 секунды. Таким образом, он не будет взломан. Соли с обычными хэшами не очень помогут, потому что вычисления по-прежнему быстрые и вычислимые параллельно. Также вы не можете ожидать, что ваши пользователи запомнят пароли из 14+ символов.
О, теперь я вижу путаницу. Вы не говорите, что «хеширование» не подходит для паролей, но говорите, что это специально для «SHA-2». Какой противоположный ответ сказал, что sha2 хорош? Я думал, вы сослались на мой ответ, где я ничего не говорю о выбранном алгоритме.
Что ж, я все еще думаю, что хеша в целом недостаточно для хранения пароля. Функция вывода ключа, такая как pbkdf2 или bcrypt, не является простым хешем, даже если они основаны на хэшах. Но, возможно, это просто путаница между нами двумя. :) Я думаю, что утверждение, что хеши подходят для хранения паролей, немного вводит в заблуждение по причинам, описанным выше.
Я думаю, что большая часть путаницы заключается в том, какова цель. Если цель состоит в том, чтобы создать уникальный хэш, который избегает коллизий, тогда подойдет простая хеш-функция. Если цель состоит в том, чтобы создать уникальный хэш для безопасности, в конечном итоге вам понадобится хороший безопасный хеш, но функция создания хеша (требующая соли и нескольких раундов) намного сложнее.
Да,
SHA256Managedвполне достаточно, можно также использоватьSHA512Managed.