Как использовать потоковый шифр для шифрования данных TCP?

Я пытаюсь использовать шифрование chacha20 в своем сетевом программном обеспечении, но у меня возникла проблема

если я зашифрую 4 байта данных: 0x01 0x02 0x03 0x04 на сервере

и получить зашифрованный текст: 0xd2 0xd3 0xc4 0xd5, а затем отправить его клиенту

клиент может получить <= 4 байта за раз

при условии, что клиент только recv 0xd2 0xd3 вначале,

он может правильно расшифровать данные и получить открытый текст 0x01 0x02

но когда клиент получает последние 2 байта 0xc4 0xd5

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

так есть ли способ решить проблему

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

2 ответа

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

Большинство криптографических API-интерфейсов позволит вам выполнять частичное шифрование / дешифрование. Это обычно означает вызов update метод для первой части и второй части, обычно сопровождаемый final метод, когда обнаружен конец открытого / зашифрованного текста. В зависимости от API вы должны ожидать вывода для каждого из этих методов.

Только если ваш API не позволяет вам правильно обрабатывать поток, вам следует объединить зашифрованный текст и выполнить расшифровку полного зашифрованного текста.

ChaCha20 генерирует поток, используя ключ и одноразовый номер. Позволять (S0, S1, S2, S3) первые байты потока и (M0, M1, M2, M3) первые 4 байта вашего сообщения.

Зашифрованный текст будет вычислен как (M0⊕S0, M1⊕S1, M2⊕S2, M3⊕S3), Это если у вас есть M0...M3 легко доступны.

Если вы шифруете (M0, M1) затем (M2, M3) используя тот же ключ и nonce, вы получите (M0⊕S0, M1⊕S1) а также (M2⊕S0, M3⊕S1), Который не может быть расшифрован с помощью (C0⊕S0, C1⊕S1, C2⊕S2, C3⊕S3),

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

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

Другие вопросы по тегам