Шифрование и гостевые пользователи

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

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

Требование должно заключаться только в том, чтобы хакер, который украдет базу данных, не смог расшифровать сообщения. Я думал использовать метод открытого/закрытого ключа и прикрепить закрытый ключ как GET-параметр к https-ссылке. Он никогда не хранится нигде и находится только в оперативной памяти. Проблема в том, что закрытый ключ очень длинный, и, конечно, мне невыносимо передавать закрытый ключ на сервер.

Существует ли другой (лучший) способ, без ввода пароля или клиентского программного обеспечения, просто с помощью ссылки по электронной почте?

Если вы хотите, чтобы только пользователь мог прочитать сообщение, и чтобы хакер не мог его прочитать в базе данных, это означает, что у вас (вашего приложения) также не должно быть возможности читать сообщения. Если вы не можете их прочитать, какой смысл хранить их в базе данных? Я бы предложил, как только вы получите новое сообщение для пользователя, зашифровать его и отправить. Может быть, одной из причин может быть то, что если пользователь потерял это письмо, вы можете его переотправить. Это нормально. Хранение зашифрованных электронных писем не является проблемой.

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

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

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

Тогда любой сможет обмениваться любым количеством оффлайн-сообщений с любым зарегистрированным пользователем. Каждый зарегистрированный пользователь сможет отвечать на эти сообщения, если вы используете криптосистему ЭльГамаля, которая объединяет открытое и симметричное шифрование. ЭльГамаль очень прост и удивителен – https://en.wikipedia.org/wiki/ElGamal_encryption.

Каждый открытый ключ генерируется следующим образом: возьмите секрет x из циклической группы и вычислите открытый ключ $X = g^x$. Вся информация о циклической группе также является общедоступной (т.е. хранится на сервере).

Каждый отправитель (гость или нет) генерирует эпемеральный секретный ключ y из циклической группы и вычисляет соответствующий эпемеральный открытый ключ $Y = g^x$.

Ключ шифрования может быть сгенерирован только отправителем ($K = X^y$) и получателем ($K = Y^x$). Y должен быть прикреплен к сообщению.

Обратите внимание, что ЭльГамаль использует концепцию Диффи-Хеллмана без уязвимости «атака посредника» – даже сервер, который действует как промежуточный канал для обмена сообщениями, не может получить K.

Фундаментальные проблемы, как я вижу, заключаются в:

  1. Гостю нужно только ввести свой адрес электронной почты, и ему не нужно создавать учетную запись

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

  1. Хакер, который украдет базы данных, не сможет расшифровать сообщения

Это довольно расплывчатое, и возникает вопрос, что именно находится в потенциально украденной базе данных или вы действительно имеете в виду кражу всей системы?

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

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

Если беспокойство заключается в полной компрометации времени выполнения с полным доступом к памяти со стороны злоумышленника, тогда у меня нет идеи!

Конечное шифрование является сложным, даже без требования учетной записи гостя!

Сказав это, в основном, ваша потребность не так уж и сложна. Какой-то пользователь хочет отправить сообщение гостю. Клиент пользователя (скрипт на стороне браузера, если это веб-приложение) генерирует симметричный ключ шифрования (нет причин использовать открытые ключи здесь) и шифрует сообщение(я), которые пользователь отправляет. Зашифрованные сообщения хранятся на сервере вместе с некоторой идентификацией (возможно, адресом электронной почты предполагаемого получателя, хотя это требует хранения некоторой открытой личной информации, так что, возможно, вы используете непрозрачный идентификатор). Клиент также генерирует URL, содержащий ключ как часть фрагмента URL (и, если актуально, непрозрачный идентификатор как параметр пути или запроса). Этот URL может использоваться для получения зашифрованных сообщений и (через фрагмент, который не отправляется на сервер) расшифровки их.

