Как мне хешировать эти данные на C#?

У меня есть строковое поле данных из 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;
}

Да, SHA256Managed вполне достаточно, можно также использовать SHA512Managed.

CodeTherapist 16.05.2018 18:38

Достаточно для чего? Только вы можете сказать нам это, поэтому, боюсь, этот вопрос здесь не по теме.

DavidG 16.05.2018 18:39

Достаточно, чтобы избежать столкновений, как я сказал @DavidG

Infin8Loop 16.05.2018 18:40

Вероятно, вам следует преобразовать эти байты в строку base64, а не просто в ASCII.Encoding, что приведет к потере данных и, следовательно, вероятность столкновения будет высокой.

Cetin Basoz 16.05.2018 18:40

Какое значение System.Text.Encoding было бы правильным, чтобы этого избежать, если не ASCII @CetinBasoz? Есть и другие, такие как UTF8, UTF16 и т. д. Мои исходные данные все же буквенно-цифровые. Вот возможные кодировки: ASCII UTF-16 UTF-32 UTF-7 UTF-8

Infin8Loop 16.05.2018 18:41

В качестве ответа я добавил, что кодировка base64 предотвратит потерю, и вы можете вернуть байты в том виде, в каком они есть.

Cetin Basoz 16.05.2018 18:44

хеширование - это больше, чем просто обфускация. Это необратимый, что означает, что после хеширования ни один. Никто больше знает исходное значение.

Joel Coehoorn 16.05.2018 18:44

SHA256 (или лучше SHA512) - это Достаточно, чтобы избежать столкновений, да, но он используется для хеширования, а не для обфускации. Хеширование и обфускация - это разные вещи. Вы не можете восстановить исходное значение из хеша.

Racil Hilan 16.05.2018 18:44

Извините, я знаю только термины C# @CetinBasoz. Одна из этих базовых 64? ASCII UTF-16 UTF-32 UTF-7 UTF-8

Infin8Loop 16.05.2018 18:45
BitConverter.ToString(bytes).Replace("-", string.Empty) для получения шестнадцатеричного строкового представления, вероятно, тоже подойдет.
Jonathon Chase 16.05.2018 18:45

Спасибо за информацию @RacilHilan. Мне не нужно восстанавливать значение, поэтому я предполагаю, что технически мне нужен хеш, а не просто обфускация. Хотя технически разве не все хэши тоже будут обфускациями? Хотя не все обфускации - это хеши?

Infin8Loop 16.05.2018 18:46

Извините, @JonathonChase ... какую проблему вы решаете с помощью этого кода?

Infin8Loop 16.05.2018 18:47

base64 также является термином C# (не только C#, но в любом языке программирования это хорошо известный термин). Вы только посмотрите на мой ответ. Кстати, вы сбили с толку людей, говоря «обфукация». Это термин, который используется для разных целей (например, для запутывания кода).

Cetin Basoz 16.05.2018 18:47

Обновил мой заголовок @CetinBasoz. Мне все еще нужно знать из этого списка, что будет подходящим: ASCII UTF-16 UTF-32 UTF-7 UTF-8

Infin8Loop 16.05.2018 18:49

Никакой алгоритм хеширования не сможет избежать коллизий с помощью отлично. Все, на что вы можете надеяться, - это снизить вероятность. Если вы абсолютно, положительно, должен избегаете коллизий любой ценой, вам необходимо сохранять хеш-значения и проверять их на соответствие тому, что вы сохранили после каждого генерируемого вами хэша, а затем, возможно, добавить уникальный указатель в тех случаях, когда коллизия действительно происходит.

Joel Coehoorn 16.05.2018 18:50

Как насчет этого кода: общедоступная статическая строка GetObfuscatedValue (строка Input) {byte [] bytes = System.Text.Encoding.UTF32.GetBytes (Input); байты = новый System.Security.Cryptography.SHA512Managed (). ComputeHash (байты); Строковый вывод = System.Text.Encoding.UTF32.GetString (байты); возвратный вывод; }

Infin8Loop 16.05.2018 18:51

