-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reproducible builds #404
Comments
Hi @adrelanos. Thanks for the clear description of the problem. All of our official firmware released to users is released by github actions, so can the compilation process be more clearly defined through the script executed each time? For example, taking classic as an example, you can see the CI script for each execution compilation here. https://github.com/OneKeyHQ/firmware/blob/touch/.github/workflows/build-classic.yml.We use the ubuntu 20.04 version, after pulling the corresponding branch code, set five environment variables, Similarly, you can find all the firmware information we have released so far in this script location:
For external users, the last step of the script Notify to Slack may fail, but it does not affect the content of the compilation result. You can still download the compilation result in the task corresponding to the github action link. Are the steps to reproduce compilation clear? |
Hello, thank you for your reply! This isn't a feature request on how to reproduce compilation. This isn't "how do I compile" question. The feature request is " You compile it, you get hash "A". How to proof that the source code that was claimed to use for compilation is the actual source code used for compilation? For that a feature called "reproducible builds" is required. Bitcoin Core is fully reproducible. If original upstream developers compile it or any other user from the same source code, the resulting binary will have the very same hash. This proves that there's no extra hidden source code or other weirdness / differences in the official binaries. Debian, Qubes OS and many others are also working on reproducible builds. https://binarywatch.org/ shows some other crypto currency software and hardware wallets which are already reproducible. If you build official builds in CI versus locally is kinda unrelated. Ideally, you would compile in a few different environments (since weird things such as different file systems, operating systems, system clock, timezones can lead to different hashes of the final binary). Once you're confident you're getting the same hash everywhere, upload the build and the hash. In short:
This might (easily) only be possible prior signing of the binaries in case you're using embedded signatures. So first step would be making it possible for unsigned binaries. Later, some solution for signatures could be found, but these are details for later. Once accomplished, you can advertise supporting |
The reason for using nixOS is to compile exactly the same results on different platforms as much as possible. Of course, our official version is released by ubuntu. Regarding whether other systems and various versions are consistent, we need to use more CI server or a third-party server for compilation verification. Our official binary is all here: https://github.com/OneKeyHQ/firmware/releases For the hash problem of each version mentioned in it, this can be provided. But on the other hand, it is also very clear at the end of this tutorial.https://help.onekey.so/hc/en-us/articles/6113121891599 In fact, use the command |
That's good.
That's also OK.
That's a commendable goal, though might be above on beyond the emerging industry standard. For example Debian's " To be fair and only make a realistic feature request, reproduciblity needs to be supported only on 1 operating system of your choice so you can checkmark and advertise the "reproducible builds are supported" security feature. Ideally compilation is done on an operating system which itself is or aspires to be reproducible in the future such as Debian, but even that is optional and not a requirement in any definition that I've seen yet. As far as I understand reproducible builds,
So in summary, if official versions are built on Ubuntu, then it would be sufficient to have instructions what has is expected and how to reproduce that. Doing the same with nixOS would be optional. |
In fact, if you only want to verify that the hashes of our officially released Ubuntu version are consistent, you only need to follow up our officially released action. Take our newly released classic v3.0.0 firmware as an example.
If you want to compile it, you need to be as consistent as possible with our CI environment. The execution environment of CI is completely transparent. You can follow the log of the internal compilation process to see to all information. Preparation
Compilation process
All open source code and open source firmware are compiled to make the release more transparent. You can see all the installed dependency versions and installation process before the release in the log of this github action. If you use the same code hash, the same environment, and the same version of all dependencies (such as executing the same github action multiple times on the same code hash), then the final content must be the same result. |
That's very good! I am taking your word for it. In that case, you can advertise on your website that you support reproducible builds and perhaps encourage the community doing reproduction. You might get added on websites such as walletscrutiny.com and/or BinaryWatch.org. (Which I am not affiliated with.) A few detail enhancements. Users could if it was documented how to do so...:
|
I followed the instructions and did the same thing as the configured Github Actions using a bash script. Here is the script I used: #!/bin/bash
### provide this script with the version without "v" and device type (classic, mini)
### and short release date (mmdd like 0511) which is the suffix of the released binary
version=$1
type=$2
short_release_date=$3
if [[ $type == mini ]]; then
boot_version_variable="BOOT_VERSION=\$(./tools/version.sh ./legacy/bootloader/version.h)"
build_script="nix-shell --run \"poetry run ./legacy/script/setup\"
nix-shell --run \"export ONEKEY_MINI=1 && poetry run ./legacy/script/cibuild\"
cp ./legacy/firmware/${type}*Stable*.bin /firmware"
elif [[ $type == classic ]]; then
boot_version_variable="BOOT_VERSION=\$(./tools/version.sh ./legacy/bootloader/version.h)"
build_script="nix-shell --run \"poetry run ./legacy/script/setup\"
nix-shell --run \"poetry run ./legacy/script/cibuild\"
cp ./legacy/firmware/${type}*Stable*.bin /firmware"
elif [[ $type == touch ]]; then
boot_version_variable="BOOT_VERSION=\$(./tools/version.sh ./core/embed/bootloader/version.h)"
build_script="git submodule update --init --recursive
nix-shell --run \"poetry run make -C core build_boardloader\"
nix-shell --run \"poetry run make -C core build_bootloader\"
nix-shell --run \"poetry run make -C core build_firmware\"
nix-shell --run \"poetry run core/tools/headertool.py -h core/build/firmware/touch*Stable*.bin\"
cp ./core/build/firmware/${type}*Stable*.bin /firmware"
fi
rm -rf /tmp/onekey_firmware
mkdir /tmp/onekey_firmware
chmod 777 /tmp/onekey_firmware
cd /tmp/onekey_firmware
podman run --rm -v ${PWD}:/firmware ubuntu:20.04 bash -x -c "
apt update
apt -y upgrade
apt install -y curl xz-utils sudo git wget g++
useradd -m nixuser
groupadd -r nixbld
usermod -aG nixbld nixuser
mkdir /nix
install -d -m755 -o \$(id nixuser -u) -g \$(id nixuser -g) /nix
sudo -H -u nixuser bash -c -x 'sh <(curl -L https://nixos.org/nix/install) --no-daemon
. ~/.nix-profile/etc/profile.d/nix.sh
cd ~
git clone https://github.com/OneKeyHQ/firmware
cd firmware
git checkout ${type}/v${version}
$boot_version_variable
FIRMWARE_VERSION=${version}
BUILD_DATE=\$(git --no-pager log -1 --format=%cd --date=format:\"%Y%m%d\" ${type}/v${version})
SHORT_HASH=\$(git rev-parse --short HEAD)
PRODUCTION=1
nix-shell --run \"poetry install\"
$build_script
cd /firmware
wget -O \"downloaded-firmware.bin\" \
\"https://github.com/OneKeyHQ/firmware/releases/download/${type}%2Fv${version}/${type}.${version}-Stable-${short_release_date}-\${SHORT_HASH:0:-2}.signed.bin\"'"
sha256sum * Run the script:
The result of sha256sum would be:
I transformed the binaries to hex format to see the diff and expected to only see a signature difference. But I got too many lines of diff (hundreds of lines). You can try it by:
I ran the same script for mini firmware:
Again transformed the binaries to hex to see a diff:
the diff for Mini version was much less than Classic but it's still too much to say the firmware is reproducible. The same happens for Touch firmware. Please check the script and let me know if I did something wrong or fix the reproducibility problem. We would be happy to mark OneKey device firmwares as reproducible in Walletscrutiny. |
The default architecture of Github Actions is x64, make sure that the rebuilt hosts are on that architecture too! |
@lyxyx Thank you, I will inform the WS team to try it. |
Dockerfile should be:
Disclaimer: I'm just the WS intern trying to learn how to do this. |
I'm getting the same recursion. Assuming that @xrviv used the exact script, I'll not dig through my minor refactoring I did for readability. The error:
My Dockerfile:
My script:
|
I haven't reproduced the problem on my end, but you can integrate libfaketime into @mohammad's script, similarly:
onekey.sh 3.4.0 classic 0917 2023-09-17 |
Do you mean you use the scripts presented above without issue or that you have not tried the exact recipe? After all, Danny had found a bug in the Dockerfile. If this works for you from scratch (building the docker image freshly, too), I'm happy to try again but as it fails for both Danny and me and the issue is with faketime at a step involved in both Mohammad's and your script, I'm not expecting a different result. |
This is a problem with the path where libfaketime is installed on different systems,
please try this script,
|
So the binary downloadable from CI Actions are not signed at all (all 0s in the headr of generated And how could we flash the signed binary by ourselves rather than the web tool, like any python script like |
The latest script is sending mixed messages, showing both
I'm a bit confused:
I've also tried
All lead to the same problem. |
After trying the latest script with
|
What I don't understand as a software engineering student is why is it so difficult to get a reproducible build? I thought if everyone knows the build instructions every build and thus binary is exactly the same? So either the dev team of OneKey really needs to improve their documentation regarding this or some info is missing. Please correct me if I'm wrong. I hope everyone figures it out. I wanted to buy a OneKey Pro wallet to use as a secondary wallet next to my Trezor but now I'm doubting this until this gets resolved. I take https://walletscrutiny.com very seriously. |
|
Thank you so much for your explanation! 😀 So, if I understand correctly OneKey needs to document the build tools, the versions of those build tools, on which platform they build it, the file structure, basically everything you mentioned here? Could also some of these be avoided? Such as embedded metadata, or the order? Can the order be fixed? I assume that this depends on the build tools right? That's quite the task TBH 😅 Still, it's needed for transparency. |
Yes If you clone the walletscrutiny repository on gitlab - https://gitlab.com/walletscrutiny/walletScrutinyCom. You will find there some existing Dockerfile configurations for wallets such as blue wallet, bitcoin schildbach, etc.
Isn't that fun!? Basically their team just has to document what they are already doing and digest it to make it easier for others to follow their procedure.
There are things that cannot be avoided and some stuff that come up with differences routinely. I know it sounds a bit "perfectionist" but it is possible. You can find more background in reproducible-builds.org.
A little documentation won't hurt anybody :) |
Docker isn't great because it requires downloading a huge binary image,
which should not be trusted. If the docker image isn't trusted (because
it's not included in the chain of reproduciblity), then anything created
using it (OneKeyHQ firmware) is conceptually not to be trusted either.
So if going the docker route, that also would need to be build
reproduciblity from soruce code.
|
@adrelanos you are right to worry about the images themselves being compromised and luckily work is being done on that front, too. At WalletScrutiny I try to avoid using images under the control of respective wallet providers and use generic, minimal images instead to build on. Of course the whole build process pulls in a lot of binary stuff in a myriad of ways and more research has to be done to avoid compromises but containers are still a great way to define exact build environments. Nix appears to be even better but you are right, if we agree on the same binary blobs, we have our single points of failure right there. The alternative is bootstrapability of all the binary that touches the result. |
Is onekey still making progress recently? It seems there has been no response or progress for a while. As a onekey user, I am also very concerned about this matter. |
Yeah, seems like they want others to figure it out while not providing reproducible build, and no build instructions and whatnot. |
It would be more constructive for us to contribute to the discussion in walletscrutiny's gitlab issue for onekey. They have, in the past, replied extensively: https://gitlab.com/walletscrutiny/walletScrutinyCom/-/issues/469 |
It would be good if OneKey could give an update here or on gitlab. It’s been a while and is concerning given the intended use case. |
Yes. Well-known hardware wallets have passed the consistency test, such as Trezor, coldcard, etc. This is especially troubling considering Onekey is made in China. |
Indeed, for me this is the reason not to buy any products. If it's not open source and not verifiable by third parties then I don't trust it. |
Has anybody else attempted to build this since... (let me check...)... Dec 9, 2023? |
At this point it's best to ask @lyxyx since he/she is a contributor and seems to be able to build. He/she is either an OneKey employee or person who contributes. Has WS tried his latest build instructions? |
I could try again. |
Using this Dockerfile:
|
Adjusting with:
Trying this out now. |
I seem to have gotten further:
Again, libfaketime. I will see if disabling these lines would work:
|
Commenting out those 2 lines in the I trimmed the results as no pastebin service can accommodate all the characters:
I will try to analyze tomorrow. |
@somebodyLi I noticed your activity on the OneKey firmware, is this something you’re able to help with? |
@xrviv Have you analyzed the results? |
After all this time and no update (and no answers) I assume that I can't trust OneKey. It's sad because I was looking to buy on of their products. |
Hi guys, sorry, was caught up with other walletscrutiny.com stuff. I have a draft for a working firmware build for 3.9.0 - It is still Very WIP. https://gitlab.com/walletscrutiny/walletScrutinyCom/-/merge_requests/814/diffs |
To better focus on getting a reproducible build, I decided to create a new issue with more specific information here: |
feature request: reproducible builds
#17 was imo wasn't particularly well handled to address the concern raised.
This resulted in a "not verifiable" rating on https://walletscrutiny.com/hardware/onekey/ (which I am not affiliated with ).
https://help.onekey.so/hc/en-us/articles/6113121891599 doesn't clearly state "reproducible builds" or that users should get the same hash after complication.
Are binaries byte for byte deterministically reproducible, resulting in the same hash values for official and user-made builds, aka reproducible builds?
references:
The text was updated successfully, but these errors were encountered: