Проверка релизов Zcash
Кратко
- Скачать бинарный файл Zcash — не то же самое, что получить именно тот файл, который опубликовал проект. Проверка позволяет увидеть разницу.
- Контрольная сумма доказывает, что файл дошёл без повреждений. Подпись доказывает, кто его выпустил. Нужны обе проверки, и сама по себе контрольная сумма доказывает очень мало.
- Zebra публикует файл
SHA256SUMS и комплект Sigstore, который привязывает релиз к конкретному workflow GitHub Actions, тегу и коммиту — управление ключами не требуется.
- Zallet публикует отделённые GPG-подписи (
.asc) вместе с SLSA provenance и SBOM.
- В 2026 году ключ подписи Zcash был заменён: вместо Electric Coin Company используется Zcash Open Development Lab (ZODL). Если вы проверяли старые релизы, вам нужен новый ключ, а заявление о передаче подписано обоими ключами, так что саму ротацию тоже можно проверить.
gpg сообщает о подключе, которым был подписан файл, а не об основном ключе, указанном в объявлениях. Отпечаток, который выглядит неправильным, обычно оказывается подключом, а не атакой.
- Если проверка не проходит, не запускайте бинарный файл.
Проверено на Zebra v6.3.0 и Zallet v0.1.0-beta.2 по состоянию на 2026-08-18.
Почему для Zcash это особенно важно
Подменённый бинарный файл кошелька может украсть spending key или viewing key. В отличие от скомпрометированного пароля, такая потеря необратима: нет ни отката, ни чарджбэка, ни службы поддержки. Shielded-транзакции защищают то, что происходит в блокчейне — но вообще никак не защищают, если используемое вами ПО было подменено ещё до того, как дошло до вас.
Это один из немногих путей атаки, при котором гарантии приватности самого протокола просто не имеют значения. Проверка — это тот слой, который закрывает этот риск.
Модель угроз — что проверка обнаруживает, а что нет
Обнаруживает:
- Подменённое зеркало или изменённый файл, выданный не со страницы релиза проекта.
- Подмену «человек посередине» во время загрузки.
- Скомпрометированный CDN или захваченный хост распространения.
- Случайное повреждение при передаче.
Не обнаруживает:
- Сопровождающего, который подписал вредоносный код. Подпись проверится корректно; она доказывает происхождение, а не намерения.
- Скомпрометированную машину сборки, которая создаёт подписанный, но вредоносный артефакт. Именно для сужения этого риска существуют воспроизводимые сборки и attestations происхождения.
- Ключ, полученный из того же скомпрометированного источника, что и бинарный файл. Если атакующий контролирует и файл, и ключ, с которым вы его сверяете, проверка вам ничего не скажет.
Именно этот последний момент большинство руководств пропускает. Источник ключа так же важен, как и запуск самой команды.
Часть 1 — Zebra: контрольные суммы и Sigstore
Zebra публикует для каждого релиза следующие артефакты:
| Артефакт | Назначение |
|---|
zebrad-<version>-<arch>.tar.gz | архив с бинарным файлом |
zebrad-<version>-<arch>.tar.gz.sha256 | контрольная сумма для конкретного файла |
SHA256SUMS | контрольные суммы для всех архитектур |
SHA256SUMS.sigstore.json | комплект Sigstore, подписывающий SHA256SUMS |
Шаг 1 — Загрузка
Code-highlight
BASE=https://github.com/ZcashFoundation/zebra/releases/download/v6.3.0
curl -sLO $BASE/zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz
curl -sLO $BASE/SHA256SUMS
curl -sLO $BASE/SHA256SUMS.sigstore.json
Шаг 2 — Проверка контрольной суммы
Code-highlight
sha256sum -c --ignore-missing SHA256SUMS
Реальный вывод:
Code-highlight
zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz: OK
Здесь обязателен --ignore-missing, потому что SHA256SUMS покрывает все архитектуры, а вы скачали только одну. Без него sha256sum сообщит об отсутствии архива aarch64 как об ошибке, и можно по ошибке принять успешную проверку за провал.
Вариант для отдельного файла тоже работает:
Code-highlight
sha256sum -c zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz.sha256
Code-highlight
zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz: OK
Одного этого шага недостаточно. Вы скачали контрольную сумму из того же места, что и бинарный файл. Тот, кто смог бы подменить одно, смог бы подменить и другое. Контрольная сумма доказывает целостность; следующий шаг доказывает происхождение.
Шаг 2b — Та же проверка в Windows
В PowerShell нет режима проверки -c, поэтому сравнение выполняется вручную:
Code-highlight
Get-FileHash .\zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz -Algorithm SHA256 | Format-List
Реальный вывод:
Code-highlight
Algorithm : SHA256
Hash : 86326F5324F4E59CC2008C15F94407CC8D5FEACF75D64942164BB5F08ECA8C5E
Path : \\wsl$\Ubuntu\home\briefking\verify\zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz
Сравните это с результатом Linux выше на этой странице:
Code-highlight
86326f5324f4e59cc2008c15f94407cc8d5feacf75d64942164bb5f08eca8c5e
86326F5324F4E59CC2008C15F94407CC8D5FEACF75D64942164BB5F08ECA8C5E
Значения идентичны. Для шестнадцатеричной записи регистр не имеет значения, и это самая распространённая ложная тревога в Windows.
Ещё две ловушки, характерные для Windows:
- Здесь нет кода возврата, который можно проверить. В Linux
sha256sum -c возвращает 1 при ошибке, и скрипт может на это отреагировать. Get-FileHash только выводит хеш: сравнение делаете вы сами, и ошибиться можно просто бегло просмотрев вывод.
- Ненадёжно сравнивать 64 шестнадцатеричных символа глазами. Пусть это делает оболочка:
Code-highlight
$expected = "86326f5324f4e59cc2008c15f94407cc8d5feacf75d64942164bb5f08eca8c5e"
$actual = (Get-FileHash .\zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz -Algorithm SHA256).Hash.ToLower()
if ($actual -eq $expected) { "OK" } else { "MISMATCH" }
В macOS: процесс тот же, но в BSD userland поставляется shasum, а не sha256sum — используйте shasum -a 256 -c --ignore-missing SHA256SUMS. У автора этой страницы не было под рукой компьютера с macOS, поэтому команда документирована по инструментам Apple, а не по фактическому запуску. Если вы проверяете на macOS, пожалуйста, откройте PR и подтвердите или исправьте её.
Шаг 3 — Проверка комплекта Sigstore
Sigstore заменяет долгоживущие ключи подписи краткоживущими сертификатами, привязанными к CI-идентичности и записанными в публичный журнал прозрачности. Никто не хранит ключ релиза, который можно украсть.
Прямой путь использует cosign:
Code-highlight
cosign verify-blob \
--bundle SHA256SUMS.sigstore.json \
--certificate-identity-regexp '^https://github\.com/ZcashFoundation/zebra/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
SHA256SUMS
Эти два флага --certificate-* и есть весь смысл. Без них вы лишь подтверждаете, что кто-то где-то подписал файл. С ними вы подтверждаете, что файл был подписан workflow в репозитории Zebra, прошедшим аутентификацию через OIDC-issuer GitHub.
⚠️ Версия имеет значение. Старые сборки cosign не умеют читать текущий формат комплектов Sigstore. Если запустить приведённую выше команду с cosign v2.4.1, получится:
Code-highlight
Error: bundle does not contain cert for verification, please provide public key
Сертификат в комплекте есть — он находится по пути verificationMaterial.certificate.rawBytes, который старые релизы не проверяют. Это ограничение клиента, а не сломанный релиз. Если вы столкнулись с этим, обновите cosign, а не делайте вывод, что загрузка повреждена. Cosign из пакетных репозиториев дистрибутивов часто заметно отстаёт от upstream.
Следующие два шага показывают, как вручную проверить тот же комплект, и это полезно понимать в любом случае — а также это рабочий запасной вариант, когда ваша сборка cosign не хочет сотрудничать.
Шаг 4 — Посмотрите, что именно утверждает сертификат
Вы можете изучить комплект без cosign, что полезно для понимания того, чему именно вы доверяете. Извлеките сертификат:
Code-highlight
python3 -c "
import json,base64
d=json.load(open('SHA256SUMS.sigstore.json'))
open('cert.der','wb').write(base64.b64decode(d['verificationMaterial']['certificate']['rawBytes']))"
openssl x509 -in cert.der -inform DER -noout -issuer -ext subjectAltName
Реальный вывод для Zebra v6.3.0:
Code-highlight
issuer=O = sigstore.dev, CN = sigstore-intermediate
X509v3 Subject Alternative Name: critical
URI:https://github.com/ZcashFoundation/zebra/.github/workflows/zfnd-release-binaries.yml@refs/tags/v6.3.0
Subject Alternative Name — это идентичность. Там указаны репозиторий, точный файл workflow и тег. Sigstore также встраивает дополнительную метаинформацию о сборке в пользовательские расширения:
| Поле | Значение для v6.3.0 |
|---|
| OIDC issuer | https://token.actions.githubusercontent.com |
| Source repository | https://github.com/ZcashFoundation/zebra |
| Build commit | f5c5277fe41eba9c74f37098738f93f35dd70d60 |
| Ref | refs/tags/v6.3.0 |
| Runner environment | github-hosted |
| Workflow run | .../actions/runs/31424510487/attempts/1 |
| Repository visibility | public |
Каждое из этих значений можно проверить. Хеш коммита должен соответствовать тегу в репозитории; запуск workflow должен существовать и быть публичным.
Шаг 5 — Криптографическая проверка подписи
Вы можете подтвердить подпись напрямую через OpenSSL:
Code-highlight
python3 -c "
import json,base64
d=json.load(open('SHA256SUMS.sigstore.json'))
open('sig.bin','wb').write(base64.b64decode(d['messageSignature']['signature']))"
openssl x509 -in cert.der -inform DER -pubkey -noout > pub.pem
openssl dgst -sha256 -verify pub.pem -signature sig.bin SHA256SUMS
Реальный вывод:
Code-highlight
Verified OK
Комплект также содержит дайджест подписанного содержимого. Убедитесь, что он совпадает с вашим локальным файлом:
Code-highlight
bundle digest : 3eb5de0634f637e793d0411b6c7108802a36e1219f9151803ecc6108fd0f59f6
local digest : 3eb5de0634f637e793d0411b6c7108802a36e1219f9151803ecc6108fd0f59f6
Шаг 6 — Запись в журнале прозрачности
Комплект содержит запись Rekor, подтверждающую, что подпись была опубликована в публичном append-only журнале:
| Поле | Значение |
|---|
| Rekor log index | 2412071838 |
| Entry type | hashedrekord v0.0.1 |
| Integrated at | 2026-08-10 19:43:09 UTC |
Именно это делает обнаружимым скрытое злоупотребление ключом. Подпись, которая никогда не появлялась в журнале или появилась в неправдоподобное время, — это сигнал, на который стоит реагировать. Сравните время интеграции с объявлением о релизе.
Примечание о пути через OpenSSL: он проверяет подпись по открытому ключу из сертификата, но сам по себе не валидирует цепочку сертификатов до корневого сертификата Sigstore и не проверяет inclusion proof записи журнала. cosign verify-blob делает все три проверки. Используйте OpenSSL, чтобы понять механизм; используйте cosign для реальной проверки.
Часть 2 — GPG-подписи Zallet
Zallet публикует другой набор артефактов:
| Артефакт | Назначение |
|---|
zallet-<version>-<platform>.tar.gz | архив с бинарным файлом |
.tar.gz.asc | отделённая GPG-подпись |
.tar.gz.intoto.jsonl | SLSA attestation происхождения |
.tar.gz.provenance.json | метаданные происхождения |
.tar.gz.sbom.spdx | программная ведомость материалов |
Шаг 1 — Определите ключ подписи до того, как начнёте его искать
Сначала запустите проверку без импортированного ключа:
Code-highlight
gpg --verify zallet-v0.1.0-beta.2-linux-amd64.tar.gz.asc \
zallet-v0.1.0-beta.2-linux-amd64.tar.gz
Реальный вывод:
Code-highlight
gpg: Signature made Tue Jul 28 19:18:44 2026 WAT
gpg: using RSA key 1FE99324758F296718B457067F4BBBBA23F0617F
gpg: issuer "sysadmin@zodl.com"
gpg: Can't check signature: No public key
Это не ошибка. Этот вывод показывает, что подпись существует, и точно указывает, какой именно ключ вам нужен, ещё до того, как вы начнёте его искать. Запишите отпечаток и issuer, а затем получите ключ из источника, независимого от загрузки.
gpg выводит временные метки в вашем локальном часовом поясе. В примере выше показано WAT (UTC+1); в другом месте та же подпись будет отображаться как 18:18:44 UTC. Это один и тот же момент времени. Не считайте разницу часового пояса несовпадением.
Шаг 2 — Импортируйте ключ и выполните проверку
Code-highlight
curl -sL https://apt.z.cash/zodl.asc -o zodl.asc
gpg --import zodl.asc
gpg --verify zallet-v0.1.0-beta.2-linux-amd64.tar.gz.asc \
zallet-v0.1.0-beta.2-linux-amd64.tar.gz
Реальный вывод:
Code-highlight
gpg: Signature made Tue Jul 28 19:18:44 2026 WAT
gpg: using RSA key 1FE99324758F296718B457067F4BBBBA23F0617F
gpg: issuer "sysadmin@zodl.com"
gpg: Good signature from "Zcash Open Development Lab (ZODL) (Dallas, Texas) <sysadmin@zodl.com>" [unknown]
gpg: WARNING: The key's User ID is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 0338 34DD 49DE CF9D BB99 34BC 6C93 CA8E 58E2 6AB1
Subkey fingerprint: 1FE9 9324 758F 2967 18B4 5706 7F4B BBBA 23F0 617F
Good signature — это именно то, что вам нужно. Людей обычно смущают две вещи в этом выводе, и обе нормальны.
Почему отпечаток не совпадает с объявлением
В заявлении о переходе на ключ ZODL указан отпечаток 0338 34DD 49DE CF9D BB99 34BC 6C93 CA8E 58E2 6AB1. Но gpg --verify сообщил 1FE9 9324 … 23F0 617F. Это выглядит как несовпадение, но таковым не является.
gpg сообщает о подключе, которым была сделана подпись. В объявлении указан основной ключ. Подтвердите связь самостоятельно:
Code-highlight
gpg --list-keys --with-subkey-fingerprints sysadmin@zodl.com
Реальный вывод:
Code-highlight
pub rsa4096 2026-03-23 [SCEA]
033834DD49DECF9DBB9934BC6C93CA8E58E26AB1
uid [ unknown] Zcash Open Development Lab (ZODL) (Dallas, Texas) <sysadmin@zodl.com>
sub rsa4096 2026-03-23 [SEA]
1FE99324758F296718B457067F4BBBBA23F0617F
Строка sub — это подписывающий подключ; строка pub — основной ключ. Одна идентичность, один комплект ключей. Именно поэтому вывод проверки печатает оба отпечатка: сравнивайте основной ключ с любым опубликованным объявлением, а строку подключа воспринимайте как указание на то, какая часть ключа выполнила работу.
Такое разделение ключей сделано намеренно: подписывающий подключ можно ротировать или отозвать, не отказываясь от основной идентичности и накопленного к ней доверия.
Что означает предупреждение [unknown]
Code-highlight
gpg: WARNING: The key's User ID is not certified with a trusted signature!
Это не проблема с подписью. Подпись криптографически валидна — именно это и означает Good signature. Предупреждение говорит о другом: вы не сообщили своей локальной GnuPG, что верите в принадлежность этого ключа тому, за кого он себя выдаёт.
GnuPG разделяет два вопроса:
- Этот файл подписан данным ключом? — ответ даёт
Good signature. Это криптография, без человеческой оценки.
- Этот ключ действительно принадлежит ZODL? — на это криптография вообще не отвечает. Это устанавливается проверкой отпечатка по независимому источнику.
Вы увидите это предупреждение почти при любой проверке, если специально не подпишете ключ локально. Не считайте его ошибкой. А вот отсутствие Good signature уже считайте ошибкой.
Шаг 3 — Проверьте сам переход на новый ключ
Подписание релизов Zcash в 2026 году перешло от Electric Coin Company к Zcash Open Development Lab после того, как ZODL была создана в январе 2026 года бывшей инженерной и продуктовой командой ECC.
| Старый ключ | Новый ключ |
|---|
| Отпечаток | B1C9 095E AA18 48DB B54D 9DDA 1D05 FDC6 6B37 2CFE | 0338 34DD 49DE CF9D BB99 34BC 6C93 CA8E 58E2 6AB1 |
| UID | Zcash Master Signing Key (ECC) <sysadmin@z.cash> | Zcash Open Development Lab (ZODL) <sysadmin@zodl.com> |
| Тип | RSA 3072-bit, created 2023-06-19 | RSA 4096-bit, created 2026-03-23, expires 2028-03-22 |
| Опубликован по адресу | https://apt.z.cash/zcash.asc | https://apt.z.cash/zodl.asc |
Опубликованная хронология: новый ключ сгенерирован 2026-03-23, объявлен 2026-03-27, используется эксклюзивно с 2026-04-23, отзыв старого ключа ECC запланирован на 2026-06-23.
Объявление о ротации на сайте надёжно ровно настолько, насколько надёжен сам сайт. Правильный механизм — это заявление, открыто подписанное обоими ключами, чтобы старый ключ поручился за новый. ZODL публикует именно такой документ:
Code-highlight
curl -sL https://zodl.com/security/key-transition.txt.asc -o key-transition.txt.asc
curl -sL https://apt.z.cash/zcash.asc -o zcash.asc
gpg --import zcash.asc
gpg --verify key-transition.txt.asc
Реальный вывод (сокращённо — две подписи на одном документе):
Code-highlight
gpg: Signature made Fri Mar 27 01:11:14 2026 WAT
gpg: using RSA key B1C9095EAA1848DBB54D9DDA1D05FDC66B372CFE
gpg: issuer "sysadmin@z.cash"
gpg: Good signature from "Zcash Master Signing Key (Electric Coin Company) <sysadmin@z.cash>" [unknown]
Primary key fingerprint: B1C9 095E AA18 48DB B54D 9DDA 1D05 FDC6 6B37 2CFE
gpg: Signature made Fri Mar 27 01:11:14 2026 WAT
gpg: using RSA key 1FE99324758F296718B457067F4BBBBA23F0617F
gpg: issuer "sysadmin@zodl.com"
gpg: Good signature from "Zcash Open Development Lab (ZODL) (Dallas, Texas) <sysadmin@zodl.com>" [unknown]
Primary key fingerprint: 0338 34DD 49DE CF9D BB99 34BC 6C93 CA8E 58E2 6AB1
Subkey fingerprint: 1FE9 9324 758F 2967 18B4 5706 7F4B BBBA 23F0 617F
Два результата Good signature на одном документе: от старого ключа и от нового. Если вы доверяли ключу ECC для более ранних релизов, теперь это доверие переносится на ключ ZODL без необходимости доверять zodl.com, apt.z.cash или сообщению на форуме. Именно такое свойство и нужно искать, когда проект ротирует ключи, и его отсутствие — хороший повод задать вопрос.
Где брать ключ — и где не стоит
В порядке от лучшего к худшему:
- Заявление, подписанное предыдущим ключом, как выше. После ротации это самый сильный вариант.
- Источник, независимый от загрузки. Бинарный файл пришёл с GitHub; ключ пришёл с
apt.z.cash. Атакующему нужно контролировать оба.
- Сервер ключей, перепроверенный по опубликованному отпечатку. На большинстве серверов ключей любой может загрузить ключ с любым заявленным именем. Безопасность здесь обеспечивает сравнение отпечатка, а не сам сервер.
- Та же страница, что и бинарный файл. Почти никакой гарантии. Кто может подменить одно, может подменить и другое.
Всегда сравнивайте полный отпечаток с основным ключом. Короткие key ID тривиально коллидируют и уже использовались в реальных атаках.
Часть 3 — Проверка, которая не проходит
Проверка полезна только если вы понимаете, как выглядит сбой. Вот реальный пример, полученный добавлением одного нулевого байта в валидный архив:
Code-highlight
cp zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz tampered.tar.gz
sha256sum tampered.tar.gz > tampered.sha256
printf '\x00' >> tampered.tar.gz
sha256sum -c tampered.sha256
Реальный вывод:
Code-highlight
tampered.tar.gz: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
Код возврата: 1.
Поместим оба дайджеста рядом:
Code-highlight
sha256sum zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz tampered.tar.gz
Code-highlight
86326f5324f4e59cc2008c15f94407cc8d5feacf75d64942164bb5f08eca8c5e zebrad-6.3.0-x86_64-unknown-linux-gnu.tar.gz
8d4e2e22adcb014e006fafc71a974f987ba11297587f593cf89eb9bb1feff0b5 tampered.tar.gz
Один байт добавлен в файл размером 66,992,676 байт. У двух хешей нет ничего общего — ни префикса, ни шаблона. Частичного совпадения или «почти совпадения» не бывает: контрольная сумма либо совпадает точно, либо файл не является тем файлом, который вам нужен.
Что делать в такой ситуации
- Не запускайте бинарный файл. Не распаковывайте его и не делайте
chmod +x.
- Попробуйте снова со страницы официального релиза. Большинство сбоев — это обрезанные загрузки.
- Если второй раз тоже не проходит, смените сетевой путь. Другое подключение или VPN. Ошибка, которая исчезает при смене сети, и ошибка, которая сохраняется, — это разные ситуации.
- Убедитесь, что у вас правильный файл контрольной суммы для правильной версии. Сравнение v6.3.0 с суммами от v6.2.3 корректно завершится ошибкой.
- Если всё равно не проходит, сообщите об этом. Откройте issue в репозитории проекта или используйте контакт из
SECURITY.md, если подозреваете преднамеренные действия. Каналы раскрытия см. на странице Безопасность экосистемы Zcash.
- Сохраните артефакт. Подменённый бинарный файл — это доказательство. Не удаляйте его до сообщения о проблеме.
Сбой проверки подписи серьёзнее, чем сбой контрольной суммы. Несовпадение контрольной суммы обычно означает повреждение; валидный файл с неверной подписью случайно не появляется.
Часть 4 — Справочная таблица
| Project | Releases published at | Method | Where the key comes from |
|---|
| Zebra | github.com/ZcashFoundation/zebra/releases | SHA256SUMS + Sigstore bundle | Ключ не нужен — идентичность CI через GitHub OIDC |
| Zallet | github.com/zcash/zallet/releases | Detached GPG .asc, SLSA provenance, SBOM | apt.z.cash/zodl.asc — основной 0338 34DD…58E2 6AB1, подписывающий подключ 1FE9 9324…23F0 617F |
| zcashd | retired | — | Остановлен на блоке 3,417,100 2026-07-18. Не устанавливайте. |
| Zodl (ранее Zashi) | App Store / Google Play; zodl-inc на GitHub | Store signing; standalone Android binaries GPG-signed | Ключ ZODL согласно заявлению о переходе |
Примечание по названию: в 2026 году Zashi был переименован в Zodl — сначала в App Store, затем в Google Play. Более старые руководства, где упоминается «Zashi», описывают ту же линейку кошельков.
Часть 5 — Мобильные и аппаратные кошельки
За пределами прямых загрузок проверка работает иначе.
Магазины приложений. Вы не можете самостоятельно проверить подпись. Пакет подписывает магазин, и вы доверяете проверке магазина и целостности аккаунта разработчика. Что можно проверить — это то, что у вас правильное приложение: сверьте имя издателя и идентификатор пакета с официальным сайтом проекта, а не с результатами поиска. Приложения-имитации встречаются часто, и наличие в магазине не является доказательством подлинности.
Отдельные Android APK. Их можно проверять. ZODL публикует отдельные бинарные файлы Android, подписанные GPG, через GitHub Releases, поэтому здесь применяется процесс из Части 2. Если вам нужна проверяемая цепочка, предпочитайте этот вариант.
Аппаратные кошельки. Устройство само подтверждает свою прошивку, поэтому корень доверия — это аппаратное устройство, а не файл на вашем компьютере. См. Keystone Zashi для процесса проверки устройства. Покупайте напрямую у производителя — подмена в цепочке поставок происходит между фабрикой и покупателем.
Дополнительное чтение
Команды на этой странице были выполнены для Zebra v6.3.0 и Zallet v0.1.0-beta.2 по состоянию на 2026-08-18. Инструментарий релизов меняется: если вывод отличается от приведённого здесь, доверяйте собственному запуску и, пожалуйста, откройте PR.