Каков формат строки Password Salt для хеша MD5?

Я создаю простое приложение для доступа к БД, используя 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, Шестнадцатеричный или оставить ее как простой текст при сохранении в базе данных?

Каковы ваши предложения?

Хэш не является «шифрованием», а MD5 небезопасен. Рассматривали ли вы en.wikipedia.org/wiki/Bcrypt? (Хотя на самом деле в вашем коде или выборе библиотеки нет указаний на то, что вы действительно используете MD5).

Lightness Races in Orbit 16.02.2019 17:44
stackoverflow.com/q/3782519/560648
Lightness Races in Orbit 16.02.2019 17:47
AutoSeededRandomPool создает однородный поток байтов, то есть каждый байт находится в диапазоне [0-255]. Вы можете сохранить его непосредственно в базе данных, используя BLOB, или вы можете закодировать его, используя HexEncoder или Base64Encoder. Кодирование соли не имеет значения, потому что она по-прежнему имеет такое же количество энтропии. И не имеет значения, что вы передаете хеш-функции, если вы делаете это последовательно. Вы можете передавать двоичные данные или закодированные данные. Просто делайте одно и то же все время.
jww 16.02.2019 18:09

@ЯрославМашко Это ограничит вас солью один для всех ваших пользователей. Фигово. Более того, безопасность, основанная на том, что злоумышленник не знает вашей схемы шифрования, вовсе не является безопасностью. Ответ, который вы, кажется, цитируете, продолжает говорить обо всем этом.

Lightness Races in Orbit 17.02.2019 17:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
1 588
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нет, ты не делаешь это правильно. MD5 — это, вернее, был — криптографически безопасный хэш. Это не применимо напрямую к хеш-паролям. Чтобы хешировать пароли, вам нужен хэш пароля, который содержит случайную соль и коэффициент работы (стоимость или количество итераций, в зависимости от используемого хэша пароля). Примерами этого являются bcrypt, PBKDF2 и более новый Argon2. Здесь — случайная статья, в которой обсуждается использование хэшей паролей.

Что касается кодировки, то я всегда старался придерживаться существующих стандартов там, где они существуют. Для хеширования паролей применимым стандартом является Модульный формат склепа. Если вы разрабатываете новую схему без жестких требований к совместимости, вы также можете использовать Формат хеширования пароля.

Оба используют кодировку тип base 64 в качестве выходного формата для соли и пароля. Примером может служить вывод bcrypt $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy, где 2a указывает bcrypt и формат, 10 — стоимость (коэффициент работы), а N9qo8uLOickgx2ZMRZoMye — кодировка соли по основанию 64; остальное - хэш пароля. Обратите внимание, что между солью и паролем нет разделителя со знаком доллара.

Я взял приведенный выше пример из bcrypt страница Википедии, который является интересной отправной точкой для получения дополнительной информации, включая, возможно, вывод хэша MD5 для crypt (который, как указано, вам не следует использовать).

Чуть не забыл, да, 16 случайных байт/128 бит соли — это множество; никто бы и глазом не моргнул, если бы вы использовали 8 байт, больше 32 байтов - это перебор.

Другие вопросы по теме