По мотивам очередного выступления

В эту субботу в очередной раз собрались обсуждать электронные выборы, и в этот раз ступора уже не было — то ли Шевяков не курил в камеру, то ли действительно надо привыкать к «публичным» выступлениям в Зуме :) Полную запись можно посмотреть на ютубе, а тут — перескажу свои основные тезисы.

Московская голосовалка — вопреки всем ожиданиям — отработала более-менее нормально, и это не может не радовать. О технических сбоях вроде остановки выгрузки данных и редких падениях сайта для наблюдения до меня уже сказали, я хочу добавить немного о проблемах скорее организационного характера.

Начну с того, что тайна голосования, которая волнует довольно многих избирателей и экспертов, действительно держалась на честном слове ДИТа. Это сложно назвать виной разработчиков и эксплуатантов системы – так уж получилось, что занимается этим ровно одно ведомство, а надо разделять систему как минимум на две части — чуть дальше станет понятно, почему, но Александр Исавнин действительно много раз задавал вопрос об этом, а ответов лучше, чем “поверьте нам на слово” техническая рабочая группа так и не получила. Опять же, отмечу, вслед за Олегом, что фактов нарушения тайны голосования пока никто не зафиксировал.

С другой стороны — некоторые технические меры для защиты тайны голосования были приняты. Да, при изучении кода системы заметно, что авторы попытались реализовать вариант хорошо известного «протокола двух агентств«, который защищает тайну голосования, и в принципе система позволяет разнести авторизацию пользователя и собственно голосование по разным ведомствам, что критично для этого семейства протоколов. Это в целом довольно положительно характеризует разработчиков системы — как минимум обращение к известным протоколам позволяет избавиться от всевозможных неожиданностей.

Чуть подробнее опишу протокол голосования — при этом постараюсь изложить это все максимально упрощенно. К сожалению, в Википедии описан похожий, но отличающийся протокол, а «Прикладная криптография» Шнайера есть под рукой далеко не у всех — хотя протокол, похожий на ДИТовский, там описан под названием «Голосование с двумя Центральными комиссиями». Основаны все эти протоколы на криптографии с открытым ключом — здесь знать о ней надо лишь то, что используется пара из открытого и закрытого ключа, таких, что сообщение, зашифрованное открытым ключом, можно расшифровать только с помощью закрытого, и наоборот — если сообщение зашифровано закрытым ключом, то оно расшифровывается открытым. Закрытый ключ обычно держится в секрете, а открытый доступен всем.

Итак, для начала — подготовка к голосованию, которая с точки зрения криптографии состоит в том, что создается пара из открытого и закрытого ключа. Закрытый ключ разделяется на части, которые передаются членам избирательной комиссии — а они, как и на обычных выборах, представляют самые разные политические силы — например, в этот раз одним из членов комиссии был Григорий Мелконянц из «Голоса«. Главное здесь это то, что закрытый ключ не будет известен никому вплоть до момента его «сборки» — а открытый ключ, наоборот, будет опубликован во время голосования. Происходит процедура генерации и разделения ключей в торжественной обстановке, с банкетом, фуршетом, журналистками с декольте — в общем, «сожалею, что не был при сей баталии хотя бы мичманом!»

Дальше происходит собственно голосование — пройдя авторизацию на «Госуслугах» или mos.ru, избиратель получает от сервера регистрации уникальный номер (GUID) и перенаправляется на сервер голосования, по адресу «$host/election/check/$guid» (строка 94 файла Ballot.php в приложении form, опубликованном в ДИТовском гитхабе).

Сервер голосования — это приложение ballot (обратите внимание, что работало оно на другом домене — авторизация происходила на 2020og.ru, а собственно голосование — на elec.moscow, можно считать это демонстрацией возможности разделения авторизации и голосования), и там нам очень интересно содержимое файла election.js — точнее, то, что начинается после 243 строки. Там происходит следующее: с помощью библиотеки NaCl создается пара из «пользовательского» открытого и закрытого ключа, случайным образом выбирается значение nonce, сообщение из выбора избирателя и nonce зашифровывается сначала с помощью закрытого ключа избирателя, а затем — с помощью открытого ключа системы голосования. Пара из зашифрованного таким образом сообщения и открытого ключа избирателя обладает следующим очень полезным свойством — зная закрытый ключ системы голосования, можно убедиться, что сообщение (голос) зашифровано именно закрытым ключом избирателя, и никаким другим; не зная закрытого ключа избирателя, невозможно «подменить» голос; не зная закрытого ключа системы голосования — нельзя сделать с этим сообщением вообще ничего.

