Я предоставлю немного другой взгляд на это.
Я всегда храню соль, смешанную с хешем соли-пароля.
Например, я помещу первую половину соли перед хешем соли, а вторую половину соли после хеша соли. Приложение знает об этой схеме, поэтому может получать эти данные и получать хэш соленого и соленого пароля.
Мое обоснование для этого подхода:
Если пароль / хеш-данные скомпрометированы и попадут в руки злоумышленника, злоумышленник не будет знать, что такое соль при просмотре данных. Таким образом, злоумышленник практически не может выполнить атаку методом "грубой силы", чтобы получить пароль, соответствующий хешу, поскольку он не знает хеш с самого начала и не может узнать, какие части данных являются частями соли, или части хэша salted-пароля ( если он не знает логику аутентификации вашего приложения ).
Если хеш-код с посоленным паролем хранится как есть, то можно выполнить атаку методом «грубой силы», чтобы получить пароль, который при посылке и хешировании дает те же данные, что и хеш-код с посоленным паролем.
Однако, например, даже если хеш-пароль с сохраненным паролем был сохранен как есть, но предварительно добавлен один случайный байт, пока злоумышленник не знает, что этот первый байт должен быть отброшен, это также увеличит сложность атаки. Ваше приложение будет знать, чтобы отбросить первый байт данных при использовании для аутентификации вашего пользователя.
Вывод к этому ..
1) Никогда не храните данные, которые ваше приложение аутентификации использует в точном виде.
2) Если возможно, держите свою логику аутентификации в секрете для дополнительной безопасности.
Иди на шаг дальше ..
Если вы не можете сохранить логику аутентификации вашего приложения в секрете - многие люди знают, как ваши данные хранятся в базе данных. И предположим, что вы решили хранить хеш соленого пароля, смешанный вместе с солью, причем часть соли предшествует хешу соленого пароля, а остальная часть соли добавляет его.
При создании случайной соли вы также можете случайным образом решить, какую долю вашей соли вы будете хранить до / после хэширования соленого пароля.
Например, вы генерируете случайную соль размером 512 байт. Вы добавляете соль к своему паролю и получаете хэш SHA-512 вашего соленого пароля. Вы также генерируете случайное целое число 200. Затем вы сохраняете первые 200 байтов соли, за которыми следует хеш соли с паролем, а затем остаток соли.
При аутентификации ввода пароля пользователя ваше приложение передаст строку и предположит, что первый 1 байт данных - это первый 1 байт соли, за которым следует хеш-код соли. Этот проход не удастся. Приложение будет продолжено с использованием первых 2 байтов данных в качестве первых 2 байтов соли и повторяется до тех пор, пока не будет найден положительный результат после использования первых 200 байтов в качестве первых 200 байтов соли. Если пароль неверный, приложение продолжит пробовать все перестановки, пока они не будут найдены.
Плюсы этого подхода:
Повышенная безопасность - даже если ваша логика аутентификации известна, точная логика неизвестна во время компиляции. Практически невозможно выполнить атаку грубой силой, даже со знанием точной логики. Увеличение длины соли повысит безопасность в дальнейшем.
Минусы этого подхода:
Поскольку точная логика выводится во время выполнения, этот подход очень загружает процессор. Чем больше длина соли, тем интенсивнее этот процесс.
Аутентификация неверных паролей потребует максимальной загрузки процессора. Это может быть непродуктивным для законных запросов, но повышает безопасность против злоумышленников.
Этот подход может быть реализован различными способами и может быть сделан еще более безопасным с использованием солей переменной ширины и / или хешей с солеными паролями.