ZYCORD docs
Português
ZycordDocumentaçãoVerificando um download

Verificando um download

Um build reproduzível afirma isto veio deste código, e qualquer um pode conferir — que é a garantia que um projeto publicado anonimamente pode oferecer no lugar de um certificado de assinatura de código. Veja como cobrá-la.

Três verificações, e elas respondem a perguntas diferentes. Execute-as nesta ordem; cada uma vale menos sem a anterior.

VerificaçãoO que ela provaO que ela não prova
ChecksumO arquivo não foi alterado em trânsito.Nada sobre quem o produziu, nem sobre o que há dentro dele.
AssinaturaA lista de checksums veio de quem detém a chave do projeto.Que a chave pertença a alguém em quem você tenha razão para confiar.
RecompilaçãoO binário contém este código e nada mais.Que o código seja honesto — leia-o, ou leia as revisões.

O checksum#

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 não é opcional, e não é indulgência

As releases agora trazem apenas os arquivos -randomx, então SHA256SUMS.randomx é a lista que cobre o que você baixou; SHA256SUMS.deb e SHA256SUMS.desktop cobrem os pacotes Debian e a carteira desktop. Cada uma cobre vários arquivos e você baixou um. Sem a flag, os cinco que você não tem são reportados como FAILED open or read e o comando sai com código diferente de zero num download perfeitamente bom, na própria página que diz a você que uma divergência significa um binário comprometido. Uma verificação cujo resultado normal é uma falha é uma verificação que as pessoas aprendem a ignorar.

A assinatura#

Nenhuma assinatura foi publicada ainda, e esta seção descreve o procedimento para quando houver uma

As releases atualmente publicam o zycord-release-key.asc — a chave pública — mas nada assinado com ela além do manifesto do atualizador: nenhum dos arquivos de checksum tem assinatura destacada, e nenhum é assinado em claro. O gpg --verify abaixo, portanto, falha hoje com um arquivo ausente, e isso é uma lacuna da release e não um erro seu. Até que ela seja fechada, a verificação que de fato sustenta o argumento de confiança é a reconstrução: ela não precisa de assinatura alguma, porque você produz os bytes você mesmo e compara.

Quando uma assinatura de checksum for publicada, ela será feita com a chave do projeto. A impressão digital completa é:

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

Ela é publicada no cabeçalho do whitepaper, no depósito arquivado, e no anúncio de gênese. Ela nunca é rotacionada silenciosamente: uma chave que muda sem uma declaração assinada pela antiga é indistinguível de um comprometimento, e deve ser tratada como tal.

A impressão digital é a âncora, não o arquivo da chave

Obtenha a chave de onde for conveniente e então confira o que você recebeu contra a linha acima. Um arquivo de chave cuja impressão digital seja aquela é a chave do projeto, não importa qual host a entregou a você, e um cuja impressão digital seja qualquer outra coisa não vale nada, por mais confiável que o host parecesse.

Três lugares a carregam. Qualquer um deles serve:

# 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

Depois confirme o que entrou no seu chaveiro, antes de confiar nele:

gpg --fingerprint E72439CEDD8511F9D607550B87FD60D5EB4A0B29
Não use keys.openpgp.org para esta chave

Ele é o keyserver padrão em várias builds do GnuPG, e serve uma cópia reduzida: o pacote de chave pública puro, sem user ID e sem autoassinatura. O GnuPG recusa essa cópia — gpg: key 87FD60D5EB4A0B29: new key but contains no user ID - skipped — e a chave nunca entra no chaveiro, então a verificação abaixo falha com o que parece uma assinatura ruim e na verdade é uma chave ausente. Aquele servidor remove user IDs por política até que um endereço seja confirmado através dele, o que não é algo que um projeto pseudônimo possa fazer.

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

Hoje isto reporta No such file or directory, porque nenhuma release publicou esse arquivo ainda. Veja a nota no topo desta seção.

O gpg vai acrescentar que a chave não está certificada com uma assinatura confiável. Isso é esperado e não é uma falha. Significa que você não disse ao seu chaveiro que pessoalmente responde por esta chave, que é exatamente o que a impressão digital está aqui para resolver. O que importa é que a assinatura seja verificada, e que a chave contra a qual ela foi verificada seja a impressão digital impressa acima.