Затем пара из GUID и зашифрованного голоса отправляется на сервер голосования, где GUID проверяется на достоверность — что он действительно был выдан сервером регистрации, и по нему еще не голосовали, а зашифрованный голос в случае успешной проверки сохраняется — в данном голосовании в блокчейн, но в принципе это может быть любая база данных или вообще файлик на диске. Списки проголосовавших избирателей доступен наблюдателям, список зашифрованных голосов — вообще всем (в ходе голосования на специальном сайте транслировались транзакции блокчейна, а раз в полчаса они выгружались в файлы csv).

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

Попробуем теперь перечислить свойства такой системы.

  • Получить GUID и проголосовать могут лишь зарегистрированные избиратели — это обеспечивается не только криптографией, но и тем, что авторизацией пользователей занимаются «Госуслуги»;
  • Cервер голосования не может «вбрасывать» в хранилище голоса по своему усмотрению — их не может быть больше, чем на сервере авторизации было создано GUID’ов (список избирателей с отметками, кто голосовал, а кто нет, доступен для просмотра наблюдателям, как и на обычных «бумажных» выборах);
  • В ходе голосования голос пользователя расшифровать нельзя (и, допустим, отклонить его под видом технической ошибки);
  • После голосования голос пользователя нельзя изменить (так как никому, кроме самого пользователя, неизвестен закрытый ключ — и то для его сохранения надо предпринять некие усилия);
  • Каждый голосовавший может найти свой голос в опубликованных результатах;
  • Каждый может самостоятельно проверить правильность подсчета голосов;
  • Если сервер авторизации не сохраняет выданные пользователям GUID’ы, а сервер голосования не сохраняет связку между GUID и голосом (тут придется поверить разработчикам и эксплуатантам на слово — но скорее всего, это так) — никто не может узнать, какой голос принадлежит какому пользователю. Кстати, обращу внимание, что для раскрытия тайны голосования требуются согласованные действия операторов сервера авторизации и голосования — собственно, поэтому этот протокол и называется «протоколом двух агентств».

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

Теперь перейду к плохому. Во-первых — зачем я полез смотреть код? Полез я туда именно для того, чтобы посмотреть, какой конкретно протокол голосования там реализован, и повторюсь, остался более-менее доволен увиденным — но хочу сказать, что программистом на PHP и Javascript я не являюсь, и гораздо проще было бы прочитать описание алгоритма голосования в более явном виде. Те же ГОСТы 34 серии предусматривают документ под названием «Описание алгоритма» — и может быть, я бы успокоился, увидев его и сравнив с реализацией. Кстати, еще две шпилечки в адрес ДИТа — во-первых, на вопрос «где же, все-таки, предусмотренная ГОСТами документация», был дан ответ в духе «ну мы систему запустили, документацию напишем потом». Хочу заметить, что у них на сайте выложен ГОСТ 34.201-89, а жить по нему они не хотят — там ясно сказано, что документ под названием «Описание алгоритма», например, пишется на этапе технического проекта, еще до разработки каких-либо программ, и уж точно — до ввода в эксплуатацию. Точно так же хотелось бы напомнить о существовании ГОСТ РД 50-34.698-90, где можно увидеть мои хотелки в плане описания криптографических протоколов в разделе 7.1.

Вообще, в плане открытости и прозрачности электронного голосования есть куда расти. Это вовсе не какие-то абстрактные соображения, информация о работе системы и том, как в ней все устроено, должна быть доступна для широкого круга заинтересованных лиц, а не избранных «экспертов» — с которыми еще и делились информацией крайне неохотно. В противном случае мы получаем, например, пресловутую публикацию «Медузы» о том, что оказывается, если знать ключи шифрования и случайное число (то самое nonce), выбранное браузером пользователя при подготовке зашифрованного бюллетеня к отправке, можно проверить, правильно ли учтен этот бюллетень в итоговом протоколе. Открытие это сродни торжественной констатации факта «вода — мокрая».

