Как использовать PBKDF2 для получения ключа шифрования из пароля и затем получить доступ к этому ключу позже без пароля (т.е. с помощью куки)?

Вопрос или проблема

Я разрабатываю приложение для ведения заметок, которое будет хранить заметки и файлы пользователей в зашифрованном виде в базе данных и на Backblaze соответственно. Приложение не будет иметь сквозного шифрования, но данные будут зашифрованы в процессе передачи (с использованием TLS) и в состоянии покоя (AES256 для данных заметок в базе данных и с использованием управляемых клиентом ключей в Backblaze для шифрования файлов). Я хочу зашифровать каждую заметку и файл отдельным ключом шифрования.

Мой план достижения этого на данный момент:

  1. Пользователь предоставляет адрес электронной почты, пароль и deviceId (модель устройства) для конечной точки “Регистрация”
  2. Пароль пользователя хешируется с помощью Bcrypt (хранится в базе данных для “пользователя”)
  3. Генерируется случайная соль (хранится в базе данных для “пользователя”)
  4. Генерируется KEK с помощью PBKDF2 из открытого пароля пользователя и соли
  5. Генерируется криптографически случайный DEK, который шифруется с помощью KEK (хранится в базе данных для “пользователя”)
  6. После успешной регистрации, когда пользователь отправляет “заметку” или “файл”, ключ для этого ресурса выводится из DEK, используя HKDF и UUID ресурса

Я считаю, что описанный выше метод надежен, но он требует пароль для работы. Я создаю мобильное приложение, поэтому хотел бы поддерживать сессию между ним и сервером (используя куки), так что мне нужен способ получить KEK без пароля. Мой текущий план:

  1. Когда пользователь входит в систему, вывести KEK и зашифровать его с помощью криптографически случайного CookieValue
  2. Сохранить зашифрованный KEK в таблице “сессий” в базе данных
  3. Установить куки пользователя на этот CookieValue (установить “HTTPOnly” и “Secure” для куки)
  4. Теперь, когда пользователь предоставляет свои куки, сервер может расшифровать зашифрованный KEK в “сессиях” и получить то, что ему нужно для шифрования/расшифрования данных пользователя

Часть этого процесса, в надежности которой я меньше всего уверен, это использование куки для валидации пользователя и предоставления серверу возможности шифровать/расшифровывать их данные. Есть ли какие-либо недостатки в этом методе? Есть ли лучший подход к любой из частей (особенно к части сессии)?

Ответ или решение

Чтобы создать безопасный механизм, позволяющий извлечь ключ шифрования из пароля, а затем получить доступ к этому ключу позже без пароля (с использованием cookie), можно предложить следующие шаги, уточняющие и расширяющие ваш первоначальный план.

Предложенный метод:

  1. Регистрация пользователя:

    • Пользователь предоставляет электронную почту, пароль и идентификатор устройства для регистрации.
    • Пароль пользователя хешируется с использованием Bcrypt и хранится в базе данных.
    • Генерируется случайная соль, которая также хранится в базе данных для пользователя.
    • С помощью PBKDF2 и пароля пользователя, а также сгенерированной соли создается ключ шифрования для ключей (KEK).
    • Создается криптографически случайный ключ шифрования данных (DEK), который шифруется с использованием KEK и хранится в базе данных для пользователя.
  2. Вход пользователя:

    • При попытке войти пользователь предоставляет свою электронную почту и пароль.
    • Пароль хешируется и сравнивается с хешем, хранящимся в базе данных.
    • Если проверка прошла успешно, генерируется новая случайная соль (Salt), которая используется в PBKDF2 для получения KEK.
  3. Использование cookie для сессий:

    • После успешного входа вам нужно зашифровать KEK с помощью криптографически случайно сгенерированного ключа (сессионного ключа).
    • Сессионный ключ генерируется с помощью, например, AES в режиме GCM, и хранится в базе данных вместе с шифрованным KEK.
    • Создается cookie, содержащий значение сессионного ключа, и ему устанавливаются атрибуты HTTPOnly и Secure.
  4. Расшифровка KEK:

    • При последующих запросах пользователь предоставляет cookie.
    • Сервер извлекает сессионный ключ, соответствующий cookie, и расшифровывает с помощью его зашифрованный KEK.
    • Теперь сервер может использовать KEK для шифрования и расшифровки данных пользователя.

Обсуждение безопасности:

  • Шифрование KEK: Защита KEK от потенциального компрометации путем шифрования сессионным ключом значительно повышает уровень безопасности. Важно, чтобы сессионный ключ имел достаточную длину и был сгенерирован с использованием надежного криптографического генератора.

  • Управление сессиями: Хорошей практикой будет реализовать механизм истечения срока действия для cookies. Это значит, что после определенного времени пользователь должен будет снова ввести свои учетные данные.

  • Уязвимости: Убедитесь, что она защищает от атак, таких как атаки на повторное воспроизведение. Например, при проверке cookie можно добавить метку времени и уникальный идентификатор сессии, чтобы гарантировать, что одно и то же значение cookie не будет использовано более одного раза.

  • Безопасность пароля: Периодически напоминайте пользователям о необходимости изменения пароля и рекомендовать использование многофакторной аутентификации (MFA) для повышения безопасности их учетных записей.

Заключение:

Ваш оригинальный метод выглядит неплохо, однако имеет смысл усиливать безопасность с помощью предложенных дополнений, таких как шифрование KEK и управление сессионными cookies. Следуя этим рекомендациям, вы сможете создать более безопасный механизм управления ключами и обеспечивать желаемую функциональность приложения.

Оцените материал
Добавить комментарий

Капча загружается...