it-roy-ru.com

Принципиальная разница между алгоритмами хеширования и шифрования

Я вижу много путаницы между хэшами и алгоритмами шифрования, и я хотел бы услышать еще несколько советов экспертов о:

  1. Когда использовать хеши против шифрования

  2. Что отличает алгоритм хеширования или шифрования (от теоретического/математического уровня), то есть то, что делает хеши необратимыми (без помощи Радужного дерева)

Вот некоторые похожие SO вопросы, в которых не было столько деталей, сколько я искал:

В чем разница между обфускацией, хешированием и шифрованием?
Разница между шифрованием и хэшированием

482
Kenny Cason

Ну, вы можете посмотреть это в Википедия ... Но так как вам нужно объяснение, я сделаю все возможное здесь:

Хэш-функции

Они обеспечивают отображение между входом произвольной длины и выходом (обычно) фиксированной длины (или меньшей длины). Это может быть что угодно, от простого crc32, до полноценной криптографической хеш-функции, такой как MD5 или SHA1/2/256/512. Дело в том, что происходит одностороннее картирование. Это всегда отображение много: 1 (то есть всегда будут конфликты), поскольку каждая функция выдает меньший вывод, чем она может вводить (если вы подадите каждый возможный файл 1 МБ в MD5, вы получите тонну коллизий).

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

Теперь, если вы хотите декодировать хеш, вам сначала нужно выяснить, как разбить данный хеш на его повторяющиеся состояния (1 возможность для входных данных, меньших, чем размер фрагмента данных, многие для больших входных данных). Тогда вам нужно будет отменить итерацию для каждого состояния. Теперь, чтобы объяснить, почему это ОЧЕНЬ сложно, представьте, что вы пытаетесь вывести a и b из следующей формулы: 10 = a + b. Существует 10 положительных комбинаций a и b, которые могут работать. Теперь зациклитесь на этом несколько раз: tmp = a + b; a = b; b = tmp. За 64 итерации у вас будет более 10 ^ 64 возможностей. И это просто простое дополнение, в котором сохраняется состояние от итерации к итерации. Реальные хеш-функции выполняют намного больше одной операции (MD5 выполняет около 15 операций с 4 переменными состояния). А поскольку следующая итерация зависит от состояния предыдущей, а предыдущая уничтожается при создании текущего состояния, практически невозможно определить входное состояние, которое привело к заданному выходному состоянию (для каждой итерации не меньше). Объедините это с большим количеством задействованных возможностей, и для декодирования даже MD5 потребуется почти бесконечное (но не бесконечное) количество ресурсов. Так много ресурсов, что на самом деле значительно дешевле взломать хэш, если у вас есть представление о размере входных данных (для меньших входных данных), чем даже пытаться декодировать хэш.

Функции шифрования

Они обеспечивают отображение 1: 1 между входом и выходом произвольной длины. И они всегда обратимы. Важно отметить, что это обратимо, используя некоторый метод. И это всегда 1: 1 для данного ключа. Теперь существует несколько пар ввода: ключей, которые могут генерировать один и тот же вывод (фактически, в зависимости от функции шифрования они обычно есть). Хорошие зашифрованные данные неотличимы от случайного шума. Это отличается от хорошего вывода хеша, который всегда имеет согласованный формат.

Случаи применения

Используйте хеш-функцию, когда вы хотите сравнить значение, но не можете сохранить простое представление (по любому количеству причин). Пароли должны очень хорошо подходить к этому варианту использования, так как вы не хотите хранить их в виде текста по соображениям безопасности (и не должны). Но что, если вы хотите проверить файловую систему на наличие пиратских музыкальных файлов? Было бы непрактично хранить 3 МБ на музыкальный файл. Поэтому вместо этого возьмите хеш файла и сохраните его (md5 будет хранить 16 байтов вместо 3 МБ). Таким образом, вы просто хэшируете каждый файл и сравниваете его с хранимой базой данных хэшей (на практике это не так хорошо работает из-за перекодирования, изменения заголовков файлов и т.д., Но это пример использования).

Используйте хэш-функцию, когда вы проверяете достоверность входных данных. Вот для чего они предназначены. Если у вас есть 2 элемента ввода и вы хотите проверить, одинаковы ли они, запустите оба с помощью хеш-функции. Вероятность столкновения астрономически мала для небольших входных размеров (при условии хорошей хэш-функции). Вот почему это рекомендуется для паролей. Для паролей длиной до 32 символов у md5 в 4 раза больше свободного пространства. SHA1 имеет 6-кратное выходное пространство (приблизительно). SHA512 имеет примерно в 16 раз больше места на выходе. Вам не важно, какой пароль был , вам важно, тот ли он, который был сохранен. Вот почему вы должны использовать хеши для паролей.

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

