Обычно используемые алгоритмы хэширования паролей работают сегодня так: солить пароль и подавать его в KDF. Например, используя PBKDF2-HMAC-SHA1, процесс хеширования пароля DK = PBKDF2(HMAC, Password, Salt, ...)
. Поскольку HMAC представляет собой двухэтапное хеширование с дополненными клавишами, а SHA1 - последовательность перестановок, сдвигов, вращений и побитовых операций, по сути, весь процесс представляет собой некоторые базовые операции, организованные определенным образом. По сути, не очевидно, насколько сложно их вычислить. Вероятно, поэтому односторонние функции все еще верят, и мы видели, как некоторые исторически важные криптографические хеш-функции стали небезопасными и устарели.
Мне было интересно, можно ли по-новому использовать комплексные задачи NP для хеширования паролей, надеясь дать ему более прочную теоретическую основу. Ключевая идея состоит в том, что P! = NP (если P == NP, тогда нет OWF, поэтому текущие схемы тоже ломаются), поскольку проблема NPC означает, что ответ легко проверить, но сложно вычислить. Это свойство хорошо согласуется с требованиями хеширования паролей. Если мы рассматриваем пароль как ответ на проблему NPC, то мы можем сохранить проблему NPC как хэш пароля для противодействия атакам вне сети: пароль легко проверить, но взломать сложно.
Предостережение заключается в том, что один и тот же пароль может быть сопоставлен с несколькими экземплярами проблемы NPC, вероятно, не все из них трудно решить. В качестве первого шага в этом исследовании я пытался интерпретировать двоичную строку как ответ на проблему 3-SAT и построить экземпляр проблемы 3-SAT, для которой двоичная строка является решением. В самой простой форме двоичная строка имеет 3 бита: x_0, x_1, x_2. Тогда есть 2 ^ 3 == 8 предложений:
000 ( (x_0) v (x_1) v (x_2) )
--------------------------------------
001 ( (x_0) v (x_1) v NOT(x_2) )
010 ( (x_0) v NOT(x_1) v (x_2) )
011 ( (x_0) v NOT(x_1) v NOT(x_2) )
100 ( NOT(x_0) v (x_1) v (x_2) )
101 ( NOT(x_0) v (x_1) v NOT(x_2) )
110 ( NOT(x_0) v NOT(x_1) v (x_2) )
111 ( NOT(x_0) v NOT(x_1) v NOT(x_2) )
Предположим, что двоичная строка равна 000. Тогда только 1 из 8 предложение является ложным (первое). Если мы отбрасываем первое предложение и И остальные 7 предложений, то 000 является решением полученной формулы. Так что, если мы храним формулу, то мы можем проверить 000.
Проблема в том, что для 3-битной строки, если вы видите там 7 различных предложений, вы сразу узнаете, какой из них отсутствует, и это выявит биты.
Позже я решил отбросить 3 из них, оставив только 4, отмеченные 001, 010, 100 и 111. Это иногда приводит к столкновениям, но делает решение задачи менее тривиальным. Столкновения не всегда случаются, но неизвестно, исчезнут ли они, когда на входе будет больше битов, пока неизвестно.
Редактировать. В общем случае, когда двоичная строка может быть любой из (000, 001, ..., 111), все еще есть 8 предложений, где 7 - истина, а 1 - ложь. Выберите 4 предложения, которые дают значение истинности (001, 010, 100, 111). Это отражено в реализации прототипа ниже.
Редактировать. Как показано в ответе @DW ниже, этот метод выбора предложений может по-прежнему приводить к слишком большому количеству предложений в данном наборе переменных, что позволяет быстро сузить их значения. Существуют альтернативные способы выбора предложений среди общих предложений 7 * C (n, 3). Например: выберите другое количество предложений из данного набора переменных и делайте это только для смежных переменных ((x_0, x_1, x_2), (x_1, x_2, x_3), (x_2, x_3, x_4), .. .) и, таким образом, образуют цикл вместо клики. Этот метод, вероятно, не работает, потому что интуитивно вы можете попробовать присвоения, используя индукцию, чтобы проверить, все ли условия могут быть выполнены. Итак, чтобы было проще объяснить общую структуру, давайте просто используем текущий метод.
Количество предложений для n-битной строки равно 4 * C (n, 3) = 4 * n * (n - 1) * (n - 2) / 6 = O (n ^ 3), что означает размер хеш - это полином от размера пароля.
Там есть реализация прототипа в Python здесь . Он генерирует экземпляр проблемы 3-SAT из двоичной строки ввода пользователя.
После этого длинного вступления, наконец, мои вопросы:
Работает ли вышеуказанная конструкция (реализованная в прототипе) как безопасное хеширование паролей или, по крайней мере, выглядит многообещающе, может быть пересмотрена и т. Д.? Если нет, то где это терпит неудачу?
Поскольку у нас есть 7 * C (n, 3) предложений, можно ли найти другой способ создания защищенного экземпляра 3-SAT, пригодного для использования в качестве хэша пароля, возможно, с помощью рандомизации?
Есть ли аналогичные работы, пытающиеся использовать полноту NP для разработки проверенных схем безопасного хеширования паролей, и уже получены некоторые результаты (положительные или отрицательные)? Некоторые вступления и ссылки будут приветствоваться.
Редактировать. Я бы принял ответ @DW, который первым ответил на него и дал отличное представление о структуре проблемы, а также о полезных ресурсах. Представленная здесь схема выбора наивного предложения (реализованная в прототипе Python), похоже, не сработала, поскольку можно быстро сузить назначения переменных в небольших группах. Однако проблема остается открытой, потому что я не видел формальных доказательств того, что такие сокращения NPC-to-PasswordHashing не будут работать вообще. Даже для этой конкретной проблемы сокращения 3-SAT могут быть разные способы выбора предложений, которые я не хочу перечислять здесь. Так что любые обновления и обсуждения по-прежнему очень приветствуются.