ZYCORD 文档
简体中文
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 构建中的默认密钥服务器,而它提供的是一份被剥离过的副本:只有裸的 公钥包,没有用户 ID,也没有自签名。GnuPG 会拒绝这份副本 — gpg: key 87FD60D5EB4A0B29: new key but contains no user ID - skipped — 于是这把 密钥根本没进钥匙串,因此下面的验证会以看起来像签名错误的方式失败,而实际上是密钥缺失。那台服务器按其政策剥离用户 ID, 直到有一个地址通过它得到确认为止,而这是一个匿名项目做不到的事。

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 — 一处成因无辜、外表吓人的不匹配。一个带有 * text=auto eol=lf 的 .gitattributes 会在每个平台、每种 git 配置下都让工作树中是 LF,因此一次全新的 克隆在哪里都会给出同样的答案。

有两种情况它没有覆盖:重建一个比该文件更早的标签(请在检出之前设置 core.autocrlf=input),以及一个用 core.autocrlf=true 做出来的 既有克隆,它不会因为 pull 而自愈。

-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 是最要紧的那条命令:一则发布公告会提前数周 就对代码标签、参数哈希和创世 id 作出承诺 — 而这条命令能在任何机器上、从源代码出发, 用毫秒级的时间把它们全部重建出来。公共 testnet 的各项取值在 testnet 页面上;一个打印出不同取值的构建,就是另一条链上的 构建,它连不上。

独立的证明#

一个人重建一个标签,证明的是这个标签可复现。若干互不相识的人重建它并 为结果签名,证明的就多得多,而这正是严肃项目出于同样的理由所收敛到的模式。 请重建一个标签,然后把你得到的摘要和你所构建的标签发到 公告帖子里 — 包括对不上的时候,那恰恰是最值得听到的情况。