Я создаю простое приложение для доступа к БД, используя C++, и я добавил таблицу пользователей, содержащую: Я БЫ, ПОЛЬЗОВАТЕЛЬ, ПАРОЛЬ и СОЛЬ, и я использую Крипто++ в качестве криптобэкенда. Поэтому я создал эту функцию:
#include "crypto.h"
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <md5.h>
#include <hex.h>
#include <osrng.h>
using namespace std;
using namespace CryptoPP;
string MyCrypto::MD5(const string strMessage)
{
byte arrbyDigest[Weak::MD5::DIGESTSIZE];
Weak::MD5 hash;
hash.CalculateDigest(arrbyDigest, /*(const byte*)*/strMessage.c_str(), strMessage.length());
HexEncoder encoder;
string strOutput;
encoder.Attach(new StringSink(strOutput));
encoder.Put(arrbyDigest, sizeof(arrbyDigest));
encoder.MessageEnd();
return strOutput;
}
string MyCrypto::GenerateSalt(const size_t length /*= 16*/)
{
SecByteBlock arrbySalt(length);
AutoSeededRandomPool asrp;
asrp.GenerateBlock(arrbySalt, length);
string strSalt(arrbySalt);
strSalt.ToAscii();
return strSalt;
}
Пока все хорошо, все работает нормально, пока я не понял, что сгенерированная строка соли может содержать непечатаемые символы даже нулевой завершающий символ
Итак, мои вопросы:
Я делаю это правильно?
Является ли длина соли 16, как я сделал на практике?
Должен ли я шифровать строку соли в База 64, Шестнадцатеричный или оставить ее как простой текст при объединении ее с простой строкой пароля перед хешем MD5?
Должен ли я зашифровать строку соли в База 64, Шестнадцатеричный или оставить ее как простой текст при сохранении в базе данных?
Каковы ваши предложения?
AutoSeededRandomPool создает однородный поток байтов, то есть каждый байт находится в диапазоне [0-255]. Вы можете сохранить его непосредственно в базе данных, используя BLOB, или вы можете закодировать его, используя HexEncoder или Base64Encoder. Кодирование соли не имеет значения, потому что она по-прежнему имеет такое же количество энтропии. И не имеет значения, что вы передаете хеш-функции, если вы делаете это последовательно. Вы можете передавать двоичные данные или закодированные данные. Просто делайте одно и то же все время.
@ЯрославМашко Это ограничит вас солью один для всех ваших пользователей. Фигово. Более того, безопасность, основанная на том, что злоумышленник не знает вашей схемы шифрования, вовсе не является безопасностью. Ответ, который вы, кажется, цитируете, продолжает говорить обо всем этом.





Нет, ты не делаешь это правильно. MD5 — это, вернее, был — криптографически безопасный хэш. Это не применимо напрямую к хеш-паролям. Чтобы хешировать пароли, вам нужен хэш пароля, который содержит случайную соль и коэффициент работы (стоимость или количество итераций, в зависимости от используемого хэша пароля). Примерами этого являются bcrypt, PBKDF2 и более новый Argon2. Здесь — случайная статья, в которой обсуждается использование хэшей паролей.
Что касается кодировки, то я всегда старался придерживаться существующих стандартов там, где они существуют. Для хеширования паролей применимым стандартом является Модульный формат склепа. Если вы разрабатываете новую схему без жестких требований к совместимости, вы также можете использовать Формат хеширования пароля.
Оба используют кодировку тип base 64 в качестве выходного формата для соли и пароля. Примером может служить вывод bcrypt $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy, где 2a указывает bcrypt и формат, 10 — стоимость (коэффициент работы), а N9qo8uLOickgx2ZMRZoMye — кодировка соли по основанию 64; остальное - хэш пароля. Обратите внимание, что между солью и паролем нет разделителя со знаком доллара.
Я взял приведенный выше пример из bcrypt страница Википедии, который является интересной отправной точкой для получения дополнительной информации, включая, возможно, вывод хэша MD5 для crypt (который, как указано, вам не следует использовать).
Чуть не забыл, да, 16 случайных байт/128 бит соли — это множество; никто бы и глазом не моргнул, если бы вы использовали 8 байт, больше 32 байтов - это перебор.
Хэш не является «шифрованием», а MD5 небезопасен. Рассматривали ли вы en.wikipedia.org/wiki/Bcrypt? (Хотя на самом деле в вашем коде или выборе библиотеки нет указаний на то, что вы действительно используете MD5).