Хеш-функции также отлично подходят для подписи данных. Например, если вы используете HMAC, вы подписываете часть данных, беря хеш данных, объединенных с известным, но не переданным значением (секретным значением). Итак, вы отправляете простой текст и хэш HMAC. Затем получатель просто хэширует представленные данные с известным значением и проверяет, соответствует ли он переданному HMAC. Если это то же самое, вы знаете, что это не было подделано стороной без секретной ценности. Это обычно используется в защищенных системах cookie-файлов в рамках HTTP, а также при передаче сообщений через HTTP, где требуется некоторая гарантия целостности данных.

Примечание к хэшам для паролей:

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

Добавление соли помогает, так как добавляет немного неизвестных данных в хеш. Поэтому вместо того, чтобы находить что-либо, совпадающее с md5(foo), им нужно найти что-то, что при добавлении к известной соли производит md5(foo.salt) (что очень трудно сделать). Но это все еще не решает проблему скорости, так как, если они знают соль, это всего лишь вопрос прохождения словаря.

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

var hash = password + salt;
for (var i = 0; i < 5000; i++) {
    hash = sha512(hash + password + salt);
}

Существуют и другие, более стандартные реализации, такие как PBKDF2 , BCrypt . Но этот метод используется довольно многими системами, связанными с безопасностью (такими как PGP, WPA, Apache и OpenSSL).

Суть в том, что hash(password) недостаточно хорош. hash(password + salt) лучше, но все еще недостаточно хорош ... Используйте механизм растянутого хеша для создания хэшей паролей ...

Еще одна заметка о тривиальном растяжении

Ни при каких обстоятельствах не передавайте выходные данные одного хеша непосредственно обратно в хеш-функцию :

hash = sha512(password + salt); 
for (i = 0; i < 1000; i++) {
    hash = sha512(hash); // <-- Do NOT do this!
}