Почему бы вам не прочитать мой ответ и не использовать base64 :)

Cetin Basoz 16.05.2018 18:51

@CetinBasoz, Джоэл Кохорн в своем ответе показал мне, где использовать Base64.

Infin8Loop 16.05.2018 18:55

Храните ли вы пароль или какие-либо конфиденциальные данные (SSN и т. д.)?

Erik Philips 16.05.2018 19:44
не все ли хэши тоже будут обфускациями? Ну не совсем. Обфускация - это процесс, который делает что-то неясным. Обычно мы используем обфускацию, чтобы другим было сложно перепроектировать наши приложения и украсть наши усилия. С другой стороны, хеширование - это процесс, который делает необратимые уникальные значения в целях безопасности. Одна общая вещь, для которой мы используем хеширование, - это хранение паролей (хотя и с использованием функции получения ключа). Если мы чрезмерно упростим его, мы можем сказать, что обфускация обратима (хотя и трудна), а хеширование - нет. Также хеширование дает уникальный результат, а обфускация - нет.
Racil Hilan 16.05.2018 20:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
20
73
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я предлагаю вам получить строку 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 определенно подходит.

Joel Coehoorn 16.05.2018 18:48

@JoelCoehoorn, да, говоря "потеря", я имел в виду именно это.

Cetin Basoz 16.05.2018 18:50

Ооооо, так что вот где использовать Base64. Итак ... Convert.ToBase64String (byte []) лучше, чем System.Text.Encoding.UTF32.GetString (byte []) ??? Прохладный!

Infin8Loop 16.05.2018 18:53

@ Infin8Loop, да, конечно. Когда вам нужно сохранить некоторые двоичные данные в виде «строки» (а затем преобразовать их обратно в байты), используйте base64. Все эти кодировки ASCII, UTF8, ... вызовут потерю данных (например, один из байтов в начале может быть шестнадцатеричным 0x0, и вы потеряете остальные байты, если не используете base64).

Cetin Basoz 16.05.2018 18:56

Как насчет этого для супер-пупер финального кода? общедоступная статическая строка GetHashedValue (строка Input) {byte [] bytes = System.Text.Encoding.UTF32.GetBytes (Input); байты = новый System.Security.Cryptography.SHA512Managed (). ComputeHash (байты); Строковый вывод = Convert.ToBase64String (байты); возвратный вывод; }

Infin8Loop 16.05.2018 18:58

@ Infin8Loop, выглядит нормально. Я бы предпочел Unicode, UTF8 или ASCII, но если вы согласны, все должно быть в порядке (кодирование - сложная тема - не уверен, что UTF8 является наиболее универсальным и кроссплатформенным, над моей головой).

Cetin Basoz 16.05.2018 19:03

UTF8 Должен быть очень надежным. Если вам абсолютно необходима кроссплатформенная языковая и системно-независимая кодировка, вам следует использовать UTF16.

Erik Philips 16.05.2018 19:10

@ErikPhilips, спасибо за информацию. Я подумал, что UTF8 может быть лучше, поскольку многие другие языки, работающие также на других платформах, похоже, отдают предпочтение UTF8. Возможно, я ошибался.

Cetin Basoz 16.05.2018 19:12

Все благосклонность UTF8, потому что он обратно совместим с ascii и потенциально может быть меньше (вероятно, чаще, чем не на неазиатских языках). Честно говоря, в вашем случае все должно быть хорошо. Если вам интересно, рекомендую прочитать en.wikipedia.org/wiki/Comparison_of_Unicode_encodings

Erik Philips 16.05.2018 19:17

Избежать столкновений - проблема века. Но решения зависят только от того, что вам подходит. Если ваша входная строка является паролем для приложения со списком задач, тогда Sha256 будет достаточно, но если вам нужна действительно надежная защита, вы должны изучить свою проблему и рассказать нам об этом больше.

Я думаю, вы не знакомы с концепцией криптографических хешей.

Крипто-хеш имеет несколько свойств, в том числе (1) устойчивость к прообразу, т. Е. вы не можете эффективно найти исходное значение из хэша и (2) сопротивления столкновениям, т.е. вы не можете эффективно найти пару входов с одним и тем же хешем, а также с учетом входа с хешем, вы не можете эффективно найти другой вход с тем же хешем (слабое и сильное сопротивление столкновениям).

Однако это не означает, что столкновений нет вообще. Должны быть входы с одинаковым хеш-значением, потому что выходные данные имеют конечную длину (256 или 512 бит для sha256 и 512), но входы конечны, но не ограничены, т.е. сколь угодно долго. Вы можете легко увидеть, что входов намного больше, чем выходов, поэтому должны быть конфликты.

Просто их действительно сложно найти, а это значит, что в идеале в случае крипто-хеша лучший метод найти коллизию - это грубая сила, которая невозможна для 256-битного вывода, не говоря уже о 512.

Итак, ответ на ваш вопрос заключается в том, что в случае sha256 или даже sha512 на самом деле В самом деле вряд ли когда-либо обнаружит столкновение пока нет известных атак на эти алгоритмы.

Сейчас есть атаки на sha2, но на самом деле все еще очень маловероятно, что вы обнаружите столкновение. Подробнее см. здесь.

Для многих целей sha2 все еще хорош, для других может и нет.

Обратите внимание, что вопреки другому ответу, одна вещь, для которой sha2 НЕ подходит, - это хеширование паролей.

Можете ли вы объяснить, почему хеширование не подходит для хеширования паролей?

Cetin Basoz 16.05.2018 19:14

Интересно, потому что это слишком быстро. Слишком легко предварительно вычислить и построить радужные таблицы - на самом деле, радужные таблицы уже доступны, так что вы можете попытаться сломать сопротивление прообразу для многих различных типов входных данных. Например, вы можете просто загрузить базу данных хэшей для всех строк с максимальной длиной 9 символов, содержащих буквенно-цифровые символы. Теперь это неплохо для взлома пароля. :)

Gabor Lengyel 16.05.2018 19:17

О нет, это то, что пароль надежный. Увеличьте количество символов и используйте любые печатные формы, которые вы можете, а также добавьте соли. Для меня это выглядит довольно безопасно. И не только то, что атакованное место могло задушить испытания. В противном случае, что вы предлагаете для паролей? Симметричный алгоритм?

Cetin Basoz 16.05.2018 19:25

Конечно, нет. Лучшей практикой является функция получения ключа с множеством раундов, например bcrypt или pbkdf2 с таким количеством раундов, что одно вычисление хэша занимает около 0,2-0,3 секунды. Таким образом, он не будет взломан. Соли с обычными хэшами не очень помогут, потому что вычисления по-прежнему быстрые и вычислимые параллельно. Также вы не можете ожидать, что ваши пользователи запомнят пароли из 14+ символов.

Gabor Lengyel 16.05.2018 19:28

О, теперь я вижу путаницу. Вы не говорите, что «хеширование» не подходит для паролей, но говорите, что это специально для «SHA-2». Какой противоположный ответ сказал, что sha2 хорош? Я думал, вы сослались на мой ответ, где я ничего не говорю о выбранном алгоритме.

Cetin Basoz 16.05.2018 19:34

Что ж, я все еще думаю, что хеша в целом недостаточно для хранения пароля. Функция вывода ключа, такая как pbkdf2 или bcrypt, не является простым хешем, даже если они основаны на хэшах. Но, возможно, это просто путаница между нами двумя. :) Я думаю, что утверждение, что хеши подходят для хранения паролей, немного вводит в заблуждение по причинам, описанным выше.

Gabor Lengyel 16.05.2018 19:40

Я думаю, что большая часть путаницы заключается в том, какова цель. Если цель состоит в том, чтобы создать уникальный хэш, который избегает коллизий, тогда подойдет простая хеш-функция. Если цель состоит в том, чтобы создать уникальный хэш для безопасности, в конечном итоге вам понадобится хороший безопасный хеш, но функция создания хеша (требующая соли и нескольких раундов) намного сложнее.

Erik Philips 16.05.2018 19:43

Другие вопросы по теме