thank you kindly!
thank you kindly!
- in general if you want to do additional development on a piece of software, it's useful to validate that your build environment is set up correctly and can reproduce bit-exact binaries, before doing additional development
- it helps prevent silent environment-specific build dependencies creeping in, aka "works on my machine"
The first is that it makes sure any maintainers who try to backdoor a package need to document that fact somewhere in the build process. Hence it becomes possible to get more confidence from an audit of a package.
This first goal is done very simply. You rebuild the package, and check that the resulting binary is bit-for-bit identical. With reproducible builds, the same build process should lead to the same binary. So if someone tampered with the source code or the build process, that can be detected if you have reproducible builds.
The second goal is to just have a consistent system which makes debugging easier.
A nice example of the importance of reproducible builds is the app signal, which I mention because of your user-name. We trust the source code of signal, but how are we supposed to be sure that the binaries offered by apt, the google play store, the app store, or whatever source you have for signal, are actually made from the source code? With reproducible builds, one person can rebuild the binary and check to see that the output is the same. This is much better than telling everyone to build signal from source, because now the lazy people who trust the binaries get to benefit from the skeptical people who build from source.
There is FOSS called ungoogled chromium. And building chromium takes a lot of times (in my case 8 hours). The problem here is chromium build is not reproducible and repo author can't build chromium for every platform and every versions as its very expensive from him. So what he currently do now is accepts the binaries from others.
But as a user how can I trust the user who build the binaries? He might have tempered with binaries? He might have inserted back doors secretly? Just because he published binaries lets say for 10 years doesn't grants 100% trustworthy right? He might be hacked etc too?
I think reproducible builds fixes such problems. Other than trust factor I really don't think there is significant advantage.
If someone kindly hands the repo author a (binary, platform) pair how would the author ever verify the original src value, other than re-doing the 8 hour compile themselves?
if no reproducible builds then, sha256(binary_from_user1) != sha256(binary_from_user2)
For smaller project distributing code source is usually correct choice as auditing src code is better than auditing binaries. But the project like chromium I think reproducible build is essential because you can't force everybody to compile and waste hours right?
Of course not! It's more like `compile(src, platform, compiler, compiler version, CPU features, current time, current date, your whole file system tree, compiler caches, ...) → binary`.
There are also absolute evil build systems that fetch random sources from the internet, then practically the whole world becomes your function closure. Even if you manage to fix or exclude these variables, you could still end up with something that's not reproducible at the bit level: for example, unordered data structures result in binary output that will vary from execution depending on the state of the compiler.
> If someone kindly hands the repo author a (binary, platform) pair how would the author ever verify the original src value, other than re-doing the 8 hour compile themselves?
If the build is bit-level deterministic it results in a fixed output given a fixed input. So, you simply hash the output, sign it and ship it along the build. The user will simply check if the hash matches the binary they received, even from an untrusted source.
My Packages file contains the following about a given package that apt will verify
SHA256: 04cd079a0676438a8fe1bdf2d897927ead9aa689808f4209d41edadfc3f72f0e
SHA1: 2073306c14d4d755d8a32dabce0623e0d9ca3dde
MD5sum: f49c2e53ff64d2568f3cb8b6fcb4b112
Release has MD5, SHA1 and SHA256 of the Packages9ff4da44240de168f7b98d1461d2d96c 65274 main/binary-amd64/Packages dc9007fe54d7f26d0922a377c81e45d9 17568 main/binary-amd64/Packages.gz fd2c8c93e1590e1fc5bc797b20b9ddd670171f1856326a8ba7816f2a6753b779 65274 main/binary-amd64/Packages 06159def8d253ed6f3401cc797bf0f2743b4623a16f996815bf8ffde6f79bfaf 17568 main/binary-amd64/Packages.gz
And Release itself has a .gpg signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQEcBAABCAAGBQJhTyrcAAoJECF64EwcjMKfNvUH/RSnkcd41AlOHrrnsDc1P0YL
MbV0RrhmHnQYCdO4VvE/C0BTOFstvF0bRDcnCHzEyaU2LvZ7pQFsOTgQqaNjuxSd
NyVTIfhwg00AGsEN/MIUZOd2jZLHQQ8esDv0eOCcpO+q4UmBtP6unTCjmdkMekkx
SGA/ClfNA1Ql48ZiXMAhn87Vpxvcl4IFtdOV5UZmMVGtMaX1bp7u8Ifz1bm2xbkx
....Of course I still have to trust the person that controls the gpg signing key, but how does that vary with
> If the build is bit-level deterministic it results in a fixed output given a fixed input. So, you simply hash the output, sign it and ship it along the build. The user will simply check if the hash matches the binary they received, even from an untrusted source.
Or is it that 3/4/10 independent people can independently build the same, concur that the checksums of the built package are all the same, and be confident that none of them are being coerced or hacked? So it's a way of verifying the person building the package in the first place (any coercion/hacking would have to apply to everyone confirming the build - which won't be everyone using it, but would be a dozen people in a dozen jurisdictions
Those hashes and signature confirm that the package is coming from a maintainer, but it can't confirm nor deny that the package you received was actually built from the sources the maintainer claims to have used. Simply because there's no guaranteed bit-level link between sources and output.
> Or is it that 3/4/10 independent people can independently build the same, concur that the checksums of the built package are all the same, and be confident that none of them are being coerced or hacked?
Yes, the improvement compared to traditional packages is that given the package inputs (sources, dependencies, build instructions) and the output you can be sure that the output is the result of building the inputs. You don't actually need multiple indepdent people: just rebuild the package and compare the hashes. Again, you could try to do this with APT and it will probably work for some very simple software (or some that the Debian maintainers managed to make reproducible), but not in general.
The way to verify is to redo the entire compile process. But the advantage is that anyone can do this, so you can have other users in the community validating the builds.
To confirm I went to https://github.com/Eloston/ungoogled-chromium it says "NOTE: These binaries are provided by anyone who are willing to build and submit them. Because these binaries are not necessarily reproducible, authenticity cannot be guaranteed;"
And by having this "threat" against the bad guys, which consists in saying: "If you poison the well, we'll find how you did it", suddenly the bad guys are having a much harder time being bad.
E.g. nobody added a keylogger after publishing the source but before compiling the executable.
- security against backdoors
- validating build environment
- reproducing bugs
But there's more:
- legal liabilities: many bad build systems pull trees of dependencies from the Internet during the build. How can you prove that no license breaching occurred in any of the dependencies? Debian explicitly verifies licensing in each package.
- prevent pulling dependencies from deleted (or hijacked!) repositories on the Internet
- reproduce performance improvements: non reproducible builds can often lead to non reproducible performance. Even things like the length of the local hostname can leak into a binary and affect memory alignment.