Pull to refresh

Comments 56

Отслеживаю проект с самого его появления, спасибо вам за него. Вообще, я считаю, идея делать VPN с одним типом шифрования — правильная. Во-первых, Salsa20 будет работать быстро как на мобильных устройствах, так и на десктопах; Google уже использует ChaCha20 в TLS для мобильных устройств, да и, например, в том же OpenVPN режимы, вроде OFB, уже давно особо никто не проверял и не использует.

Честно говоря, чтобы проект взлетел, по моему мнению, нужны клиенты под все мейнстрим ОС (включая мобильные). Это, пожалуй, самое главное. Если бы у tinc были клиенты под мобильные ОС, да еще и с GUI, то он был бы явно популярнее OpenVPN (они, кстати, теперь тоже ChaCha20, Poly1305 и Ed25519-ключи используют).
И обязательно клиенты под аппаратные роутеры. Mikrotik хотя бы, за ним D-Link. Cisco, как обычно, ничего такого не станет делать, но ОС-based VPN — это, увы, совсем не всегда удобно.
Вовсе нет. На железках какие VPN-ы стандартные (не фирменные) реализованы? IPSec, PPtP, L2TP, что еще? Если ни один из них не устраивает, то все грустно. Тот же Mikrotik имеет хотя OVPN и SSTP — оба не широко распространены (да и реализованы, кажется, по остаточному принципу — «когда есть время разработчиков»), но это хоть что-то.

Посему, кроме реализации нового VPN под все популярные ОС, хочу уточнить, что на железе тоже нужна реализация, иначе так и будет новый протокол только для связи ПК.
Кстати, сам сюда заходил чтобы сказать про Tinc :)
// Кстати, в 1.1pre-версиях (апстримных, не android'ной морды) он стал куда более няшкой.
// А вот с андроидной мордой есть косяк: ни оригинальный автор андроидной морды, ни я, не имеем понятия какие пермишны нужно прописать в манифест, чтобы получить доступ к /dev/tun. А без них требуется рут (ибо иначе приложение не может им пользоваться). Так и живём :(
Насколько вероятно что Go будет поддерживаться эмбидед-системами: телевизорами, роутерами?
Реально ли собрать GoVPN под arm, при том, что размер ПЗУ 10 мегабайт?
Оно уже сейчас свободно поддерживается, вопрос только в пока еще не существующих библиотеках. При условии, если мы говорим об ARM платформе.
ПЗУ, конечно же, нужно будет иметь в запасе больше 50.
Под ARM 32bit он собирается. Сам ARM устройств не имею, но думаю что 10 мегабайт хватит, так как клиент и сервер бинарь скомпилированный и со сделанным strip занимает 2.7MiB.
UFO just landed and posted this here
юзер спейс, медленно. Оно хорошо только для стадии разработки и дебага.
Вся скорость чачи/сальсы на этом месте и потеряется.
Э? Вы серьезно? Гоняю гигабит через TUN по Ethernet point-to-point линку на компьютерах 7-8-летней давности, проблем никаких.
UFO just landed and posted this here
Не сложно запилить прямо в ядре? Вы учитываете и то что нужно вместо одной реализации писать две различные например чтобы поддерживать GNU/Linux и FreeBSD одновременно? Что проще поддерживать и администрировать: userpace демон требующий только TAP устройство или ядерные модули? О производительности надо париться когда она даёт о себе знать. Гигабиты гонять — проблема. Не у всех такие потребности. С таким же успехом можно было бы говорить и о том что на ассемблере гораздо производительнее софт без overhead-ов сторонних, но люди почему-то придумывают дополнительные абстракции, языки высокоуровневые. Стоимость разработки и поддержки ПО гораздо выше чем стоимость железа, как правило.
UFO just landed and posted this here
Нужен форк под винду/мак? У меня контрвопрос: а зачем вам вообще это тогда всё надо, какие задачи вы хотите решить? Понятие криптографической безопасности на этих платформах исключено по определению в виду закрытости кода и поэтому что бы там не хотелось добиться, но либо GoVPN либо Windows/OS X — не тот инструмент которым можно решить задачу.

