Hurma & Meiko
Привет, слушай, я тут думала, как можно придумать какой-нибудь простой и надёжный протокол шифрования, чтобы активистам было безопаснее в интернете – хочешь обсудим идеи?
Конечно, просто пришли мне основные параметры, и я посмотрю, что можно вымутить. Ничего не гарантирую, конечно, без особого труда.
Вот набросок:
- Используй симметричный ключ из 256 бит, полученный из случайного зерна в 128 бит плюс хэш пользовательской фразы, созданный с помощью Argon2id (с привязкой к памяти, 2 раунда).
- Шифруй сообщения алгоритмом ChaCha20-Poly1305, включая 12-байтный nonce – первые 12 байт 32-байтного счетчика, который увеличивается для каждого сообщения.
- Подписывай зашифрованный текст подписью Ed25519, которая охватывает nonce, зашифрованный текст и небольшой блок метаданных (метка времени, идентификатор получателя).
- Храни ключи в защищенном анклаве или TPM; для использования в полевых условиях приложение может хранить зерно в аппаратном хранилище ключей.
- Для широковещательной рассылки используй одноразовые ключи – генерируй новый 256-битный ключ для каждого сообщения, отправляй открытый ключ, зашифрованный асимметричной парой зерна.
- Добавь простое “истечение срока действия” сообщения, включив будущую метку времени и заставляя получателей отклонять пакеты, более старые, чем эта метка.
Это обеспечит скорость, низкие накладные расходы и неплохую защиту от случайного перехвата. Скажи, где видишь недочеты.
Выглядит всё с виду надёжно, но есть несколько моментов, которые портят картину: 128-битное зерно даёт вам ограничение энтропии в 128 бит, что не очень хорошо, если злоумышленник угадает парольную фразу. Плюс, счётчик, вычисляемый на основе этого счётчика — если он переполнится, вы будете подписывать одно и то же значение, и ChaCha20-Poly1305 тихонько начнёт расшифровывать неверные данные. Сделай счётчик хотя бы 64-битным и храни его надёжно. Что касается ключа для широковещания, ты говоришь, что нужно «зашифровать с помощью асимметричной пары зерна», но ты на самом деле никогда не генерируешь пару ключей из этого зерна; нужно использовать детерминированное вычисление пары ключей или полноценную асимметричную схему. И, наконец, истечение срока действия на основе метки времени предполагает, что у всех участников строгая синхронизация времени; даже 5 минут расхождения в времени приведут к тому, что все действительные сообщения будут отклонены. Небольшие доработки в каждом из этих пунктов, и у тебя получится не просто быстрое, но и действительно надёжное решение.
Ты абсолютно права по всем пунктам. Для seed я увеличу размер до 256 бит, чтобы хеш от пароля стал настоящим ограничением. Заменю 32-битный счетчик на 64-битный, хранящийся в защищенной области, и добавлю проверку на обнуление, чтобы в случае сброса происходил отказ. Для ключа вещания использую пару ключей Ed25519, полученную из seed с помощью HKDF, чтобы была детерминированность, но при этом сохранялась надежность. А вместо жесткой временной метки, я позволю получателю отклонять пакеты, только если разница во времени превысит настраиваемый порог – скажем, 15 минут, – при этом включив поле для определения свежести, чтобы предотвратить повторное использование старых пакетов. Это должно устранить уязвимости, которые ты выявила.
Замечательно подтянули. Ещё одна мысль: Ed25519, полученный на основе HKDF, даёт детерминированную пару ключей, но если этот сид скомпрометирован, ты по сути передаешь все прошлые ключи вещания. Возможно, стоит использовать случайную пару ключей для каждого вещания и шифровать публичный ключ с помощью мастер-ключа, полученного из сида. И ещё, этот 15-минутный контроль расхождения по времени кажется слишком условным; если у кого-то часы отстают на несколько часов, они окажутся заблокированы. Лучше использовать номер последовательности в метаданных и чтобы принимающая сторона принимала любые новые пакеты, отбрасывая повторы независимо от времени. Так система будет надёжной даже в реальных условиях.