Verifying downloads
Every Tetherand release artefact ships with two sidecar hash files computed by independent cryptographic constructions. To trust an artefact, both must match what's published on the release page.
Why two hashes
A single hash function is only as strong as the cryptographic family it belongs to. Even though no general collision attack is known against SHA-256 today, the value of the artefacts being signed makes them a worthwhile target. By also publishing a hash from a fundamentally different construction, an attacker who wants to substitute a malicious binary needs two independent collisions simultaneously — a problem with no known general method.
| Function | Construction | Used by |
|---|---|---|
SHA-256 | Merkle–Damgård chain over a Davies–Meyer compression function | The wider Internet (TLS certs, Bitcoin, git blob hashing, …) |
SHA3-256 | Keccak sponge permutation | NIST FIPS 202, post-Merkle–Damgård designs |
The two are deliberately unrelated. A collision attack on the Merkle–Damgård family (the Marc Stevens / SHAttered class of work) tells you nothing about a sponge construction's collision resistance. A multi-hash forge is a different cryptanalysis problem than a single-hash forge.
The two commands
shasum -a 256 <file> # must match the .sha256 sidecar
openssl dgst -sha3-256 <file> # must match the .sha3-256 sidecar
Both should print a hex hash on stdout. Compare each to the corresponding sidecar file from the release page.
On macOS, shasum ships with the base system; openssl 3.x (which has SHA3-256) is Homebrew's by default (brew install openssl). On Linux, sha256sum and openssl are both standard.
Worked example
After downloading tetherand.apk, tetherand.apk.sha256, and tetherand.apk.sha3-256 from the release page:
$ shasum -a 256 tetherand.apk
075ef70425f1d3544bfba9cea7b2c77cbbb438b52c4014c4f0056494d91899b7 tetherand.apk
$ cat tetherand.apk.sha256
075ef70425f1d3544bfba9cea7b2c77cbbb438b52c4014c4f0056494d91899b7 tetherand.apk
Same hex string — first check passes. Now the SHA3-256 check:
$ openssl dgst -sha3-256 tetherand.apk
SHA3-256(tetherand.apk)= fb2452227d975d79fdd1200c57e45b955c1caf932ab799288f7a86f2119d9157
$ cat tetherand.apk.sha3-256
fb2452227d975d79fdd1200c57e45b955c1caf932ab799288f7a86f2119d9157 tetherand.apk
Second check passes. The artefact is safe to install.
Master index files
The release page also includes two text indexes:
SHASUMS.txt— every hash for files underbin/.COMBOSUMS.txt— every hash for files underdist/bundles/.
These are convenient for verifying multiple downloads in one pass. They are themselves unsigned, so use them only to compare against the per-file sidecars (which match the on-page checksums GitHub itself displays for every release asset).
Verifying the release tag
The Git tag v0.1 is annotated. To inspect it:
git fetch --tags
git tag -v v0.1
This confirms the tag's author identity and shows the message GitHub displays on the release page. The same identity authors every commit on main.
Reproducing the build locally
Once you have the source clone, you can rebuild the APK locally and compare its hashes to the published ones. The cross-compile scripts apply --remap-path-prefix so workstation-specific paths don't end up in the shipped binaries, and the workspace's profile.release is configured for strip = true, debug = false. Combined with deterministic Gradle timestamps, the same source on the same toolchain produces byte-identical output. See Building from source for the full pipeline.