Powers of Tau Operational Writeup
This is my report for my contribution to the Powers of Tau ceremony, which ended up not being included because of unknown corruption of the response.
The Powers of Tau ceremony was used to generate the base reusable trusted parameters that were then specialized for the Zcash Sapling zero-knowledge proofs (and have been leveraged and extended by several other projects since). I was the 15th person to participate in the ceremony, but unfortunately not the 15th contribution.
Below is my signed report describing my ceremony participation. I recorded my actions throughout, which involved running the ceremony step twice and randomly choosing one response to submit and the other to reveal in the report. I posted my report to the mailing list, whereupon I learned two things:
- The
powersoftau
code, unmodified, does not act determinisically with the random input provided by the user. I did not know it was using system randomness at all, and so my intended verifiable run was not usable as such. - The contribution received from me was corrupted; it did not have the same BLAKE2b hash as in my report, and one of the points inside of it did not lie on the curve. The BLAKE2b hash of the corrupted response file is
7d90a636ba0448245cadb7fde245e2f9b0556948b54f8eab51f32f1d7dbefcfdfcfe1eb9a392dac9f0b4a189295af43d9284b1b674a5908edc250cdfda5b7e63
.
Curiously, I computed the same corrupted hash for the response files sitting on the USB drive I used to transfer it from the compute node. So despite my poor internet there was no corruption during the upload process. This implies either there was corruption in writing the file to the USB drive, or my setup was compromised.
As it happens, I do have a DVD with the response file burned to it (I was going to use that originally, before realising I didn't have a way to read it on site), but I have yet to investigate it. If I ever do, I'll make another post with my findings.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Powers of Tau Operational Writeup
=================================
Round: 15
Date: 2017-11-22
Name: Jack Grigg
Location: UK
Challenge:
d27e5d6c5a7611f6690443d8a47c6ebd134bc863f05984d9b3d845060a3f036a
Response:
2c052c1f 039810e7 69779017 9943bdb9
d00a84fb 25593453 85af3826 1fbe061c
4dc79f4e 87da26f4 3202bcf4 3960db16
be870511 7f3de50c 8922b502 32a3e126
Procedure
=========
2017-11-18
- ----------
I withdrew cash from an ATM I happened to be passing in London.
2017-11-19
- ----------
I withdrew more cash from a different ATM. I then drove four hours south-west of
London to my grandmother's farm. She lives in a valley with no cell reception,
and her granite house is well-known in our family for its electromagnetic and
audio shielding properties (ie. WiFi reception sucks beyond the one room the
router is in, and you can't hear someone calling you from a few rooms away).
On the way down, I stopped in at a shopping center, turning off my phone and
leaving it in the car. I then purchased:
- - An HP Pavilion Notebook 15 (15-cd054na)
- I had no device in mind when I entered the store. After browsing the
available models, I chose this laptop based on a combination of price,
performance, the use of an AMD chip, and the presence of a DVD burner.
- I asked the sales assistant if I could choose a laptop at random from their
stock room. The manager confirmed I could not, as it was a secure area. I
asked them to bring out three laptops for me to choose from, which they did.
I flipped two coins to determine which of the three I chose.
- - Five identical USB drives
- - A stack of 10 DVD+R discs (which were eventually not used)
- - A screwdriver set
- - A soldering iron (which turned out to be unnecessary)
2017-11-20
- ----------
I unboxed the laptop, and opened it up. I removed the WiFi/Bluetooth chip, and
unplugged the built-in speakers. I then started the laptop and set up the
default Windows installation, confirming that there was no wireless connectivity
or sound, but the headphone jack still worked. I pried off the screen bezel,
unplugged the built-in camera and microphone array, and confirmed that they both
no longer worked (the microphone array still showed up as a device, but
registered no input).
I used Tor Browser and the Tails downloader plugin to download the Tails 3.3 ISO
(the first deterministically-built one) on my development laptop (a Thinkpad X1
Carbon Gen4), and verified its GPG signature. SHA256 hash of the ISO:
5ac6b8a563a999701aa394a0761ba3e29d5a964537549e5b4a81b2abf12a1c09
I also installed tails-live-installer from their PPA.
2017-11-22
- ----------
I opened up the laptop again, and confirmed that the wireless functionality and
speakers were still disabled. I then removed the hard drive and re-assembled the
laptop. From this point onward, I did not let the laptop (henceforth referred to
as the compute node), nor any of the USB drives, out of my sight for more than a
few seconds.
I rolled a dice to select one of the five USB drives at random. I used
tails-live-installer to install Tails 3.3 on the USB drive. I then realised that
I hadn't yet upgraded the drivers for my development laptop to fix the Intel
AMT/ME vulnerability. I booted into the Windows partition to do so. Following
this, I rebooted into Ubuntu again, imaged the USB drive, and then wiped it and
re-installed Tails 3.3.
I installed Docker CE on my development laptop, and used Andrew Miller's
Dockerfile to deterministically build the powersoftau compute binary. SHA256
hash:
922b2e0a59841ecdaba7b4953d8c67e62b74b8f52f968624cff664dc086da93a
On my Qubes 3.2 laptop (a Purism Librem 15) I created a disposable VM, and
downloaded the challenge file in it. SHA256 hash:
d27e5d6c5a7611f6690443d8a47c6ebd134bc863f05984d9b3d845060a3f036a
I created a fresh AppVM for staging (backed by the fully-upgraded
fedora-24-minimal TemplateVM) with network access. I ran the following commands:
$ su - (the minimal template does not have sudo)
$ dnf config-manager \
--add-repo \
https://download.docker.com/linux/fedora/docker-ce.repo
$ dnf install docker-ce
$ docker --version
Docker version 17.06.0-ce, build 02c1d87
$ systemctl start docker
$ docker run -it socrates1024/powersoftau
[snip]
Digest: sha256:3d42ec3bc947c410dca07e4bbbe5e88bf264b147ecaa87807ec58424f309b046
$ $ sha256sum target/x86_64-unknown-linux-musl/release/compute
922b2e0a59841ecdaba7b4953d8c67e62b74b8f52f968624cff664dc086da93a
Having obtained the same binary hash on both machines, I then fetched the
compute binary out of the staging AppVM's Docker container, and copied the
challenge file from the disposable AppVM to the staging AppVM. I also downloaded
EFF's long wordlist: https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt
SHA256 hash:
addd35536511597a02fa0a9ff1e5284677b8883b83e986e43f15a3db996b903e
BEGIN COMPUTATION STEPS
```````````````````````
I rolled a dice to select one of the four remaining USB drives at random. I
attached the USB drive to my Qubes laptop, and then redirected it from sys-usb
to the staging AppVM using qubes-usb on Dom0. I copied the challenge file, the
compute binary, and the wordlist to the USB drive.
I took the compute node, Tails USB drive, and challenge USB drive to a room at
the far end of the house (from the router), which had the most line-of-sight
granite surrounding it, and also had a large metal filing cabinet. I emptied one
of the drawers and set up the compute node inside it. I inserted the Tails USB
drive, started the compute node, and disabled SecureBoot. Once in the Tails
environment, I inserted the challenge USB drive, copied the compute binary and
wordlist to the Tails home directory (in RAM), and symlinked the challenge file
into that directory (as I didn't have enough RAM to hold the challenge file in
memory twice).
I started the compute binary, opened the wordlist, and then used five dice (of
assorted sizes, that I scrounged from around the house) in a cardboard box to
generate an eight-word random phrase. I typed the phrase into the compute binary
input (space-separated, no leading or trailing spaces), and also wrote it down
on the inside of a piece of folded card. I then started the computation process,
and closed the filing cabinet drawer. The computation took around 40 minutes,
during which I sat beside it, occasionally pulling the drawer open slightly to
check progress, and reading Serious Cryptography in between. At the point where
I noticed that the challenge itself had been read into memory, I unmounted and
removed the challenge USB drive.
After the computation was completed, I rolled a dice to select one of the three
remaining USB drives at random. I copied the response file to it, and used my
phone to tweet out the BLAKE2b hash printed by the compute binary:
2c052c1f 039810e7 69779017 9943bdb9
d00a84fb 25593453 85af3826 1fbe061c
4dc79f4e 87da26f4 3202bcf4 3960db16
be870511 7f3de50c 8922b502 32a3e126
I then shut down the compute node.
END COMPUTATION STEPS
`````````````````````
I repeated the steps above a second time (using the two remaining USB drives),
to obtain a second response file, and a second BLAKE2b hash:
3df44b57 4c66cb75 9bba2f2a 96b12ea1
9037a70c 4c898397 35ad6b3d 50b84715
39bfdea2 0d6e6db3 79ce6f3d 3d823d32
901d2651 20481863 45d99475 e63a91a9
Finally, I rolled a dice to decide which of the two responses to upload; the
dice landed on an odd number, meaning that I uploaded the first response. I am
revealing the randomness used to compute the second response:
boogeyman amber reverse oversight scorn impending wheat engraver
After typing in the above phrase, I burned the card on which I had written the
two random phrases. I opened up the compute node, and removed the battery and
RAM stick. I have not yet destroyed the RAM chips, and am keeping the stick on
my person until I am able to (so I've probably damaged it already with static).
I connected the USB drive containing the first response to my Qubes laptop, and
then redirected it from sys-usb to the staging AppVM. I then copied the response
to the disposable AppVM, and then into another AppVM to upload it to one of my
personal servers (as the upload to AWS was timing out).
Security Considerations
=======================
- - The laptop was chosen randomly, with as little unreported bias as possible,
and with my participation at that point only mentioned to Sean. However, a
sufficiently-motivated adversary could potentially have figured out that I was
participating, guessed which store I would go to on my route, and persuaded
the staff to alter the displays to draw my attention towards a particular
laptop. A constraint, or a private deterministic metric for selection, may
have helped to eliminate more bias.
- - Using a deterministically-built ISO for the operating system should make it
easier to determine the OS code that was running at the time, modulo the trust
in the machine that the live USB was built on (which is my Zcash dev laptop).
- - Using a fresh Qubes AppVM for staging increases the bar for having compromised
the OS in order to compromise the challenge USB drive.
- - Tails by default disables sudo and mounts itself as read-only, meaning that a
malicious userspace process shouldn't be able to persist data on that USB
drive.
- - Tails by default mounts plugged-in USB drives as read-write. Using a fresh USB
drive each time to transfer the compute binary, challenge and wordlist to the
compute node removed that as a vector for persistance between iterations.
- - Revealing the randomness in the unused response, after the compute node had
been shut down, should make it possible to ascertain that the compute binary
was behaving correctly, by having third parties independently re-compute the
corresponding response file and verify the hash against the one I published.
Things I'd Do Differently In Future
===================================
- - Pick somewhere with faster internet. The internet here isn't snappy to begin
with, and it was raining and blowing which significantly impacts speeds. As a
result, the challenge file took several hours to download, and the response
file took probably double that.
- - Use a DVD to set up the compute OS instead of a USB (and then load the OS into
RAM to free up the DVD drive). A DVD would in theory be more easily auditable,
putting less trust in the machine creating it than the live USB. This would
also increase the amount of RAM required in the machine (I ran this entirely
in 4GB memory).
- - Build the compute binary ahead of time. In particular, the time it took to
download Docker and build dependencies (twice) significantly extended the
setup time.
- - The binary was built deterministically, but it would be preferable to have it
only use dependencies and a compiler that could be reasonably assumed to not
have backdoors targeted at the MPC in general or participants in particular. I
did briefly try to compile Devrandom's branch, but decided determinism was
more important for now.
- - Monitor and keyboard. I had to open the filing cabinet drawer in order to type
in the randomness and monitor progress; an external monitor and keyboard would
limit the EM leakage of doing so.
- - Hardware separation of randomness. There was maybe 10 minutes between
compute iterations (as I created the second challenge USB drive), and the
battery was not removed in between (as that required disassembly), so there is
a small but non-zero possibility that the second computation could have been
influenced by (maliciously or otherwise) the first one. In this case it
happens to not matter much, as the random roll at the end selected the result
of the first computation, but in a future MPC I'd prefer to at least remove
the battery in between runs, and ideally swap out the RAM.
- - Different response extraction mechanism. I neglected to purchase a DVD reader
for my existing laptops, so could not use DVDs as the airgap mechanism,
falling back to the USB drives. I also had a more ambitious mechanism in mind,
but that will require significant additional development work.
- - Use a separate AppVM for staging the response. I had intended to do this (to
limit the ability of any malicious data hidden on the response USB to escape),
but reused the previous qubes-usb command neglecting to change the AppVM name.
Once it was connected to the challenge staging VM, I decided that any damage
had already been done, and continued.
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCgAGBQJaFib5AAoJEGZdvNKE99r/tHsP/jZjS+VbrYQz0pHi9MS4wQzP
4kErUDJgF8t6TkNj6W4ZCBIu9ryEQthUxpMgDEqbRFt9M7ueYB8bys9YUtna7fVJ
tyrj7UmPlYGOLs6QaFaE+TBhnDoWA+bdHNb5bHzC2mWaXwya3DYrW5ai7BA7/YUF
hcW5dMtyQRrL4vKMLWq500nhZ1n5aa0Njq0NJ3XEzDa3W4+Wq3nJBTk5NNXz0iAC
+h0j542AlrHcp4dzWf/PvBpZrnerpMlMatJmR/GN0153tbdFVs8zqPAfRmLvyl3m
vYPuW4S/QGUoKKsyM3zJps3QtaNQJooHkD8Y6nOBbX9piEURy2hZUMoPYhiIVyM7
T8wvt3UNXjBAzzoNWOSt8+s/OMGt+E++9bFKxOKqE2zXQAxIGGVxYfc563DHM051
BuYNSfYKwoFP5Cq2pU2j6WOGs20zQxh6ySRd8Iz1v5uJSQ0Z6+GJ9Ddc1Lo2YDpt
hcPa8oe2vGReuX33lN6PBNYjr+CkwV8metJXG+2irKCTGdgaBv+IweBUkP4SUxe6
C0kmxjgQ9BJ0/kW4EHeyIS1YGFAyZDbXedsaSRBvBNegnCYfCavPKBIYcRINrCPk
1XJ/J6Lhhc0xC4fILsXhot3uoAl1QHwT69a5Gfj/nTCSaJ6E3vbbaOgr8Igu6Jf8
VCTWs0YxUiG8EctFHElQ
=uVQb
-----END PGP SIGNATURE-----