Preparation (when accepting to be the Trusted Reproducer)
Use whatever scheduling tool you prefer to make sure you will, on your own initiative, return to this document and follow it within 72 hours from the start of the manual testing session. In particular, do not trust anything said by the RM about this process: we assume their system may be compromised and could be used by an adversary to mislead you.
Gather input data
Inputs from the release process
Look at the "Environment" section at the beginning of the release process instructions and set the following variables as instructed:
ARTIFACTS
DIST
ISOS
RELEASE_BRANCH
VERSION
Inputs from manual testers
A manual tester should have sent you clear-signed hashes for all products of this release. Then:
- Verify that the signature is valid and made by one of our usual manual testers
- Put the hashes, excluding the OpenPGP signature data, into a file
called
SHA512SUMS.txt
.
Your inputs
Set these environment variables accordingly:
PUBLISHED_ARTIFACTS
: some new directory where you can download gigabytes of data to.SHA512SUMS
: the path of theSHA512SUMS.txt
file from above.TAILS_CHECKOUT
: path to your Tails Git repo checkout.
Derived environment variables
cd "${TAILS_CHECKOUT:?}" && \
TAG="$(echo $VERSION | tr '~' '-')" && \
TAG_COMMIT="$(git rev-parse --verify ${TAG:?})" && \
git fetch && \
git checkout "${RELEASE_BRANCH:?}" && \
git merge "origin/${RELEASE_BRANCH:?}"
Build your own products
Build your own images
Fetch and verify the Git tag:
cd "${TAILS_CHECKOUT:?}" && \ git fetch origin --tags --force && \ git tag -v "${TAG}"
If the last output is a "Good signature" for the expected tag, made by Tails signing key, then we are good. Otherwise, if you see anything else, we're not good; immediately contact the RM and tails@boum.org! Proceeding with the rest of the steps are pointless in this case, so await instruction.
Build ISO and USB images:
cd "${TAILS_CHECKOUT:?}" && \ git checkout "${TAG:?}" && \ git submodule update --init && \ export SOURCE_DATE_EPOCH=$(date --utc --date="$(dpkg-parsechangelog --show-field=Date)" '+%s') && \ rake build && \ mkdir "${ISOS:?}/tails-amd64-${VERSION:?}" && \ mv "${ARTIFACTS:?}/tails-amd64-${VERSION:?}".* \ "${ISOS:?}/tails-amd64-${VERSION:?}/"
Verification
If there is any type of mismatch at some point below, let the RM and tails@boum.org know immediately! But still proceed and do everything below, potentially reporting multiple different issues.
Verify that your products match what was tested
cd "${ISOS:?}/tails-amd64-${VERSION:?}" && \
sha512sum -c "${SHA512SUMS:?}"
Wait for the release to be published
In order to get the guarantees we're looking for here, the following steps have to be done only after the release has been made public.
Download published products
mkdir -p "${PUBLISHED_ARTIFACTS:?}" && \
cd "${PUBLISHED_ARTIFACTS:?}" && \
mkdir tails-amd64-${VERSION:?} && \
cd tails-amd64-${VERSION:?} && \
wget http://dl.amnesia.boum.org/tails/${DIST:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.{img,iso}
Verify that your products match what was published
ISO and USB images
for type in iso usb ; do
case "$type" in
iso)
ext=iso
;;
usb)
ext=img
;;
esac
if cmp --quiet \
"${ISOS:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.$ext" \
"${PUBLISHED_ARTIFACTS:?}/tails-amd64-${VERSION:?}/tails-amd64-${VERSION:?}.$ext" ; then
echo "OK: locally built $type matches the published one"
else
echo "FAIL: locally built $type does not match the published one"
fi
done
IDF
If you are verifying the reproducibility of anything but a stable release (for example, a beta or a RC), skip this part.
Download the IDF by running:
wget https://tails.boum.org/install/v2/Tails/amd64/${DIST:?}/latest.json
Then check that the hashes and sizes match what you have built:
sudo apt install jq && \
for type in iso usb ; do
locally_built_dir="${ISOS:?}/tails-amd64-${VERSION:?}"
case "$type" in
iso)
ext=iso
;;
usb)
ext=img
;;
esac
locally_built_file="${locally_built_dir}/tails-amd64-${VERSION:?}.$ext"
idf_size=$(cat latest.json | jq ".installations[0].\"installation-paths\" | map(select(.type == \"$ext\"))[0].\"target-files\"[0].size")
locally_built_size=$(stat --format='%s' "$locally_built_file")
if [ "$idf_size" = "$locally_built_size" ]; then
echo "OK: $type size matches"
else
echo "FAIL: $type size does not match"
fi
idf_sha256=$(cat latest.json | jq --raw-output ".installations[0].\"installation-paths\" | map(select(.type == \"$ext\"))[0].\"target-files\"[0].sha256")
locally_built_sha256=$(sha256sum "$locally_built_file" | cut -f 1 -d ' ' | tr -d '\n')
if [ "$idf_sha256" = "$locally_built_sha256" ]; then
echo "OK: $type sha256 matches"
else
echo "FAIL: $type sha256 does not match"
fi
done