Ваша боль на пустом месте по поводу производительности (вы ведь даже не спросили и не проверили а какую выдаёт сейчас то что сделано), ассемблере, контексте и желания засунуть всё в ядро, да ещё и упоминания Windows могут говорить только о том что вы смутно представляете трудозатраты на разработку ПО, его поддержку и обеспечения достойного качества. И последнее: студентов которые констатируют всем хорошо известные факты о дороговизне переключения контекста программ, об очевидности производительности ассемблера, о том что очевидно что на C это будет работать быстрее Go — пруд пруди, но отношение к ним одинаковое: они не знакомы с трудозатратами поддержки, тестирования, они закрывают глаза на то что десятилетиями вовсю внедрённые OpenSSL библиотеки полны багов, причём катастрофическим (не верят что это из-за сложности кода в который и смотреть то даже противно), не знают о большом разнообразии ОС и что писать ядерные вещи для них дело мягко говоря куда более дорогое чем всё железо за жизнь одного человека/компании вместе взятое.

Когда от безопасности протоколов, их реализаций и софта будут зависеть ваши деньги (как минимум), то вы не будете рисковать и заставлять своих разработчиков писать ядерные модули, переписывать кучу всего на ассемблере. Вы пожелаете чтобы они на каждом чихе проверяли не выходит ли обращение к памяти за границы массивов, не переполнились ли где integer-ы и всё в таком духе. Вы будете рады знать что о тем что на каждую операцию делается в несколько раз больше проверок, чем могло бы быть на ассемблере, но если где-то проскочет какая-то дырка/лазейка которая может поставить весь ваш бизнес на грань краха, то вы лично пойдёте покупать ещё процессоров и серверов, потому-что их стоимость легко может быть пылинкой перед рисками сложного ПО: то, которое сложно оценивать, сложно review-ить. Или ПО в ядерном процессе, ещё в котором память может течь: гораздо дешевле иметь GC и userland в котором сильно всё ограничено по доступу.

И когда к заказчику придёт новость о том найдена фатальная бага, как тьма находится в OpenSSL, то новость о том что «зато мы работали так быстро что сэкономили целый Xeon процессор» его не сильно обрадует.

Безусловно количество перерастает в качество и если бы GoVPN работал со скоростью 1 килобайт/сек загружая на 100% процессор, то это одно, но GoVPN на одном ядре Xeon выдаёт почти 100Mbps.
И ещё замечу что в ядро с ходу я вспоминаю что встраивают IPsec. Он самый достойный и качественный? Отнюдь. OpenVPN вовсю работающий в userspace куда чаще используется. IPsec криптографически совершеннее? Он не плох, но например набор примитивов, мягко говоря, староват и все они очень и очень не быстрые (куда там до ChaCha20/Poly1305!).

В базу например берут средства шифрования WiFi, как например WEP. Стандарт, супер распространённый. Очень он безопасен? TLS? Лучше не связываться. SSHv2 не шибко где какой стандарт и база, но закрыв глаза на пару недочётов он куда грамотнее и с Ed25519/ChaCha20/Poly1305 быстрее многих.

Кто платит: тот быстрее и попадёт в «базу». А всё потому-что дорого. Не будут в OpenVPN писать ядерные модули.
UFO just landed and posted this here
У вас есть причины доверять Windows/OS X? А у меня нет, совсем. Вы можете гарантировать что не происходит ничего плохого в закрытом коде под которым это всё будет запускаться, что он не будет производить слив данных? Нет, так как нет открытого кода. Плюс там нет PRNG и источников энтропии которым бы можно было доверять и не реализовать свои, так как никто не гарантирует что энтропия не сольётся наружу. Много пользователей? Это их проблемы. Задача чего-либо связанного с безопасностью не выполнима под данной ОС.