Причина этого связана с коллизиями. Помните, что все хеш-функции имеют коллизии, потому что возможное выходное пространство (количество возможных выходных данных) меньше, чем входное пространство. Чтобы понять почему, давайте посмотрим, что происходит. Чтобы предварить это, давайте предположим, что вероятность столкновения составляет 0,001% от sha1() (в действительности ( ((=== -)) намного , но для демонстрационных целей).

hash1 = sha1(password + salt);

Теперь hash1 имеет вероятность столкновения 0,001%. Но когда мы делаем следующую hash2 = sha1(hash1);, все коллизии hash1 автоматически становятся коллизиями hash2. Итак, теперь у нас есть коэффициент hash1 на уровне 0,001%, и второй вызов sha1() добавляет к этому. Так что теперь hash2 имеет вероятность столкновения 0,002%. Это в два раза больше шансов! Каждая итерация добавит еще один 0.001% шанс столкновения к результату. Таким образом, при 1000 итерациях вероятность столкновения подскочила с тривиального до 0,001% до 1%. Теперь ухудшение является линейным, и реальные вероятности намного меньше, но эффект тот же (оценка вероятности одного столкновения с md5 составляет около 1/(2128) или 1/(3х1038). Хотя это кажется маленьким, благодаря атака на день рождения на самом деле это не так мало, как кажется).

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

hash = sha512(password + salt);
for (i = 0; i < 1000; i++) {
    hash = sha512(hash + password + salt);
}

Вероятность столкновения такая же, как и у нативной функции sha512. Что ты хочешь? Используйте это вместо этого.

698
ircmaxell

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

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

Множество различных вариантов входов теоретически будут давать идентичные буханки (например, 2 чашки воды и 1 цбп дрожжей дают точно такой же хлеб, как 2,1 стакана воды и 0,9 ц/б дрожжей), но, учитывая один из этих хлебов, вы не можете сказать, именно то, что комбинация входов произвела это.

Шифрование, с другой стороны, может рассматриваться как сейф. Все, что вы положили туда, возвращается, пока у вас есть ключ, с помощью которого он был заперт в первую очередь. Это симметричная операция. При наличии ключа и некоторого ввода вы получите определенный вывод. Учитывая этот вывод и тот же ключ, вы получите исходный ввод. Это отображение 1: 1.

155
Marc B

Используйте хэши, если вы не хотите иметь возможность вернуть исходный ввод, используйте шифрование, когда вы это делаете.

Хэши берут некоторый ввод и превращают его в несколько бит (обычно это число, например, 32-битное целое, 64-битное целое и т.д.). Один и тот же ввод всегда будет давать один и тот же хеш, но вы ПРИНЦИПАЛЬНО теряете информацию в процессе, поэтому вы не можете надежно воспроизвести исходный ввод (однако есть несколько предостережений).

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

Простой пример хеширования

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

Пример:

Input    Hash
0010     0
0011     1
0110     1
1000     0

Обратите внимание, что есть много входных значений, которые приводят к хешу 0, и многие, которые приводят к хешу 1. Если вы знаете, что хэш равен 0, вы не можете точно знать, каким был исходный ввод.

Кстати, этот 1-битный хэш не совсем придуман ... взгляните на бит четности .

Простой пример шифрования

Вы можете зашифровать текст, используя простую замену букв, скажем, если ввод A, вы пишете B. Если ввод B, вы пишете C. До конца алфавита, где, если ввод Z, вы напиши еще раз.

Input   Encrypted
CAT     DBU
Zoo     APP

Как и в простом хэш-примере, этот тип шифрования исторически использовался .

41
Eric J.

Базовый обзор методов хеширования и шифрования/дешифрования.

хеширование:

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

hashing


Шифрование и дешифрование:

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

encryption and decryption


ОБНОВЛЕНИЕ: Для решения вопросов, упомянутых в отредактированном вопросе.

1. Когда использовать хеши против шифрования

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

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


2. Что отличает алгоритм хеширования или шифрования (от теоретического/математического уровня), то есть то, что делает хеши необратимыми (без помощи радужного дерева)

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

Шифрование/дешифрование (обратимое):

Дополнение:

4 + 3 = 7  

Это может быть полностью изменено, беря сумму и вычитая одно из дополнений

7 - 3 = 4     

Умножение:

4 * 5 = 20  

Это можно изменить, взяв продукт и разделив на один из факторов

20 / 4 = 5    

Таким образом, здесь можно предположить, что одним из добавлений/факторов является ключ расшифровки, а результат (7,20) - это зашифрованный текст.


Хеширование (необратимое):

деление по модулю:

22 % 7 = 1   

Это не может быть отменено, потому что нет операции, которую вы можете сделать с частным и дивидендом, чтобы восстановить делитель (или наоборот).

Можете ли вы найти операцию для заполнения, где '?' является?

1  ?  7 = 22  
1  ?  22 = 7

Таким образом, хеш-функции имеют то же математическое качество, что и деление по модулю, и теряют информацию.

кредиты

36
mrsrinivas

Мой один лайнер ... Как правило, интервьюер хотел ответ ниже.

Хеширование - это один из способов. Вы не можете конвертировать ваши данные/строки из хеш-кода.

Шифрование - это 2 способа - вы можете снова расшифровать зашифрованную строку, если у вас есть ключ.

25
Shiv Mohan

A Хеш-функция превращает объем текста переменного размера в текст фиксированного размера.

Hash

Источник: https://en.wikipedia.org/wiki/Hash_function

Давайте посмотрим на это в действии. Я использую php для этого.

HASH:

$str = 'My age is 29';
$hash = hash('sha1', $str);
echo $hash; // OUTPUT: 4d675d9fbefc74a38c89e005f9d776c75d92623e

DEHASH:

SHA1 - односторонний хеш. Что означает, что вы не можете дешифровать хеш. Тем не менее, вы можете перебрать хэш. Пожалуйста, смотрите: https://hashkiller.co.uk/sha1-decrypter.aspx .

MD5, это еще один хеш. Дехашер MD5 можно найти на этом сайте: https://www.md5online.org/ .


Функция шифрования преобразует текст в бессмысленный зашифрованный текст с помощью ключа шифрования и наоборот. enter image description here

Источник: https://en.wikipedia.org/wiki/Encryption

Давайте углубимся в некоторый PHP код, который обрабатывает шифрование.

--- Расширение Mcrypt ---

ENCRYPT:

$cipher = MCRYPT_RIJNDAEL_128;
$key = 'A_KEY';
$data = 'My age is 29';
$mode = MCRYPT_MODE_ECB;

$encryptedData = mcrypt_encrypt($cipher, $key , $data , $mode);
var_dump($encryptedData);

//OUTPUT:
string '„Ùòyªq³¿ì¼üÀpå' (length=16)

Расшифровывать:

$decryptedData = mcrypt_decrypt($cipher, $key , $encryptedData, $mode);
$decryptedData = rtrim($decryptedData, "\0\4"); // Remove the nulls and EOTs at the END
var_dump($decryptedData);

//OUTPUT:
string 'My age is 29' (length=12)

--- Расширение OpenSSL ---

Расширение Mcrypt устарело в версии 7.1. и удалены в php 7.2. Расширение OpenSSL следует использовать в php 7. См. Фрагменты кода ниже:

$key = 'A_KEY';
$data = 'My age is 29';

// ENCRYPT
$encryptedData = openssl_encrypt($data , 'AES-128-CBC', $key, 0, 'IV_init_vector01');
var_dump($encryptedData);

// DECRYPT    
$decryptedData = openssl_decrypt($encryptedData, 'AES-128-CBC', $key, 0, 'IV_init_vector01');
var_dump($decryptedData);

//OUTPUT
string '4RJ8+18YkEd7Xk+tAMLz5Q==' (length=24)
string 'My age is 29' (length=12)
15
Julian

Симметричное шифрование:

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

enter image description here

Асимметричное шифрование:

Асимметричное шифрование также известно как криптография с открытым ключом. Асимметричное шифрование отличается от симметричного шифрования прежде всего тем, что используются два ключа: один для шифрования и один для дешифрования. Наиболее распространенным алгоритмом асимметричного шифрования является RSA.

По сравнению с симметричным шифрованием асимметричное шифрование накладывает большие вычислительные затраты и имеет тенденцию быть намного медленнее. Таким образом, он обычно не используется для защиты данных полезной нагрузки. Вместо этого его основной силой является способность устанавливать безопасный канал через небезопасную среду (например, Интернет). Это достигается путем обмена открытыми ключами, которые могут использоваться только для шифрования данных. Дополнительный закрытый ключ, который никогда не передается, используется для расшифровки.

enter image description here

хэширования:

Наконец, хеширование - это форма криптографической защиты, которая отличается от шифрования. Принимая во внимание, что шифрование - двухэтапный процесс, используемый, чтобы сначала зашифровать и затем расшифровать сообщение, хеширование конденсирует сообщение в необратимое значение фиксированной длины, или хэш. Два наиболее распространенных алгоритма хеширования, встречающихся в сети, это MD5 и SHA-1.

enter image description here

Подробнее читайте здесь: http://packetlife.net/blog/2010/nov/23/symmetric-asymmetric-encryption-hashing/

9
Vahid Farahmandian

Алгоритмы шифрования и хеширования работают аналогичным образом. В каждом случае необходимо создавать путаница и диффузия среди битов. Сложная путаница создает сложные отношения между ключом и зашифрованным текстом и диффузией распространяет информацию каждого бита вокруг.

Многие хеш-функции фактически используют алгоритмы шифрования (или примитивы алгоритмов шифрования. Например, кандидат SHA-3 Skein использует Threefish в качестве базового метода для обработки каждого блока. Разница в том, что вместо сохранения каждого блока зашифрованного текста, они деструктивно, детерминистически объединены в фиксированную длину

4
Justin Morgan
  1. Используйте хэши, когда вам нужно идти только одним путем. Например, для паролей в системе вы используете хеширование, потому что вы всегда будете проверять, чтобы значение, введенное пользователем после хеширования, соответствовало значению в вашем хранилище. С шифрованием вы можете пойти двумя путями.

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

4
hvgotcodes

когда речь идет о безопасности при передаче данных, т. е. при двусторонней связи вы используете шифрование. Все шифрование требует ключа

когда дело доходит до авторизации, вы используете хеширование. В хешировании нет ключа

Хеширование берет любой объем данных (двоичный или текстовый) и создает хэш постоянной длины, представляющий контрольную сумму для данных. Например, хеш может быть 16 байтов. Различные алгоритмы хеширования производят хэши разного размера. Очевидно, что вы не можете заново создать исходные данные из хэша, но вы можете снова хэшировать данные, чтобы увидеть, генерируется ли то же самое значение хэша. Так работают односторонние пароли на основе Unix. Пароль хранится в виде значения хэша, и для входа в систему вводимый вами пароль хэшируется, и значение хэша сравнивается с хэшем реального пароля. Если они совпадают, значит, вы ввели правильный пароль

почему хеширование необратимо:

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

4
ayush