URL отправляется получателю (гостю). У вас есть выбор: как передать эту ссылку от клиента пользователя в почтовый ящик получателя-гостя? В целом можно выделить три способа:

  • Отправить URL на сервер, и сервер отправляет электронное письмо. Это нарушает свойство нулевого доверия, так как требует доверия к тому, что сервер не хранит URL (или даже только его часть ключа), или использует его, пока он временно проходит через систему, или хранит в журнале “отправленных сообщений” на почтовом сервере, или что-то другое.
  • Сказать пользователю отправить ссылку самостоятельно (то есть скопировать ее в буфер обмена и вставить в свой собственный почтовый клиент или чат-программу, или даже записать ее на письме и отправить обычной почтой). Не лучший пользовательский опыт, но, эй, это (в основном) сохраняет нулевое доверие… пока вы не используете веб-приложение, которое, по сути, несовместимо с нулевым доверием (пользователь и получатель всегда должны доверять тому, что сервер не отправляет им вредоносный скрипт, который украдет открытый текст; теоретически вы могли бы вручную проверять это каждый раз, так как даже минифицированный клиентский JS технически читаем, но на практике, хм, нет).
  • Пусть клиентское приложение отправляет сообщение с минимальным взаимодействием пользователя, но без пересылки через сервер. Для веб-приложения, вероятно, ближайшее, к чему вы можете приблизиться, это заставить пользователя нажать на mailto: URI и надеяться, что браузер пользователя настроен открывать их в правильной почтовой программе или веб-приложении и что почтовый клиент (веб-или другой) обрабатывает его как ожидалось (и что пользователь затем нажимает “Отправить”). Для настольного/мобильного приложения, теоретически, вы можете заставить приложение подключиться напрямую к SMTP-серверу (вероятно, к серверу пользователя, на который они должны предоставить учетные данные, что вряд ли возможно) но на самом деле вы, вероятно, будете использовать “контракт общей” для отправки URL в мессенджер какого-либо рода через функционал, предоставляемый ОС для передачи данных и намерений между приложениями.

Я оставляю тут кучу подробностей, заметьте. Вам нужна защита целостности, а не только шифрование, на шифротексте; это, вероятно, должно быть сделано с использованием аутентифицированного шифрования. Вы также можете подписывать сообщения, если хотите, чтобы они определенно пришли от этого конкретного пользователя, но иногда конфиденциальность отправителя/отказ от сообщения является желаемым свойством вместо этого. Вам нужен какой-то способ истечения сроков ссылок, использованных или не использованных, и, вероятно, истекать их раньше, если использованы… но, вероятно, вы не хотите, чтобы они истекали немедленно после первого использования, иначе любая программа, которая загружает URL (например, чтобы проверить их через сканер безопасности, отобразить предварительное изображение результирующей страницы или кэшировать их для более быстрой загрузки позже) может преждевременно истечь ссылку. Система, как описано, обрабатывает только отправку сообщени для гостей, а не для начала разговора гостем или ответа на сообщение; оба варианта возможны, но это делает ситуацию более сложной. Это также в первую очередь предназначено для одного получателя; если вы хотите отправить одно и то же сообщение нескольким людям, не дублируя один и тот же открытый текст на кучу шифротекстов, тогда вам потенциально нужно использовать гибридную криптосистему, где вы отправляете гостю закрытый ключ; ключи эллиптической кривой достаточно короткие, чтобы это было жизнеспособно, но это снова добавляет сложность.

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

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

Кажется, в дизайне этой системы есть недостаток.

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

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

Существует ли другой (лучший) способ, без ввода пароля или клиентского программного обеспечения, только с помощью ссылки по электронной почте?

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

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

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

1. Понимание угроз и требований

Перед тем как предложить техническое решение, стоит четко обозначить угрозы:

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

2. Тактический подход к шифрованию

Основное предложение заключается в использовании симметричного и асимметричного шифрования в гибридной модели. При этом следует учитывать, что:

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

Шаги по реализации:

  1. Генерация ключей: При первом взаимодействии с системой зарегистрированный пользователь создает пару ключей (публичный и приватный пара) прямо в браузере и отправляет публичный ключ на сервер.

  2. Шифрование сообщений:

    • Когда зарегистрированный пользователь отправляет сообщение, оно шифруется с помощью уникального симметричного ключа. Этот ключ в свою очередь шифруется с использованием публичного ключа получателя.
    • Зашифрованные сообщения и зашифрованный ключ помещаются в базу данных.
  3. Отправка ссылки гостю: Сервер отправляет гостю электронное письмо с одноразовой ссылкой для доступа к зашифрованному сообщению. В данном случае ссылка может содержать идентификатор сообщения.

  4. Дешифрование на клиенте:

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

3. Важные аспекты реализации

  • Хранение данных: Сообщения должны храниться в шифрованном виде, чтобы даже в случае утечки базы данных злоумышленники не смогли получить доступ к их содержимому.
  • Dual Key Management: Для повышения безопасности следует использовать внешние системы управления ключами, которые позволят хранящим ключи служебным системам взаимодействовать с шифрованными данными без деградации безопасности.
  • Обновление ссылок: Одноразовые ссылки для доступа к сообщениям должны иметь ограниченный срок действия и автоматически удаляться после использования. Это защитит информацию от повторных попыток доступа.

4. Заключение

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

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

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