OpenVPN находится в нише: более доверяемая реализация хотя бы косвенно из-за относительной простоты; гораздо более удобный для большинства (не для всех, нет) пользователей в плане администрирования. Именно простота играет решающую роль. Один бинарник и пара опций к нему и вот уже приемлимый готовый VPN.

AES он умеет. Лично я не доверяю AES, так как в нём есть уязвимости. Более того IPsec/OpenVPN и прочие не имеют zero-knowledge протоколов.

Я не говорю что написать ядерные модули это невозможно. Всё возможно. Вопрос трудозатрат и наличия ресурсов. Даже в случае с популярным OpenVPN это требует больших ресурсов (в виде человекочасов), а profit-а от этого будет так мало, что овчинка выделки не стоит. Ядерные модули это увеличение сложности, а значит потенциально больше возможностей для ошибок, недочётов, как это происходит с OpenSSL. Если ценой производительности можно добиться большей безопасности, то выбор падает именно на это.

Мог бы выдавать. Сейчас беготня за подобной производительностью это последнее о чём надо надо думать. И если уж вдаваться в конкретику, то реализация Salsa20 в используемой Go библиотеки написана как-раз таки на ассемблере, если что, на SSE. Вы пытаетесь оптимизировать шифрование/аутентификацию, хотя я уже говорил что они и так настолько быстрые что задумываться о Salsa vs ChaCha бессмысленно. Проседание идёт куда сильнее хотя бы на GC. Вариант решения: переписать с Go. Недостаток я думаю очевиден.
Ну, насчет уязвимостей в AES вы загнули, конечно, конкретно. Нет, во влажных мечтаниях Бернштайна, конечно, любой алгоритм с s-блоками подвержен timing attack (если не используются constant time hardware implementation). Но на практике это не было и никогда не будет применимо, особенно по сети. А вот у salsa/chacha выход keystream однозначно более biased, чем выход от AES-CTR, что обнаруживается статистически. Я ненастоящий сварщик, чтобы из этого делать выводы, но и заявлять, что, дескать, chacha безопаснее AES, я бы сильно поостерегся.
Да, я намекал только на timing attack-и на S-box-ы. Согласен что вопрос применимости на практике: очень хороший. Говорить что AES не безопасен это конечно не правильно или что Salsa/ChaCha сильно лучше в этом плане. Лично я ему просто поменьше доверяю, исключительно субъективно.
Ну так классические s-блоки были предназначены для реализации в железе, где они просто представляются дешифраторами (и однозначно имеют constant time для любых входных комбинаций). А в софте часто используют «оптимизации» AES на достаточно больших таблицах подстановки. Но даже в таком случае я не вижу абсолютно никакой реальной возможности timing атаки. Если мы берем SMP систему, где есть планировщик задач, прерывания и уж тем более, если мы берем сеть с ее непредсказуемым шумом. «Железный» aes по определеню constant time (те же AES-NI).

Насчет чачи у меня очень противоречивое мнение. С одной стороны, мне нравится реализация алгоритма в софте. С другой же, когда я внимательно смотрел пермутации чачи, мне это показалось очень-очень похожим на классическую s-p сеть, где s блок — это сложение по модулю 32, а p блок — ротации. Но однозначно я могу сказать только то, что глубина криптоанализа aes пока не сравнится с анализом чачи (хотя eSTREAM — это очень уважаемое мероприятие, бесспорно). И наблюдаемые на практике статистические bias'ы мне крайне не понравились:

paste.lisp.org/display/144927

AES-CTR прошел все тесты без проблем. RC4 я не тестировал, скажу сразу :)
UFO just landed and posted this here
Не доверять причины есть: авторство и под кем в итоге создавался AES. AES != Rijndael.

Нет увеличения сложности? То есть вместо того чтобы написать один кусок кода который работает и под FreeBSD и под GNU/Linux, мне надо будет писать уже как минимум два. Действительно, никакой сложности.

Про 100Mbps уже говорил: если вас эта скорость не устраивает — не используйте. Приговор это например двойное использование nonce, так как тогда бы не выполнялись поставленные задачи перед проектом. С чего вы взяли что в этой реализации нет возможности распределения по ядрам?

Лично я видел что на ассемблере она там имеется. Для нужд большинства людей и на чистом Go скорость будет достаточная за глаза.

Хм. Ассемблер тоже работает и не тормозит. Ужас, куда же движется человечество изобретая бесполезные с вашей точки зрения (ну похоже на то) инструменты разработки, высокоуровневые языки и прочее, которое почти всегда делает куда более громоздкий и медленный код.
4. Иван, вы проявляете удивительное незнание базовых принципов криптографии. Повторение нонсов — это ужаснейшая проблема, которая делает автоматически любую шифросхему потенциально небезопасной. Почему? Да потому что это дает одинаковый ключевой поток k и k'. Тогда если k == k', то (P ^ k) ^ (P' ^ k') дает на выходе P ^ P', что явно отличимо от random output. Это даже *без* знания P и P' позволяет статистически выделить закономерности в таком шифротексте. Более того, в случае счетчика повторение нонса однажды значит повторение его и впоследствие, что позволит однозначно выделить закономерности и расшифровать содержимое. Повторение нонсов безопасно только в случае, если вы и так передаете /dev/random через зашифрованный канал. Что, очевидно, крайне редко применимый кейс. Зная открытый текст, конечно, все еще проще, но это знание необязательно в огромном количестве реальных случаев.
1. Медленно. Не спорю. Вопрос насколько. В GoVPN я 100Mbps почти выжимаю на одном ядре процессора. На самом деле скорость куда сильнее теряется на одном только garbage collector Go. Задача была сделать reviewable, поддерживаемый простой код, портируемый. Завязываться на ядро: так это писать для каждой ОС совершенно независимую реализацию.
2. Если вам так критична скорость, то да. Производительность GoVPN удовлетворительна будет для большинства пользователей.
3. Salsa20 перевесила только одним: она есть по-умолчаню из коробки в golang.org/x/crypto. Но тут это не шибко принципиально. Про ChaCha20 я поэтому и упомянул. Заменить на ChaCha20 это поменять название библиотеки. Но порог безопасности Salsa20 и так настолько высок, а разница в производительности на фоне того же garbage collector так незначительна, что тут уж проще выбрать что есть «из коробки», так как портируемость и простота поддержки лучше
4. Вы не разобрались как это работает. Перехватив два шифротекста (сделанных одним ключём, одной PRNG последовательностью) и сделав XOR между ними мы получим XOR между двумя их открытыми текстами. Ни я, ни другие не говорят что вы сразу же получите на экране готовый к чтению открытый текст, но уже банальными методами простейшего криптоанализа, типа статистического, XOR открытых текстов тривиально достаётся особенно когда там человеческое письмо передаётся. Первое чему учит любая книга по прикладной криптографии это про одноразовые шифроблокноты, как идеальную систему шифрования, второе — как-раз что будет если послать два шифротекста одного ключа, третье — никогда не использовать выходы потоковых ключей дважды.
UFO just landed and posted this here
1. Это ваша субъективная оценка что мало. Лично меня и некоторых других пользователей *полностью* удовлетворяет и не напрягает нисколько. Я вот например в GnuPG и в полнодисковом шифровании выставляю Twofish вместо AES, хотя есть AES-NI: да, оно в разы медленнее получается, но зато мне спокойнее в плане безопасности. Смотря какие задачи вы хотите решать. Сделать линк между 10Gbps дата-центрами конечно не пойдёт.
2. А в Raspberry Pi ставят. Go большой, а места там ещё больше. 5 Mbps — вполне удовлетворительно. Смотря какие задачи и требования.
3. Ломается. Обновятся. Если заботится о совместимости дотошно, то так можно дожить и до 2015-го года и иметь всё ещё включённый SSLv3. Salsa20 имеет превосходную безопасность и она is good enough. ChaCha20 не факт что быстрее (зависит от процессора) и даже если и быстрее, то его вклад в процессор на уровне погрешности. Особо переживать по поводу ChaCha vs Salsa не вижу.
4. Почитайте литературу. Для криптографов это фатально и абсолютно непригодно для использования.
5. «Пофиг на дропы». Опять же, с чего вы взяли что это необходимо? Это VPN. Сеть. Сеть может дропать пакеты. Чтобы бороться с этим: используйте TCP, только на уровне выше. Ethernet же не перезапрашивает пакеты.
6. Потому-что если в VPN гонять TCP, то выйдет TCP over TCP. Производительность тут при малейших потерях пакетов будет страдать так, что хоть 3DES будет вместо Salsa20 — ничего не поможет.
7. Этой информации нет. И не планируется. Скорее даже принципиально, дабы не усложнять протокол, превращая его в TLS со всеми вытекающими. С ходу я даже не назову а какую информацию надо передавать. Разве что только heartbeat. О нём действительно в статье нет, но он конечно же есть чтобы давать о себе знать что противоположная сторона жива. Реализован он очень просто: так как у нас TAP, то передаются Ethernet frame-ы, так вот в MAC адресе фрейма прописывается константа HEARTBEAT. В будущем наверное появятся «шумовые» пакеты.
UFO just landed and posted this here
1, 2, 3: вы так и не поняли задачи для которых оно создавалось. Задачи которое творение решает несовместимы с тем что предоставляют закрытые проприетарные ОС. Если вы рассчитывали на них решать задачи связанные с криптографической безопасностью, то это никак не моя оплошность.
5,6: каких например? Я, честно говоря, впервые слышу про то чтобы предъявлялись требования к тому чтобы сеть гарантировала доставку пакетов. Для этого есть транспортные уровни на которых живут TCP.
7. Вопрос совместимости/портируемости: Go работает не под «конкретно перечисленные ядра для которых написали модули», а под ОС предоставляющими «TAP интерфейс и где есть Go». В гораздо меньшем количестве кода я сделал более широкую поддержку платформ. Плюс вопрос безопасности: безусловно можно написать качественный код который бы безопасно можно запускать в ядре, не опасаться за безопасность, но вопрос трудозатра.
UFO just landed and posted this here
Не было про закрытые ОС? Вообще это очевидно. Если нет, то задачи GoVPN действительно будут не понятны и странны.

