Грокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих - Адитья Бхаргава
Для каждой строки алгоритм SHA генерирует свой уникальный хеш-код.
примечание
Хеш-коды SHA достаточно длинные. Здесь приводится только начало.
Алгоритм SHA позволяет определить, совпадают ли два файла. Такая возможность особенно полезна для очень больших файлов. Допустим, у вас имеется 4-гигабайтный файл и вы хотите проверить, хранится ли у вашего друга точно такой же файл. Вам не придется пересылать большой файл по электронной почте; вместо этого можно вычислить хеш-коды SHA двух файлов и сравнить их.
Проверка паролей
Алгоритм SHA также может использоваться для сравнения строк при отсутствии информации об исходной строке. Например, только представьте, что сервис Gmail атакован хакерами! Ваш пароль стал добычей злоумышленников? А вот и нет. Google хранит не исходный пароль, а только хеш-код пароля по алгоритму SHA! Когда вы вводите пароль, Google хеширует его и сравнивает результат с хеш-кодом, хранящимся в базе данных.
Сравниваются только хеш-коды — хранить пароль не нужно! Алгоритм SHA очень часто используются для хеширования паролей. Хеширование является односторонним: вы можете получить хеш-код строки…
…но не сможете восстановить исходную строку по хеш-коду:
Это означает, что даже если злоумышленник похитит хеш-коды SHA с серверов Gmail, он не сможет по ним восстановить исходные пароли! Пароль можно преобразовать в хеш, но не наоборот.
Под термином SHA скрывается целое семейство алгоритмов: SHA-0, SHA-1, SHA-2 и SHA-3. На момент написания книги в алгоритмах SHA-0 и SHA-1 были обнаружены слабости. Если вы применяете алгоритм SHA для хеширования паролей, выбирайте SHA-2 или SHA-3. В настоящее время «золотым стандартом» хеширования паролей считается функция bcrypt (хотя идеальной защиты не бывает).
Локально-чувствительное хеширование
У хеширования SHA есть еще одна важная особенность: оно является локально-нечувствительным. Предположим, имеется строка, для которой генерируется хеш-код:
Если изменить в строке всего один символ, а потом сгенерировать хеш заново, строка полностью изменяется!
И это хорошо, потому что сравнение хешей не позволит атакующему определить, насколько он близок к взлому пароля.
Иногда требуется обратный результат: локально-чувствительная функция хеширования. Здесь на помощь приходит алгоритм Simhash. При незначительном изменении строки Simhash генерирует хеш-код, который почти не отличается от исходного. Это позволяет сравнивать хеш-коды и определять, насколько похожи две строки, — весьма полезная возможность!
• Google использует Simhash для выявления дубликатов в процессе индексирования.
• Преподаватель может использовать Simhash для обнаружения плагиата (копирования рефератов из Интернета).
• Scribd позволяет пользователям загружать документы или книги, чтобы они стали доступны для других пользователей. Но Scribd не хочет, чтобы пользователи размещали информацию, защищенную авторским правом! С помощью Simhash сайт может обнаружить, что отправленная информация похожа на книгу о Гарри Поттере, и при обнаружении сходства автоматически запретить ее размещение.
Simhash используется для выявления сходства между фрагментами текста.
Обмен ключами Диффи—Хеллмана
Алгоритм Диффи—Хеллмана заслуживает упоминания, потому что он изящно решает давно известную задачу. Как зашифровать сообщение так, чтобы его мог прочитать только тот человек, которому адресовано сообщение?
Проще всего определить подстановочный шифр: a = 1, b = 2 и т.д. Если после этого я отправлю вам сообщение «4,15,7», вы сможете преобразовать его в «d,o,g». Но чтобы эта схема сработала, необходимо согласовать шифр между сторонами. Договориться о шифре по электронной почте невозможно, потому что злоумышленник может перехватить сообщение, узнать шифр и расшифровать сообщения. Даже если передать шифр при личной встрече, злоумышленник может угадать шифр, если он достаточно прост. Значит, шифр придется ежедневно менять. Но тогда нам придется ежедневно проводить личные встречи для изменения шифра!
Даже если вам удастся ежедневно изменять шифр, подобные простые шифры достаточно легко взламываются методом грубой силы. Допустим, я вижу сообщение «9,6,13,13,16 24,16,19,13,5». Я предполагаю, что при шифровании используется подстановка a = 1, b = 2 и т.д.
Бессмыслица. Пробуем a = 2, b = 3 и т.д.
Сработало! Подобные простые шифры взламываются достаточно легко. Во Вторую мировую войну в Германии использовался намного более сложный шифр, но и он был взломан.
Алгоритм Диффи—Хеллмана решает обе проблемы:
• знание шифра обеими сторонами не обязательно. Следовательно, им не придется встречаться и согласовывать шифр;
• расшифровать зашифрованные сообщения чрезвычайно сложно.
Алгоритм Диффи—Хеллмана использует два ключа: открытый и закрытый. Открытый ключ известен обеим сторонам. Его можно опубликовать на сайте, отправить электронной почтой друзьям и вообще сделать с ним все, что вам заблагорассудится. Его не нужно скрывать. Когда другая сторона захочет отправить вам сообщение, она зашифрует его с применением открытого ключа. Зашифрованное сообщение можно расшифровать только с закрытым ключом. При условии, что вы являетесь единственным владельцем закрытого ключа, никто другой расшифровать сообщение не сможет!
Алгоритм Диффи—Хеллмана продолжает применяться на практике вместе с его наследником RSA. Если вы интересуетесь криптографией, алгоритм Диффи—Хеллмана станет хорошей отправной точкой: он элегантен и не особо сложен.
Линейное программирование
Самое лучшее я приберег напоследок. Линейное программирование — одна из самых интересных областей, которые мне известны.
Линейное программирование используется для максимизации некоторой характеристики при заданных ограничениях. Предположим, ваша компания выпускает два продукта: рубашки и сумки. На рубашку требуется 1 м ткани и 5 пуговиц. На изготовление сумки необходимо 2 м ткани и 2 пуговицы.