ZYCORD docs
Русский
ZycordДокументацияПроверка загруженного файла

Проверка загруженного файла

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

Три проверки, и они отвечают на разные вопросы. Выполняйте их в этом порядке; каждая стоит меньше без предыдущей.

ПроверкаЧто доказываетЧего не доказывает
Контрольная суммаФайл не был изменён при передаче.Ничего о том, кто его произвёл и что внутри.
ПодписьСписок контрольных сумм исходит от держателя ключа проекта.Что этот ключ принадлежит кому-то, кому у вас есть причины доверять.
ПересборкаБинарник содержит этот исходный код и ничего больше.Что исходный код честен — прочтите его или прочтите разборы.

Контрольная сумма#

curl -fsSLO https://zycord.com/releases//download/v<version>/SHA256SUMS.randomx
sha256sum --check --ignore-missing SHA256SUMS.randomx

# on macOS:
shasum -a 256 --check --ignore-missing SHA256SUMS.randomx
--ignore-missing не опционален и не является послаблением

Релизы теперь поставляют только архивы -randomx, поэтому SHA256SUMS.randomx — это список, покрывающий то, что вы скачали; SHA256SUMS.deb и SHA256SUMS.desktop покрывают пакеты Debian и настольный кошелёк. Каждый покрывает несколько файлов, а вы скачали один. Без этого флага пять отсутствующих у вас файлов отмечаются как FAILED open or read, и команда завершается с ненулевым кодом на совершенно исправной загрузке — на той самой странице, которая говорит вам, что несовпадение означает скомпрометированный бинарник. Проверку, чей нормальный результат — сбой, люди приучаются игнорировать.

Подпись#

Подпись пока не опубликована, и этот раздел описывает процедуру на случай, когда она появится

Релизы сейчас поставляют zycord-release-key.asc — открытый ключ — но ничего подписанного им, кроме манифеста обновлятора: ни у одного файла контрольных сумм нет отделённой подписи, и ни один не подписан внутри себя. Поэтому gpg --verify ниже сегодня завершается ошибкой об отсутствующем файле, и это пробел релиза, а не ваша ошибка. Пока он не закрыт, проверка, которая на деле несёт аргумент доверия, — это пересборка: ей не нужна никакая подпись, потому что байты вы получаете сами и сравниваете.

Когда подпись контрольных сумм будет опубликована, она будет сделана ключом проекта. Полный отпечаток таков:

E724 39CE DD85 11F9 D607 550B 87FD 60D5 EB4A 0B29

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

Якорь — это отпечаток, а не файл ключа

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

Его несут три места. Подойдёт любое из них:

# 1. The repository, if you have a clone. No network, no keyserver.
gpg --import packaging/zycord-release-key.asc

# 2. The release page, as an asset beside the archives.
curl -fsSLO https://zycord.com/releases//download/v<version>/zycord-release-key.asc
gpg --import zycord-release-key.asc

# 3. A keyserver. Use this one.
gpg --keyserver hkps://keyserver.ubuntu.com --recv-keys E72439CEDD8511F9D607550B87FD60D5EB4A0B29

Затем подтвердите, что именно попало в вашу связку ключей, прежде чем на это полагаться:

gpg --fingerprint E72439CEDD8511F9D607550B87FD60D5EB4A0B29
Не используйте keys.openpgp.org для этого ключа

Это сервер ключей по умолчанию в нескольких сборках GnuPG, и он отдаёт урезанную копию: голый пакет открытого ключа, без идентификатора пользователя и без самоподписи. GnuPG отвергает такую копию — gpg: key 87FD60D5EB4A0B29: new key but contains no user ID - skipped — и ключ так и не попадает в связку, поэтому проверка ниже падает с тем, что выглядит как неверная подпись, а на деле является отсутствующим ключом. Этот сервер по своим правилам вырезает идентификаторы пользователя, пока через него не подтверждён адрес, а этого псевдонимный проект сделать не может.

gpg --verify SHA256SUMS.randomx.asc SHA256SUMS.randomx

Сегодня это сообщает No such file or directory, потому что ни один релиз ещё не опубликовал такой файл. См. примечание в начале этого раздела.

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

Техническое описание тоже подписано#

У PDF, отдаваемого с этого сайта, рядом лежит отделённая подпись, сделанная тем же ключом:

curl -fsSLO https://zycord.com/assets/zycord-whitepaper.pdf
curl -fsSLO https://zycord.com/assets/zycord-whitepaper.pdf.asc
gpg --verify zycord-whitepaper.pdf.asc zycord-whitepaper.pdf

Пересборка — проверка, которая на деле заменяет сертификат#

Хеш говорит вам, что файл не был изменён при передаче. Он ничего не говорит о том, что издатель в него положил. А вот это говорит:

git clone https://gitlab.com/zycord-group/zycord-node.git
cd zycord-node
git checkout v<version>
make build
sha256sum bin/zcd bin/zycordd

Сравните с SHA256SUMS.binaries из релиза. Они должны совпасть точь-в-точь. Если совпали, то скачанный вами бинарник содержит этот исходный код и ничего больше — утверждение, которого ни один сертификат никогда ни о чём не делал.

Набор инструментов Go — часть того, что вы воспроизводите#

Это go1.26.2. Один и тот же исходный код, собранный двумя разными выпусками Go, — это два разных бинарника; это не тонкость, это измеримо — собственный релизный процесс этого репозитория однажды зафиксировал три разных значения SHA-256 для одного коммита и одного набора флагов, по одному на версию Go. Поэтому make build закрепляет GOTOOLCHAIN=go1.26.2 и останавливается с пояснением, если этот набор инструментов недоступен, вместо того чтобы выдать несовпадение, выглядящее как подделка, ради обнаружения которой вся эта страница и существует.

Два полезных следствия:

  • Вам не нужно доверять версии, написанной выше. Выпущенный бинарник сам её сообщает: go version -m zcd печатает набор инструментов, которым он собран, рядом с модулем и флагами сборки. Если эта строка и закрепление в Makefile когда-либо разойдутся, бинарник собран не так, как говорит эта страница.
  • Выгрузка старого тега выгружает вместе с исходным кодом и его закрепление, так что пересборка старого релиза продолжает работать и после перехода проекта на более новый Go.

Переводы строк здесь — часть исходного кода#

wallet/webui встраивает фронтенд кошелька через //go:embed, поэтому переводы строк в этих файлах — это байты в бинарнике: рабочая копия, преобразованная в CRLF, собирает другой zcd из того же коммита — несовпадение с невинной причиной и пугающим видом. Файл .gitattributes со строкой * text=auto eol=lf даёт LF в рабочем дереве на любой платформе и при любой конфигурации git, так что свежий клон даёт один и тот же ответ везде.

Два случая, которые он не покрывает: пересборка тега старше этого файла (задайте core.autocrlf=input перед выгрузкой) и уже существующий клон, сделанный с core.autocrlf=true, который не исправляется при получении изменений.

Архивы -randomx невоспроизводимы по устройству

RandomX написан на C++, поэтому сборка с cgo уносит в результат системный набор инструментов C, и никто не может пересобрать её байт в байт. Контрольные суммы этих архивов лежат в SHA256SUMS.randomx, и они намеренно отсутствуют в SHA256SUMS.binaries, который перечисляет, какие хеши должна дать сборка, которую вы делаете из исходного кода. Это единственное место, где уровень, подключающийся к сети, и уровень, который аттестован, не пересекаются — см. таблицу двух уровней в разделе Установка. Смысл в том, что это сказано вслух: это ваше решение, а не предположение, сделанное за вас.

Проверьте реализацию на соответствие протоколу#

Отдельно от проверки происхождения бинарника вы можете проверить, что он реализует протокол. Эталонные векторы и есть протокол; независимая реализация, проходящая их, — равноправный участник, а не форк.

zcd vectors            # check this build against spec/vectors
zcd genesis --testnet  # rebuild block 0 and print its id
zcd params --testnet   # print the frozen parameters

zcd genesis — важнейшая из команд: объявление о запуске обязуется, за недели вперёд, к тегу кода, хешу параметров и идентификатору генезис-блока — и эта команда пересобирает всё это за миллисекунды, из исходного кода, на любой машине. Значения публичного testnet приведены на странице testnet; сборка, печатающая другие, — это сборка на другой цепочке, и она не подключится.

Независимые аттестации#

Один человек, пересобравший тег, доказывает, что тег воспроизводим. Несколько незнакомых людей, пересобравших его и подписавших результат, доказывают заметно больше, и именно к этому образцу серьёзные проекты пришли ровно по этой причине. Пересоберите тег, а затем опубликуйте полученный дайджест и собранный тег в ветке анонса — в том числе если он не совпал: именно об этом случае и стоит услышать.