Вообще, во многих алгоритмах тайного голосования возможность проверить правильность учета своего бюллетеня, найдя его в итоговом протоколе, предусмотрена штатно (к ним относятся и вышеназванные) — хотя тот же Шнайер все же намекает, что такая возможность при неправильном ее использовании — прямой путь к организованной скупке голосов. Здесь же получилось так, что из-за некоторой скрытности авторов системы голосования возможность проверить правильность своего голоса журналисты объявили «уязвимостью».

Довольно странно была организована и публикация исходных кодов системы — опубликованы были лишь два обеспечивающих голосование веб-приложения и код смарт-контрактов блокчейна, причем некоторые особенно интересные с точки зрения стойкости шифрования и сохраняемой информации места в исходном коде были почищены. Примерно так же выглядела и переданная рабочей группе «документация», причем местами доходило до смешного — цитирую один из документов: «хеш длиной YYY кодируется в XXX для сохранения целостности». При этом узнать длину хеша и способ его кодирования можно было совершенно тривиальным образом — например, открыв отладчик страницы во время голосования или заглянув в опубликованные исходники. Стоит еще сказать, что местами исходный код производит впечатление полуготового прототипа, к примеру, в некоторых местах остались комментарии в духе «удалить после тестирования».

Кстати, к вопросу об отладчике — получить представление о работе системы голосования можно было бы во время тестирования. К сожалению, тестовое голосование было доступно лишь для избирателей, уже имеющих право голоса на реальном голосовании — то есть жители Московской области, желающие посмотреть, как что там устроено, оказались в пролете. К настоящему тестированию, с другой стороны, это не имело никакого отношения — возможность проголосовать давалась лишь один раз, так что сделать несколько попыток и посмотреть, «что будет, если» было невозможно.

Еще одно странное явление — это подключение некоей «системы антифрода» (по словам представителей ДИТ), которая изначально не была заявлена. Фактически на каждую веб-страницу голосования внедрялся посторонний код на Javascript, не выложенный в публичный доступ заранее.

Скажу еще немного о блокчейне. Довольно часто говорят, что именно благодаря блокчейну эта система голосования надежна и безопасна. Вот даже на ютубе в комментариях задали вопрос — «СМИ писали, что система надёжно защищена и использование блокчейна гарантирует от подмены голосов и деанонимизации, так ли это?» — на самом деле это не совсем так. Блокчейн обеспечивает хранение уже принятых голосов, и существенно затрудняет какие-либо изменения данных постфактум — но в «модели угроз» для электронного голосования это лишь один из многих рисков. О том, как система защищена от подмены голосов и деанонимизации я сказал выше, блокчейн как таковой для этого не нужен. Впрочем, если в этот раз блокчейн работал почти хорошо (за исключением его “падения” на несколько часов в первый день голосования) – то почему бы и нет? С другой стороны, представляется, что блокчейн в целом — это «узкое место» системы, Александр Щербаков высказывал свои соображения по этому поводу.

Наблюдение за выборами — еще один не до конца проработанный вопрос. Например, не опубликован исходный код веб-приложения для наблюдателей — но скорее всего, каких-либо попыток скрыть попадающую в блокчейн информацию не предпринималось, по трудозатратам это эквивалентно созданию еще одной, «параллельной» системы голосования. Был довольно длительный период, когда не работала выгрузка данных о голосовании — по причинам, которые были попросту не предусмотрены или забыты в момент разработки. В теории это могло бы стать основанием не доверять голосам, поданным в этот период — с другой стороны, каких-либо аномалий там обнаружено не было, наоборот, было два заметных скачка голосов «против».

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

В целом, конечно, вопросы к разработчикам имеющейся системы голосования — скорее не технические, а организационные. Повторюсь, что с точки зрения используемых протоколов голосования система довольно адекватна, а с точки зрения реализации — к сожалению, пока приходится верить на слово, что используемая система голосования совпадает с тем, что было показано публике. В будущем, конечно, хотелось бы иметь возможность изучить систему голосования не только по кускам кода на Github, а еще и по более-менее нормальной документации, причем целиком, а не отдельными частями «тут покажем, тут не покажем».

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *