I'm developing an open source project and I have been working on making the builds reproducible so that my users can compare the checksums of the binaries that I distribute with their own builds (if they were to build the project with/from the source code).
Unfortunately, new versions of Windows and MacOS use code signing in order to check binaries and prevent their execution if they aren't signed (I'm aware that there are ways to override this and execute the binary anyways, but this is not user friendly).
I'd like to sign the binaries that I distribute so that my users can run them without any problems. But I'm not sure if that is possible to do while also keeping the reproducible builds.
For a build to be reproducible, the end user must have all the tools / source code required to build the project and, once compiled, the end result should be the same bit-a-bit binary compared to the one that I'm distributing. But that would mean that I'd have to distribute the private key / cert used to sign the binary, which is not a good idea for multiple reasons.
Is there a way to have both reproducible builds and signed binaries?
It's possible to make reproducible signatures for Windows binaries using Jsign (disclaimer: I'm the author). When signing a binary the signature is exported into a separate file which is meant to be distributed along with the source code of the version released. When the build is executed another time by someone else, Jsign detects the detached signature, and instead of signing the binary it injects the detached signature into the binary file. If the build is reproducible, the binary has the same hash and the signature will be valid.
For example, when the new release is built for the first time, Jsign is invoked with the --detached parameter:
jsign --keystore keystore.p12 --storepass secret --alias test --detached application-1.0.exe
This will sign application-1.0.exe and create an application-1.0.sig file containing the signature. The signature file can be checked into the source repository. The next time the build is executed, the same jsign command is invoked and the content of application-1.0.sig is injected into application-1.0.exe, recreating the exact same binary built initially. Once the signature file is created no access to the private key is necessary, so anyone can recreate the same binary as the original developer.
This process is used by the Apache Tomcat project to make its Windows releases digitally signed and reproducible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With