Как использовать одноразовые номера в асимметричном шифровании (libsodium)?

Я пишу приложение, в котором пользователи могут общаться между устройствами с помощью сквозного шифрования. Для этого я использую библиотеку шифрования libsodium. Функция асимметричного шифрования crypto_box(...) требует одноразового номера в качестве одного из аргументов.

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

Достаточно ли того, что все сообщения, отправленные из A в B, имеют разные одноразовые номера, или одноразовый номер, используемый для отправки сообщения из A в B, не может использоваться для отправки из C в B?

Может кто-нибудь, пожалуйста, объясните мне это.


person joakimb    schedule 12.06.2014    source источник
comment
nonce на самом деле является сокращением числа, используемого ОДИН РАЗ. Так что ДА, вы используете разные номера!   -  person OJFord    schedule 09.07.2014


Ответы (2)


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

Что такое общий секрет? Это ключ, рассчитанный из (секретного ключа A, открытого ключа B) или (открытого ключа A, секретного ключа B). A и B выполняют разные вычисления на основе того, что у них есть, но в итоге получают один и тот же общий секрет.

Общие секреты, используемые в crypto_box, имеют длину 256 бит. Что огромно. Вы можете смело считать, что общие секреты будут уникальными для каждого «разговора».

Итак, (A, B), (A, C) и (C, B) могут безопасно обмениваться сообщениями, используя одни и те же одноразовые номера. Но если A отправляет сообщение B, используя данный одноразовый номер, B не может отправить сообщение A, используя тот же одноразовый номер. Nonces должны быть уникальными для всего, чем обмениваются во время разговора между A и B.

Таким образом, простой счетчик может быть в порядке. Попросите A выбрать четные числа, оставить нечетные числа B, увеличить одноразовый номер на 2 после каждого отправленного сообщения, и все готово.

Но шифр, используемый в конструкции crypto_box, на самом деле имеет очень большой одноразовый номер. 192 бита.

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

Некоторые потоковые шифры, включенные в Sodium (AES128-CTR, ChaCha20, Salsa20), имеют более короткий одноразовый номер и требуют счетчика во избежание коллизий. Вот почему они находятся в «расширенном» разделе документации.

Но с crypto_box и crypto_secretbox просто каждый раз выбирайте случайный одноразовый номер (randombytes_buf(nonce, sizeof nonce)), и вы будете в безопасности.

person Frank Denis    schedule 10.06.2015

Нужно ли шифровать каждое сообщение одному человеку с использованием разных одноразовых номеров?

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

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

Зачем вам хранить свой одноразовый номер на сервере с публичным доступом? И как, по-вашему, злоумышленник может «использовать» одноразовый номер? Для этого им понадобится ваш закрытый ключ.

Почему вы не можете хранить одноразовый номер в том же месте, что и ваш закрытый ключ?

person Jay Sullivan    schedule 12.06.2014
comment
Но когда А хочет отправить зашифрованное сообщение Б, А шифрует сообщение с помощью ОТКРЫТОГО ключа Б. Вот тут я запутался. Таким образом, A определяет одноразовый номер, а B не имеет контроля над тем, какой одноразовый номер используется для шифрования сообщений, отправляемых B, а затем расшифровываемых с помощью закрытого ключа B. Что мне здесь не хватает? - person joakimb; 13.06.2014
comment
Нашел эту ссылку: curvecp.org/nonces.html, в которой говорится: "После того, как определенный одноразовый номер был использован для шифровать пакет, тот же одноразовый номер никогда не должен использоваться для шифрования другого пакета от секретного ключа отправителя до открытого ключа этого получателя, и тот же одноразовый номер никогда не должен использоваться для шифрования другого пакета от секретного ключа получателя до этого открытого ключа отправителя. Теперь я понимаю, что только между A и B один и тот же одноразовый номер нельзя использовать дважды. - person joakimb; 13.06.2014
comment
Если A отправляет зашифрованное сообщение B. Должен ли B использовать тот же одноразовый номер (используемый для шифрования сообщения A) для расшифровки сообщения? Или он генерирует новый одноразовый номер для расшифровки сообщения. Я понимаю, что для шифрования и дешифрования требуется открытый ключ друг друга. Я пытаюсь выяснить, нужно ли обмениваться одноразовым номером между A и B для шифрования/дешифрования данных, отличных от открытых ключей. - person Feru; 18.02.2015
comment
@Feru да, одноразовый номер не является секретом и включен как часть полезной нагрузки зашифрованного текста. - person Woodstock; 22.10.2020