Verificar una descarga
Una compilación reproducible afirma esto salió de este código, y cualquiera puede comprobarlo — que es la garantía que un proyecto publicado de forma anónima puede ofrecer en lugar de un certificado de firma de código. Aquí se explica cómo cobrarla.
Tres comprobaciones, y responden a preguntas distintas. Hazlas en este orden; cada una vale menos sin la anterior.
| Comprobación | Qué demuestra | Qué no |
|---|---|---|
| Suma de verificación | Que el archivo no se alteró en tránsito. | Nada sobre quién lo produjo, ni sobre qué contiene. |
| Firma | Que la lista de sumas vino de quien posee la clave del proyecto. | Que la clave pertenezca a alguien en quien tengas motivos para confiar. |
| Recompilación | Que el binario contiene este código y nada más. | Que el código sea honesto — léelo, o lee las revisiones. |
La suma de comprobación#
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 no es opcional, y no es indulgenciaLas versiones ahora distribuyen solo los paquetes -randomx, así que
SHA256SUMS.randomx es la lista que cubre lo que descargaste;
SHA256SUMS.deb y SHA256SUMS.desktop cubren los paquetes Debian y el
monedero de escritorio. Cada una cubre varios archivos y tú descargaste uno. Sin el flag, los cinco que no tienes se informan como
FAILED open or read y el comando termina con código distinto de cero en una descarga perfectamente correcta, en
la misma página que te dice que una discrepancia significa un binario comprometido. Una comprobación cuyo resultado normal es
un fallo es una comprobación que la gente aprende a ignorar.
La firma#
Las versiones publican actualmente zycord-release-key.asc — la clave pública — pero
nada firmado con ella más allá del manifiesto del actualizador: ninguno de los archivos de sumas de comprobación tiene firma
separada, y ninguno está firmado en claro. Por tanto, el gpg --verify de abajo falla
hoy con un archivo inexistente, y eso es una carencia de la versión y no un error tuyo. Hasta que se cierre, la
comprobación que de verdad sostiene el argumento de confianza es la
recompilación: no necesita firma alguna, porque tú mismo produces los bytes y comparas.
Cuando se publica una firma de sumas de comprobación, se hace con la clave del proyecto. La huella completa es:
E724 39CE DD85 11F9 D607 550B 87FD 60D5 EB4A 0B29
Se publica en la cabecera del whitepaper, en el depósito archivado y en el anuncio de la génesis. Nunca rota en silencio: una clave que cambia sin una declaración firmada por la anterior es indistinguible de un compromiso, y debe tratarse como tal.
Consigue la clave de donde te resulte cómodo y luego comprueba lo que obtuviste contra la línea de arriba. Un archivo de clave cuya huella sea esa es la clave del proyecto sin importar qué servidor te la entregó, y uno cuya huella sea cualquier otra cosa no vale nada por muy fiable que pareciera el servidor.
Tres sitios la ofrecen. Cualquiera de ellos sirve:
# 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
Luego confirma qué ha entrado en tu llavero, antes de fiarte de ello:
gpg --fingerprint E72439CEDD8511F9D607550B87FD60D5EB4A0B29
keys.openpgp.org para esta claveEs el servidor de claves por defecto en varias compilaciones de GnuPG, y sirve una copia recortada: el paquete de
clave pública desnudo, sin ID de usuario y sin autofirma. GnuPG rechaza esa copia —
gpg: key 87FD60D5EB4A0B29: new key but contains no user ID - skipped — y la
clave nunca entra en el llavero, así que la verificación de abajo falla con lo que parece una firma incorrecta y
en realidad es una clave ausente. Ese servidor recorta los ID de usuario por política hasta que se confirma una dirección
a través de él, algo que un proyecto pseudónimo no puede hacer.
gpg --verify SHA256SUMS.randomx.asc SHA256SUMS.randomx
Hoy esto informa de No such file or directory,
porque ninguna versión ha publicado aún ese archivo. Véase la nota al principio de esta sección.
gpg añadirá que la clave no está certificada con una firma de confianza. Eso
es lo esperado y no es un fallo. Significa que no le has dicho a tu llavero que
respondes personalmente por esta clave, que es exactamente lo que la huella está ahí para zanjar. Lo que
importa es que la firma verifique, y que la clave contra la que verificó sea la huella
impresa arriba.
El whitepaper también está firmado#
El PDF que sirve este sitio tiene una firma separada junto a él, hecha con la misma clave:
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
La recompilación — la comprobación que de verdad sustituye a un certificado#
Un hash te dice que el archivo no fue alterado en tránsito. No dice nada sobre qué puso el editor dentro. Esto sí:
git clone https://gitlab.com/zycord-group/zycord-node.git
cd zycord-node
git checkout v<version>
make build
sha256sum bin/zcd bin/zycordd
Compara contra SHA256SUMS.binaries de la versión. Deben coincidir
exactamente. Si lo hacen, el binario que descargaste contiene este código fuente y nada más
— una afirmación que ningún certificado ha hecho jamás sobre nada.
La cadena de herramientas de Go forma parte de lo que estás reproduciendo#
Es go1.26.2. El mismo código fuente compilado por dos versiones distintas de Go son dos
binarios distintos; eso no es una sutileza, es medible — el propio flujo de trabajo de publicación de este repositorio
registró una vez tres valores SHA-256 separados para un mismo commit y un mismo conjunto de flags, uno por
versión de Go. Por eso make build fija GOTOOLCHAIN=go1.26.2 y se detiene con una
explicación si no puede usar esa cadena de herramientas, en lugar de producir una discrepancia que parece
la manipulación que toda esta página está aquí para detectar.
Dos consecuencias que conviene tener presentes:
- No tienes que fiarte de la versión escrita arriba. El binario publicado la
declara:
go version -m zcdimprime la cadena de herramientas que lo compiló, junto al módulo y los flags de compilación. Si esa línea y la fijada en elMakefilediscrepan alguna vez, el binario no se compiló como dice esta página. - Descargar una etiqueta antigua descarga su fijación junto con su código, así que recompilar una versión vieja sigue funcionando después de que el proyecto pase a un Go más nuevo.
Los finales de línea son parte del código fuente aquí#
wallet/webui incrusta el frontend del monedero con //go:embed, así que los
finales de línea de esos archivos son bytes dentro del binario: un checkout convertido a CRLF compila un
zcd distinto a partir del mismo commit — una discrepancia con una causa inocente y una
apariencia alarmante. Un .gitattributes que lleve * text=auto eol=lf da LF en el
árbol de trabajo en toda plataforma y toda configuración de git, así que un clon nuevo
da la misma respuesta en todas partes.
Dos casos que no cubre: recompilar una etiqueta anterior a ese archivo (fija
core.autocrlf=input antes de hacer el checkout), y un clon existente hecho con
core.autocrlf=true, que no se cura al hacer pull.
-randomx no son reproducibles, por construcciónRandomX es C++, así que una compilación con cgo arrastra una cadena de herramientas de C del sistema hasta la salida y nadie puede
recompilarla byte a byte. Esos archivos llevan sumas de comprobación en SHA256SUMS.randomx y
están deliberadamente ausentes de SHA256SUMS.binaries, que enumera a qué debería resumir una compilación que hagas
tú desde el código fuente. Este es el único punto donde el
nivel que se une a una red y el nivel que está atestiguado no se solapan — véase la tabla de dos niveles
en Instalación.
Enunciarlo es lo importante: es una decisión tuya y no una suposición hecha por ti.
Comprobar la implementación contra el protocolo#
Aparte de comprobar la procedencia de un binario, puedes comprobar que implementa el protocolo. Los vectores de referencia son el protocolo; una implementación independiente que los pase es un par, no un 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
zcd genesis es el comando que más importa: un anuncio de lanzamiento se compromete, semanas
antes, con la etiqueta de código, el hash de parámetros y el id de la génesis — y esto los reconstruye
todos en milisegundos, desde el código fuente, en cualquier máquina. Los valores de la testnet pública están en la
página de testnet; una compilación que imprima otros distintos es una compilación en una
cadena distinta, y no se conectará.
Atestaciones independientes#
Una persona que recompila una etiqueta demuestra que la etiqueta es reproducible. Varios desconocidos recompilándola y firmando el resultado demuestran bastante más, y es el patrón al que los proyectos serios convergieron por esta misma razón. Recompila una etiqueta y publica el digest que obtuviste y la etiqueta que compilaste en el hilo del anuncio — incluso cuando no coincida, que es el caso que vale la pena conocer.