Лучший способ шифрования сообщений в Java, где зашифрованный текст является общедоступным

#java #algorithm #encryption #cryptography

#java #алгоритм #шифрование #криптография

Вопрос:

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

Требования примерно:

  • Каждый пользователь может публиковать некоторую информацию (например, открытый ключ) в общедоступной базе данных, но должен делать это только один раз
  • Другие пользователи должны иметь возможность зашифровать сообщение для целевого пользователя и опубликовать его публично в той же базе данных
  • Предполагаемый получатель должен иметь возможность расшифровать сообщение, но ни один другой пользователь не должен иметь возможности это сделать
  • Шифрование должно быть достаточно надежным, чтобы никакое правдоподобное вычисление методом перебора не могло расшифровать сообщение (сейчас или в будущем)
  • Сообщения имеют произвольную длину, но обычно довольно малы (например, короткие электронные письма, твиты и т. Д.)
  • Должно быть легко реализовать в обычной Java (библиотеки, такие как Bouncy Castle, подойдут, если необходимо)
  • У пользователей уже есть Ed25519 пары ключей для цифровых подписей, если это необходимо

Какой криптоалгоритм или комбинация алгоритмов лучше всего соответствуют этим требованиям? Я предполагаю некоторую форму асимметричного алгоритма шифрования с парой открытых / закрытых ключей для каждого пользователя, но альтернативные идеи приветствуются. Я определенно хочу избежать ловушки «свернуть свою собственную криптографию»….

Ответ №1:

Вы (почти) всегда запускаете свои собственные протоколы. Обычно это место, где происходят взломы.

Теперь, если бы вы использовали свой собственный алгоритм (например, вы избегаете, скажем, AES-256 и пишете что-то самостоятельно. Мы просто будем XOR каждый байт с повторным применением «Ого, это как одноразовый блокнот, его нельзя взломать! — это своего рода мышление, о котором весь мем «не запускай свой собственный криптограф». Не делайте этого.

Даже если вы используете готовые «протоколы», очень легко все испортить и создать дыры. Сторона протокола (ТО, КАК вы используете криптоалгоритмы) по своей природе нелегко абстрагироваться в единую, трудно-невозможно злоупотреблять встроенной библиотекой.

Итак, создайте свой собственный. То есть протокол.

Здесь это кажется почти тривиальным, но это не так. Основная задача — использовать криптографию с открытым / закрытым ключом обычным способом, шифруя сообщение с помощью симметричного шифрования (скажем, AES-256), генерируя случайный IV и случайный ключ и сохраняя оба в БД, но ключ хранится зашифрованным — зашифрованным с использованием криптографии с открытым / закрытым ключом.

Этого, по сути, достаточно, чтобы делать то, что говорят ваши требования. Но как насчет повторных атак? Возможно, это слишком усердно или неправдоподобно, но что, если я смогу записать материал в вашу БД? Я мог бы воспроизвести сообщение: сохранить точно такой же набор зашифрованных байтов, но с разными временными метками, и вы подумали бы, что это реально.

Это как раз одна из тех протокольных штучек: это помогает, если вы включаете временную метку, отправителя и т. Д. Внутри большого двоичного объекта для шифрования — вы хотите, чтобы повторная атака была безвредной, и, как правило, если сообщение (включая метаданные) является точным, точно таким же, оно должно быть. Возможно. Обычно. Это зависит от того, чего ожидают ваши пользователи и для чего они будут его использовать. В конце концов, идеального шифрования не существует. Но если даже это неприемлемо, для этого тоже есть решения, хотя простой путь — просто убедиться, что ни у кого нет доступа на запись на уровне raw SQL к БД.

Если ваша система будет «взломана», это почти всегда будет в битах «протокола» второго уровня. Могу ли я просто позвонить в вашу службу поддержки и указать пользователя? Могу ли я просто сказать, что потерял свой пароль, и получить новый, отправленный мне по почте, и «просто» взломать электронную почту пользователя вместо этого? Могу ли я вставить кейлоггер на их компьютер? Может быть, разбросать несколько USB-накопителей с крысиными червями по парковке; КРЫСИНЫЙ червь, специально написанный для поиска их ключевых файлов, ловит их при вводе пароля для этого ключевого файла и отправляет все это мне? Никакая «готовая библиотека java» никогда не защитит вас от всего этого. Вы не можете обеспечить безопасность с помощью «Я действительно не знаю, что я делаю, но я, по крайней мере, знаю, что не знаю, поэтому я обязательно получу библиотеку, рекомендованную сообществом и экспертами, и постараюсь следовать ее руководству, насколько смогу, и, конечно, со мной все будет в порядке!» -своего рода мода. Нет, если вы относитесь к этому серьезно.

Некоторые из алгоритмов, которые вам, вероятно, следует использовать:

  • BouncyCastle поддерживает ElGamal, схему шифрования с открытым / закрытым ключом. Идея состоит в том, что у всех пользователей есть открытый и закрытый ключи; открытый ключ известен вашему серверу (и всем пользователям по запросу; ваш сервер является центром обмена информацией для них и должен будет ручаться за правду, то есть, если вы идете: «вот открытый ключ для пользователя Foo», вы подтверждаете, что это правда, и, предположительно, подтверждаете, что личная информация пользователя Foo на вашем сайте верна. Как — это зависит от вас и не имеет ничего общего с криптографией, а с политикой и локальными процессами. Вы их вызываете? Идентифицируют ли они себя с помощью паспорта? Что? Закрытый ключ известен только им. Вам нужно будет вручную использовать какую-то схему аннулирования. Возможно, пользователи могут помазать несколько других пользователей — тогда они получат право аннулировать свой ключ. Идея заключается в том, что если пользователь чувствует, что его закрытый ключ скомпрометирован, он просит одного из своих приятелей войти в систему и аутентифицироваться в системе, а также сообщить системе пометить ваш открытый ключ как недействительный для любых дальнейших сообщений.

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

  • Используйте AES-256 вместе с вашим plane jane basic new SecureRandom() для генерации ключа для каждого сообщения, которое вы хотите сохранить в системе. Чтобы сохранить сообщение, вы берете данные, генерируете случайный ключ, шифруете данные с помощью этого ключа и алгоритма AES-256, сохраняете зашифрованные данные, затем шифруете ключ с помощью ElGamal и открытого ключа пользователя и тоже сохраняете его. Чтобы расшифровать эти данные, пользователь извлекает (с зашифрованным открытым ключом) ключевые данные (которые могут быть общедоступными) и зашифрованные данные (также общедоступные) и может отменить задание с их стороны, сначала используя свой закрытый ключ ElGamal для получения случайно сгенерированного ключа AES-256, используемого, а затем используйте это. Вы не шифруете все сообщение с помощью ElGamal; это довольно медленный и не самый распространенный способ сделать это. AES-256 невероятно быстр. Но симметричный. В дополнение к алгоритму (который будет AES-256) вам понадобятся «режим блокировки» и «режим заполнения» для вашего шифрования. режим блокировки, вероятно, должен быть GCM; вы можете прочитать о CBC; это устарело (хуже и медленнее). Определенно не выбирайте ECB, это небезопасно. Заполнение, вероятно, не имеет значения, зависит, как обычно, от очень многих факторов.

  • Вы ничего не упомянули о подписях. Если пользователь «Foo» хочет отправить сообщение пользователю «Bar» таким образом, чтобы никто, кроме Bar, не мог его прочитать, все, что им нужно сделать, это вышеуказанное. Но если они это сделают, «Bar» абсолютно не знает, кто его отправил. GCM имеет некоторую встроенную поддержку для компьютеров Mac, что вам нужно для пометки сообщения таким образом, чтобы отправители могли доказать, что они на самом деле были отправителем, а также для пометки даты и времени, хотя это непросто; в основном вы, как сервер, помечаете любое сообщение с помощью ‘I, сервер, указ, и вам придется поверить мне, что это присутствовало в БД на данный момент времени и появилось недавно; для меня в любом случае. Подписано, сервер’.

Это даст вам несколько терминов (MAC, GCM, AES-256, ElGamal, Bouncy Castle, подписи и еще несколько) для поиска в Интернете и чтения.

Комментарии:

1. Спасибо за подробные мысли! Похоже, что ElGamal и AES должны хорошо работать в сочетании, я проверю это (и приму ваш ответ, если он сработает!)

Ответ №2:

Мне кажется, что вы разрабатываете систему чата.

Для выполнения ваших требований вам необходимо объединить две криптосистемы.

Первый — это обмен ключами Диффи-Хеллмана — короче говоря: каждая сторона генерирует пару закрытых / открытых ключей. Открытый ключ хранится на сервере. Если я попытаюсь отправить сообщение Бобу, я использую вашу базу данных для «Боба» и получаю его открытый ключ. Затем я создаю «общий секрет» с моим закрытым ключом и открытым ключом Боба — этот общий секрет обычно имеет длину 32 байта.

Теперь начинается вторая фаза — я шифрую свое сообщение с помощью алгоритма AES (лучшим может быть режим «GCM») и сохраняю зашифрованное сообщение (закодированное как Base64-string) в вашей общедоступной базе данных (конечно, с любым намеком на то, что аналог — это я).

Третья фаза: Боб получает зашифрованное сообщение с пометкой, что оно от Майкла. Теперь Боб ищет в базе данных открытый ключ Майкла, создает общий секрет с помощью своего (Боба) закрытого ключа и открытого ключа Майкла. Произойдет какая-то магия — общий секрет — это тот же ключ, который я использовал для шифрования. Теперь Боб смог расшифровать мое сообщение.

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

Комментарии:

1. Вам также нужна система, которая доверяет или проверяет, что то, что вы считаете открытым ключом Боба, действительно принадлежит Бобу. Это не позволяет злоумышленнику «человек посередине» притворяться Бобом.

2. @PresidentJamesK. Polk В этом конкретном случае требуется, чтобы Боб подписал цифровой подписью ключ, который он хочет использовать для шифрования сообщений для него, с помощью отдельного закрытого ключа Ed25519. Кажется, выходит за рамки части шифрования, но этого должно быть достаточно, если он сохраняет оба закрытых ключа в безопасности — правильно?

3. @LutherKroe: Вам всегда нужен механизм доверия с открытыми ключами, хотя существует несколько моделей. Проще всего просто жестко запрограммировать открытый ключ в программном обеспечении и использовать этот открытый ключ для привязки модели доверия. Боб может подписывать вещи своим ключом Ed25519, но откуда Алиса знает, что это действительно Боб подписал его, а не кто-то, притворяющийся Бобом?