O whitepaper também é assinado#

O PDF servido a partir deste site tem uma assinatura destacada ao lado, feita pela mesma chave:

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

A reconstrução — a verificação que de fato substitui um certificado#

Um hash diz que o arquivo não foi alterado em trânsito. Não diz nada sobre o que o publicador colocou nele. Isto diz:

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

Compare com o SHA256SUMS.binaries da release. Eles precisam coincidir exatamente. Se coincidirem, o binário que você baixou contém este código-fonte e nada mais — uma afirmação que nenhum certificado jamais fez sobre coisa alguma.

O toolchain Go faz parte do que você está reproduzindo#

É o go1.26.2. O mesmo código-fonte compilado por duas releases diferentes do Go são dois binários diferentes; isso não é uma sutileza, é mensurável — o próprio fluxo de release deste repositório já registrou três valores SHA-256 distintos para um commit e um conjunto de flags, um por versão do Go. Por isso o make build fixa GOTOOLCHAIN=go1.26.2 e para com uma explicação se não puder usar esse toolchain, em vez de produzir uma divergência que parece a adulteração que esta página inteira existe para detectar.

Duas consequências que vale ter em mente:

  • Você não precisa confiar na versão escrita acima. O binário lançado a declara: go version -m zcd imprime o toolchain que o construiu, ao lado do módulo e das flags de build. Se essa linha e a fixação do Makefile algum dia discordarem, o binário não foi construído do jeito que esta página diz.
  • Fazer checkout de uma tag mais antiga traz também a fixação dela junto com o código, então recompilar uma release antiga continua funcionando depois que o projeto migra para um Go mais novo.

As quebras de linha fazem parte do código-fonte aqui#

O wallet/webui embute o frontend da carteira com //go:embed, então as quebras de linha desses arquivos são bytes no binário: um checkout convertido para CRLF constrói um zcd diferente a partir do mesmo commit — uma divergência de causa inocente e aparência assustadora. Um .gitattributes contendo * text=auto eol=lf dá LF na árvore de trabalho em toda plataforma e em toda configuração do git, então um clone novo dá a mesma resposta em qualquer lugar.

Dois casos que ele não cobre: reconstruir uma tag mais antiga que esse arquivo (defina core.autocrlf=input antes do checkout), e um clone já existente feito com core.autocrlf=true, que não se corrige com um pull.

Os arquivos -randomx não são reproduzíveis, por construção

O RandomX é C++, então uma build com cgo carrega um toolchain C do sistema para dentro da saída e ninguém consegue reconstruí-la byte a byte. Esses arquivos têm checksum no SHA256SUMS.randomx e estão deliberadamente ausentes do SHA256SUMS.binaries, que lista o hash que uma build feita por você a partir do código-fonte deve produzir. Este é o único ponto em que a camada que entra numa rede e a camada que é atestada não se sobrepõem — veja a tabela das duas camadas em Instalação. Declarar isso é o ponto: é uma decisão sua em vez de uma suposição feita por você.

Confira a implementação contra o protocolo#

Separadamente de conferir a procedência de um binário, você pode conferir que ele implementa o protocolo. Os vetores dourados são o protocolo; uma implementação independente que passe por eles é um par, não um fork.

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

O zcd genesis é o comando que mais importa: um anúncio de lançamento se compromete, semanas antes, com a tag do código, o hash dos parâmetros e o id de gênese — e isto reconstrói todos eles em milissegundos, a partir do código-fonte, em qualquer máquina. Os valores da testnet pública estão na página da testnet; uma build que imprima outros é uma build em uma cadeia diferente, e ela não vai conectar.

Atestações independentes#

Uma pessoa reconstruindo uma tag prova que a tag é reproduzível. Vários desconhecidos reconstruindo-a e assinando o resultado provam bastante mais, e é o padrão para o qual projetos sérios convergiram exatamente por esse motivo. Reconstrua uma tag e publique o digest que você obteve e a tag que você construiu na thread do anúncio — inclusive quando não bater, que é justamente o caso que vale a pena ouvir.