Создание безопасной веб-системы управления паролями с возможностью обмена данными между пользователями

Заранее прошу прощения за входящий Wall-O-Text . Это (по крайней мере, для меня) довольно сложная проблема, над которой я довольно много подумал. Вы можете прочитать мой вопрос, а также увидеть тестовую реализацию на Ruby (очень наспех построенную, без поддержки базы данных и, вероятно, очень некрасивую) в этом GitHub Gist , если вам так хочется.


Введение

Представьте, что нужно было создать веб-систему управления паролями. Это (по крайней мере, для меня) довольно сложная проблема, над которой я довольно много подумал. Вы можете прочитать мой вопрос, а также увидеть тестовую реализацию на Ruby (очень наспех построенную, без поддержки базы данных и, вероятно, очень некрасивую) в этом GitHub Gist , если вам так хочется.


Введение

Представьте, что нужно было создать веб-систему управления паролями. Это (по крайней мере, для меня) довольно сложная проблема, над которой я довольно много подумал. Вы можете прочитать мой вопрос, а также увидеть тестовую реализацию на Ruby (очень наспех построенную, без поддержки базы данных и, вероятно, очень некрасивую) в этом GitHub Gist , если вам так хочется.


Введение

Представьте, что нужно было создать веб-систему управления паролями. (через SSL! :) со следующими требованиями:

  1. Отдельные пользователи входят в систему, используя свой уникальный пароль фраза.
  2. Этой парольной фразы должно быть достаточно, чтобы позволить пользователю использовать систему эффективно (например, со смартфона и т. д.) - дело в том, что они не должны иметь при себе файл ключа.
  3. Пользователи могут хранить в системе биты данных произвольной длины («записи»).
  4. Записи зашифрованы в базе данных таким образом, что нет достаточно информации только в базе данных или приложении, чтобы прочитать зашифрованные записи.
  5. Пользователи должны иметь возможность «делиться» записями с другими пользователями системы. чтобы другой пользователь (пользователи) мог прочитать содержимое записи.

Я не специалист в криптографии. Подумав некоторое время, я подошел со следующим. Мой вопрос : безопасна ли эта реализация? Я чего-то не хватает? Если да, то можно ли реализовать указанную выше спецификацию? Или это перебор?

База данных

База данных настроена следующим образом:

+------------------------------------------------------------------------------+
|  users                                                                       |
+---------+--------------+--------------+---------------+----------------------+
| salt    | pub_key      | enc_priv_key | priv_key_hmac |                      |
+---------+--------------+--------------+---------------+----------------------+
|  entries                                                                     |
+---------+--------------+--------------+---------------+----------+-----------+
| user_id | parent_entry | enc_sym_key  | sym_key_sig   | enc_data | data_hmac |
+---------+--------------+--------------+---------------+----------+-----------+

Основные варианты использования

Представьте себе двух пользователей системы, Алису и Боба.

Боб регистрируется на сайте :

  • Боб вводит пароль. Этот пароль отправляется на сервер (но не сохранено).
  • Сервер генерирует случайную соль и сохраняет ее в поле salt .
  • Сервер генерирует хэш SHA-256 пароля и соли Боба.
  • Сервер генерирует Пара ключей RSA. Открытый ключ хранится как обычный текст в поле pub_key . Закрытый ключ зашифрован через AES-256. используя хэш, сгенерированный из пароля и соли Боба в качестве ключа, и хранится в поле enc_priv_key .
  • Сервер генерирует код аутентификации сообщения на основе хэша для Боба закрытый ключ, использующий пароль и соль Боба в качестве ключа, и сохраняет его в поле priv_key_hmac .

Боб хранит запись в системе :

  • Боб вводит некоторые данные, которые будут сохранены как запись вместе со своим паролем. Эти данные отправляются на сервер.
  • Сервер генерирует ключ, который будет использоваться в качестве ключа для шифрования AES-256.
  • Сервер использует этот ключ для шифрования данных и сохраняет результат в поле enc_data .
  • Сервер генерирует код аутентификации сообщения на основе хэша для данные, используя сгенерированный ключ, и сохраняет их в поле data_hmac .
  • Симметричный ключ, используемый для шифрования данных, зашифрован общедоступным ключ и хранится в поле enc_sym_key .
  • Сервер использует закрытый ключ Боба для генерации подписи для симметричный ключ.

Боб извлекает свою сохраненную запись :

  • Боб вводит свой пароль и идентификатор записи для получения.
  • Сервер генерирует SHA-256 хэш пароля и соли Боба .
  • Зашифрованный закрытый ключ Боба расшифровывается с помощью шифрования AES-256 с использованием хэш.
  • Сервер проверяет, что зашифрованный закрытый ключ Боба не был вмешательство путем проверки HMAC в priv_key_hmac .
  • Сервер расшифровывает симметричный ключ, хранящийся в поле enc_sym_key используя закрытый ключ Боба.
  • Сервер проверяет, что зашифрованный симметричный ключ не был подделан с помощью проверки подписи в sym_key_sign с использованием открытого ключа Боба.
  • Сервер дешифрует данные с помощью симметричного ключа.
  • Сервер проверяет, что зашифрованные данные не были подделаны. путем проверки HMAC, хранящегося в поле data_hmac .
  • Сервер возвращает расшифрованные данные Бобу.

Боб делится записью с Алисой :

  • Боб хочет, чтобы Алиса чтобы иметь доступ к записи, которой он владеет. Он входит в свой пароль и идентификатор записи для совместного использования.
  • Данные для записи дешифруются с использованием метода в "Боб получает его сохраненная запись »
  • Новая запись создается для Алисы таким же образом, как и в« Боб хранит запись в системе »со следующими исключениями:
    1. Для записи parent_entry задана запись Боба.
    2. Подпись для симметричного ключа вычисляется с использованием частной ключ (поскольку закрытый ключ Алисы недоступен для Боба).
    3. Когда Алиса обращается к этой новой записи, наличие ненулевого parent_entry заставляет систему использовать открытый ключ Боба для проверки подпись (поскольку для ее создания использовался его закрытый ключ).

Боб изменяет данные в своей общей записи :

  • Боб решает изменить данные в записи, которой он поделился с Алисой. Боб указывает идентификатор записи, которую необходимо изменить, и новые данные, которые она должна содержать.
  • Система перезаписывает данные, созданные в «Боб сохраняет запись в system. "
  • Система находит каждую запись с parent_entry , равной записи который был только что изменен, и для каждого из них перезаписываются данные, созданные в «Боб делится записью с Алисой».

Анализ

Преимущества:

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

Недостатки / проблемы (которые я могу придумать):

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

Повторяется из введения: мой вопрос: эта реализация безопасный? Я что-то пропустил? Если да, то можно ли реализовать эту спецификацию? Или это излишество?

Спасибо, что так долго не торопились. Мне интересно ваше мнение! Я на правильном пути или полный придурок? ВАМ РЕШАТЬ! :)

6
задан Michelle Tilley 28 March 2011 в 15:52
поделиться