5,6 — пока вы не приводите конкретики и по мне это абсолютная выдумка. Если есть настолько странный софт который предполагает с какой-то стати что сетевой уровень ему должен гарантировать доставку, то как бы это проблемы такого кривого софта.

Ну что ж, используйте супер быстрый OpenSSL раз вы такой бесстрашный и C до сих пор является юзабельным языком. Человечество доказало что сложные вещи не способно писать на C так чтобы они были без уязвимостей. В OpenSSL фатальных уязвимостей нашли уже гору. Закрывайте на это глаза и радуйтесь производительностью.
> GO — в ядро не засунуть
А вы обратитесь к Леннарту Поттерингу, он еще и не такое засовывать пытался.
Немного не понял вашего описания ECDH.

1.
Curve25519 всё же имеет не все 256 бит задействованными, соответственно, его криптографическая стойкость чуть меньше симметричного аналога 128 бит порога.


Вообще, автор curve25519 описывает пороговый уровень безопасности ECDH c этой кривой в 128 бит. Но значение rho для нее, все-таки, 126 бит: safecurves.cr.yp.to/rho.html

2.
Кроме того, не добропорядочная сторона может использовать специально созданные публичные ключи, которые при перемножении могут давать слабые ключи K: в теории такое не исключено, хотя на практике для Curve25519 не замечено.


Традиционный способ ECDH на curve25519 — это генерировать сессионный ключ после одного раунда hsalsa (или hcacha). Например, как это делал я: github.com/vstakhov/rspamd/blob/master/src/libcryptobox/cryptobox.c#L146 (в nacl там hsalsa).

3.
При этом имеется такое свойство, как нулевое неразглашение (zero-knowledge proof), при котором ни бита информации о PSK-ключе не будет известно злоумышленнику: он получает зашифрованные данные (шум) и единственное, что он может предпринять, так это попытаться дешифровать, но у него нет возможности узнать правильно ли он нашёл публичный ключ (дешифровал ли его), так как он тоже является шумом.


Немного не понял, почему вы считаете, что публичный ключ — это шум? На самом деле, публичный ключ — это точка на кривой, и если его не прятать специально (например, elligator'ом), то отличить его от шума элементарно. Ну и определение zero-knowledge proof все-таки неверно в таком случае.
1. Я брал классическое предположение что биты эллиптических кривых надо разделить на два. 256/2=128. 25519 это 256 бит, но несколько бит которого в приватном ключе явно устанавливаются в чётко заданные значения: раздел «Computing secret keys» на cr.yp.to/ecdh.html
2. Да, действительно выхлоп DH прогоняется через HSalsa: github.com/stargrave/govpn/blob/develop/handshake.go#L109
Я решил опустить эту мелочь из текста, хотя в коде делаю конечно же. Генерирование всё же результирующего секретного ключа из двух половинок передаваемых по каналу это сильно рекомендуемый совет уже из описания EKE протокола. Подчеркну: даже в EKE они говорят что не знают насколько это надо и полезно, лишь паранойя на всякий пожарный
3. Шум с точки зрения внешнего наблюдателя. Для нас это конечно же перемноженный приватный ключ (который является выхлопом PRNG (плюс заменённых нескольких бит)) относительно константной точки
1. Надо делить не биты, а сложность дискретного логарифма, и даже не делить, а брать квадратный корень. Поэтому эти детерминированные биты в приватном ключе по факту не влияют на сложность дискретного логарифма (если вы не собрались, конечно, брутфорсить все 256 бит ключа, тогда да — их надо исключать из сложности такого перебора, но она будет заведомо намного больше, чем 128 бит).

2. Это излишне, если вы применяете hsalsa. Задача атакующего тут в том, чтобы из ключа сервера и собственной ключевой пары подобрать такую пару, чтобы ее умножение давало бы гарантированно слабый ключ для hsalsa. Но это не даст ничего, т.к. выхлоп hsalsa даже со слабым ключом, очевидно, не будет давать слабого ключа для последующих применений salsa (хотя у rc4 есть определенные забавные ключи, да).

3. Передаваемые вами публичные DH ключи — это не шум для внешнего наблюдателя. Если атакующий брутфорсит передаваемые данные, то ему достаточно проверять, лежит ли то, что он получил, на кривой curve25519 (а это делается просто подстановкой данных в уравнение), чтобы понять, правильно ли он расшифровал данные. После чего он получает PSK. Варианты коллизий точек, в принципе, возможны, но все равно мне не кажется, что это zero-proof.
1, 2. Возможно вы и правы. Но ведь хуже же не будет. Это тот же самый «на всякий пожарный» что и игнорирование 256 бит после первых 256 бит из Salsa20 которое делают в SSH и TLS реализациях. Насколько понимаю никто не доказал что они реально могут повлиять на безопасность алгоритма, но на всякий пожарный откидывают, чтобы внутреннее состояние полностью сротировалось. Я не криптограф и не решился отбрасывать рекомендацию DH-EKE по такому генерированию ключей.
3. А мне вот кажется что коллизии там будут и гарантированно и достаточно много. Приватный ключ 25519 можно использовать и без установки трёх бит: то есть чистые 256 выхлопа PRNG, но ведь это тоже будет точкой на кривой. Так что любой рандом можно будет интерпретировать как точку на кривой.
1,2. Игнорируют из-за того, что размер блока сальсы и чачи 512 байт, а шифровать дробными блоками очень трудно и неудобно (т.е. есть негативный эффект на производительность). Да и reference имплементация и не умеет шифровать дробными блоками на самом деле.

3. curve25519 задается уравнением y^2 = x^3 + 486662*x^2 + x. Публичный ключ — это точка на этой кривой в поле 2^255 − 19. Точек, принадлежащих кривой, на этом поле значительно меньше, чем значений в поле. Но поскольку брутфорс салсы требует примерно 2^256 попыток, то да, коллизий будет очень много. Но если предположить, что есть более эффективный способ взлома PRF, то все хуже.
Всё же не очень понимаю где потеря производительности. То что выход Salsa/ChaCha имеет размер в 512 бит — действительно. Но это же не блочный шифр в котором нужно где-то выравнивать или дополнять. Все эти биты нужно XOR-ить с данными и раз уж мы получили какой-то выход, то можно было бы использовать сразу же. Если надо зашифровать 100 бит данных, то одна итерация Salsa/ChaCha даёт 512 бит из которых 256 бы пошли на Poly1305, а остальные 100 из оставшихся 256 на XOR с открытым текстом.

Да, с публичными ключами вы всё же правы. То что мы на вход для секретного подаём 256 бит энтропии не должно означать что эти же 256 бит останутся и в публичном ключе. 25519 как-раз гарантии даёт относительно 128-бит уровня brute force как минимум.
Дело не столько в производительности, сколько в алгоритмическом усложнении. Допустим, мы зашифровали 256 бит подключа, у нас осталось еще 256 бит ключевого потока. Нужно это как-то сохранить в блоке, а потом начать шифровать вначале куском того keystream, что у нас имеется, а потом уже начинать новый раунд пермутаций. Это существенное усложнение кода, и рефренсная имплементация этого не делает. Более того, nacl Бернштайна и libsodium при определении cryptobox и secretbox из-за этого делают вот эти вот уродливые cryptobox_ZEROBYTES = 32, а cryptobox_BOXZEROBYTES = 16, что делает сущим мучением применение этих примитив на практике. То есть, делается так:

Берется весь поток, в котором первые 32 байта (т.е. полный блок chacha/salsa) забиваются нулями. Дальше прилепляется plaintext. Дальше делается xchacha/xsalsa с заданным ключом на все данные (т.е. 32 байта нулей и весь payload). Потом первые 16 байт используются как ключ для poly1305, а в оставшиеся 16 байт записывается mac от шифротекста без первых 32-х байт. Расшифровка еще хуже: берется 32 байта, зануляются, потом по ним делают полную итерацию xchacha/xsalsa и получают искомые 16 (!) байт ключа для poly1305, потом проверяется целостность шифротекста, а дальше прогоняется полная итерация xchacha/xsalsa по всему payload, а первые 32 уже байта забиваются нулями.

Вот такой вот подход позволил избежать кусковых блоков, но с другой стороны добавил лишние нули в конструкции и постоянно требует копирования шифротекста/плейнтекста, что очень неудобно на практике (и в реализации протоколов).
В GoVPN реализации именно так и делается тоже: создаётся участок забитый нулями, на него Salsa20 выхлоп натравливается, где из начала берутся данные для Poly1305, а нужная часть XOR-ится с plaintext-ом. Ну и дешифрование аналогично. Появляются нули, но так действительно проще. В целом начинаю понимать что действительно проще будет делать если итерироваться поблочно по выходам Salsa/ChaCha. Конкретно в Go библиотеке работа с блоками скрыта и там задаётся конкретная длина сколько надо сгенерировать байт.

PS: всё же не 32 байта, а 64 (полный блок) и на вход Poly1305 32 байт, вместо 16 подаётся в качестве ключа.
Ну вот как раз нулей я хотел избежать по причине сложностей с копированием и лишних маркеров для анализаторов (все-таки 16 нулей последовательно нечасто встречаются в реальных данных): github.com/vstakhov/rspamd/blob/master/src/libcryptobox/cryptobox.c#L162

Да, конечно же вторая часть первого блока используется уже для payload. И да, мой подход хуже, если в протоколе много очень коротких сообщений (меньше 32-х байт), т.к. делается дополнительный раунд пермутаций. С другой же стороны, он более скрытный и простой в плане адаптации существующего кода.
Да, еще такой вопрос: откуда вы берете и как передаете PSK в вашей схеме? Ведь я правильно понимаю, что вы генерируете его из пароля (в таком случае вопрос к PRNG становится вообще неясным, для чего нужны вам криптографически стойкие случайные числа).
Нет, сейчас PSK это вне программы сгенерированный ключ. В простейшем случае просто dd if=/dev/random bs=32 count=1: github.com/stargrave/govpn/blob/develop/utils/newclient.sh#L6. Из пароля предполагается генерирование с внедрением Secure Remote Password протокола, пока это на уровне TODO: github.com/stargrave/govpn/blob/develop/TODO#L3

PRNG нужен для создания сессионных ключей, которые действуют только на протяжении одной сессии. PSK используется только для аутентификации сторон на этапе рукопожатия.
Крайне странный подход. Ведь вам нужно этот psk как-то еще и передать между клиентом и сервером. А в случае пароля достаточно взять PBKDF и применить его клиентом и сервером. Или же вообще взять OTR и их 'Socialist millionaire problem' подход к проверке сторон (который, кстати, действительно является zero-proof протоколом).
DH-EKE точно так же является zero-knowledge протоколом (замечу что не я его изобрёл :-), он известен давно). PSK мне не надо передавать. Он используется в дебрях EKE нигде напрямую не передаваясь. В этом и суть DH-EKE. Пароль известный в полной мере и клиенту и серверу — не вариант. PAKE протоколы давно изобретены с приставкой augmented: когда серверй действительно не знает пароля клиента. SRP относится к таким.

В augmented PAKE протоколах пароль в чистом виде известен только клиенту. Сейчас EKE это не augmented схема: PSK известен в равной степени обоим. Поэтому и смотрим в сторону SRP.
Да, я сейчас прочитал про EKE, и понял, что был неправ. Просто из вашей статьи не следует полного описания самого EKE и получения на его основе PSK, отчего я решил, что PSK заранее подкладывается клиенту и серверу.
К сожалению, неюзабельно на embeded платформах из-за GO — развер в даже в 2МБ очень велик.
> Но уже нормальной практикой стало генерирование ключа аутентификации для каждого сообщения на основе выхода Salsa20 PRNG этого пакета.
Можно узнать, где и с каких пор это стало нормальной практикой?
Жесть какая:
The reason for generating the Poly1305 key like this rather than
using key material from the handshake is that handshake key material
is per-session, but for a polynomial MAC, a unique, secret key is
needed per-record.

Обоснование ни о чём. MAC и без этого будет достаточно уникальным, хотя бы потому, что гамма генерируется каждый раз разная, поэтому и MAC от неё будет разный, даже если его через HMAC считать. Плюсы предложенного подхода очень не очевидны. Зато шанс ухудшения криптостойкости ненулевой, так скажем.
Не понимаю, откуда вы предлагаете брать уникальную гамму, если не использовать раунда шифрования.
Так именно оттуда и брать. На данные XOR-ом накладывается уникальная гамма, данные после шифрования оказываются псевдослучайными, от них считается MAC.
MAC считает просто только от зашифрованных данных? А где же секретная часть, ключ? Это какой-то просто хэш получается, а не MAC.
Ключ для MAC берётся на этапе согласования ключей и не совпадает ни с какими другими ключами.
Все хорошо, но откуда вы возьмете ключ для MAC'а? Напомню, что poly1305 в данном виде не содержит финального раунда aes и не принимает, соответственно nonce. У HMAC, напомню также, такой проблемы нет — там можно использовать один и тот же ключ сколь угодно долго. Хотя на практике его все равно ротируют, чтобы ограничить время на поиск коллизий.
Sign up to leave a comment.