aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-05-02 18:31:05 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-05-02 18:31:05 +0800
commit5d4d79ae2672b295a539cf3ce0163b2cb10eb2b2 (patch)
treed56b5e8aa13a14d27aa3ce52b8f59cff304927ea /cmd
parent6a01363d1ddb15fa79817c425de472066e72a094 (diff)
downloaddexon-5d4d79ae2672b295a539cf3ce0163b2cb10eb2b2.tar.gz
dexon-5d4d79ae2672b295a539cf3ce0163b2cb10eb2b2.tar.zst
dexon-5d4d79ae2672b295a539cf3ce0163b2cb10eb2b2.zip
cmd/clef: documentation about setup (#16568)
clef: documentation about setup
Diffstat (limited to 'cmd')
-rw-r--r--cmd/clef/README.md15
-rw-r--r--cmd/clef/docs/qubes/clef_qubes_http.pngbin0 -> 14302 bytes
-rw-r--r--cmd/clef/docs/qubes/clef_qubes_qrexec.pngbin0 -> 20261 bytes
-rw-r--r--cmd/clef/docs/qubes/qrexec-example.pngbin0 -> 19109 bytes
-rw-r--r--cmd/clef/docs/qubes/qubes-client.py23
-rw-r--r--cmd/clef/docs/qubes/qubes.Clefsign16
-rw-r--r--cmd/clef/docs/qubes/qubes_newaccount-1.pngbin0 -> 25142 bytes
-rw-r--r--cmd/clef/docs/qubes/qubes_newaccount-2.pngbin0 -> 42747 bytes
-rw-r--r--cmd/clef/docs/setup.md198
9 files changed, 251 insertions, 1 deletions
diff --git a/cmd/clef/README.md b/cmd/clef/README.md
index 93799a761..027c22c98 100644
--- a/cmd/clef/README.md
+++ b/cmd/clef/README.md
@@ -12,6 +12,11 @@ synchronised with the chain or a particular Ethereum node that has no built-in (
Clef can run as a daemon on the same machine, or off a usb-stick like [usb armory](https://inversepath.com/usbarmory),
or a separate VM in a [QubesOS](https://www.qubes-os.org/) type os setup.
+Check out
+
+* the [tutorial](tutorial.md) for some concrete examples on how the signer works.
+* the [setup docs](docs/setup.md) for some information on how to configure it to work on QubesOS or USBArmory.
+
## Command line flags
Clef accepts the following command line options:
@@ -49,7 +54,6 @@ Example:
signer -keystore /my/keystore -chainid 4
```
-Check out the [tutorial](tutorial.md) for some concrete examples on how the signer works.
## Security model
@@ -862,3 +866,12 @@ A UI should conform to the following rules.
along with the UI.
+### UI Implementations
+
+There are a couple of implementation for a UI. We'll try to keep this list up to date.
+
+| Name | Repo | UI type| No external resources| Blocky support| Verifies permissions | Hash information | No secondary storage | Statically linked| Can modify parameters|
+| ---- | ---- | -------| ---- | ---- | ---- |---- | ---- | ---- | ---- |
+| QtSigner| https://github.com/holiman/qtsigner/| Python3/QT-based| :+1:| :+1:| :+1:| :+1:| :+1:| :x: | :+1: (partially)|
+| GtkSigner| https://github.com/holiman/gtksigner| Python3/GTK-based| :+1:| :x:| :x:| :+1:| :+1:| :x: | :x: |
+| Frame | https://github.com/floating/frame/commits/go-signer| Electron-based| :x:| :x:| :x:| :x:| ?| :x: | :x: |
diff --git a/cmd/clef/docs/qubes/clef_qubes_http.png b/cmd/clef/docs/qubes/clef_qubes_http.png
new file mode 100644
index 000000000..a641e1987
--- /dev/null
+++ b/cmd/clef/docs/qubes/clef_qubes_http.png
Binary files differ
diff --git a/cmd/clef/docs/qubes/clef_qubes_qrexec.png b/cmd/clef/docs/qubes/clef_qubes_qrexec.png
new file mode 100644
index 000000000..f57fc8933
--- /dev/null
+++ b/cmd/clef/docs/qubes/clef_qubes_qrexec.png
Binary files differ
diff --git a/cmd/clef/docs/qubes/qrexec-example.png b/cmd/clef/docs/qubes/qrexec-example.png
new file mode 100644
index 000000000..0d86fde19
--- /dev/null
+++ b/cmd/clef/docs/qubes/qrexec-example.png
Binary files differ
diff --git a/cmd/clef/docs/qubes/qubes-client.py b/cmd/clef/docs/qubes/qubes-client.py
new file mode 100644
index 000000000..93a74b899
--- /dev/null
+++ b/cmd/clef/docs/qubes/qubes-client.py
@@ -0,0 +1,23 @@
+"""
+This implements a dispatcher which listens to localhost:8550, and proxies
+requests via qrexec to the service qubes.EthSign on a target domain
+"""
+
+import http.server
+import socketserver,subprocess
+
+PORT=8550
+TARGET_DOMAIN= 'debian-work'
+
+class Dispatcher(http.server.BaseHTTPRequestHandler):
+ def do_POST(self):
+ post_data = self.rfile.read(int(self.headers['Content-Length']))
+ p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ output = p.communicate(post_data)[0]
+ self.wfile.write(output)
+
+
+with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
+ print("Serving at port", PORT)
+ httpd.serve_forever()
+
diff --git a/cmd/clef/docs/qubes/qubes.Clefsign b/cmd/clef/docs/qubes/qubes.Clefsign
new file mode 100644
index 000000000..9b5af7b4f
--- /dev/null
+++ b/cmd/clef/docs/qubes/qubes.Clefsign
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+SIGNER_BIN="/home/user/tools/clef/clef"
+SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
+
+# Start clef if not already started
+if [ ! -S /home/user/.clef/clef.ipc ]; then
+ $SIGNER_CMD &
+ sleep 1
+fi
+
+# Should be started by now
+if [ -S /home/user/.clef/clef.ipc ]; then
+ # Post incoming request to HTTP channel
+ curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
+fi
diff --git a/cmd/clef/docs/qubes/qubes_newaccount-1.png b/cmd/clef/docs/qubes/qubes_newaccount-1.png
new file mode 100644
index 000000000..598dbbee7
--- /dev/null
+++ b/cmd/clef/docs/qubes/qubes_newaccount-1.png
Binary files differ
diff --git a/cmd/clef/docs/qubes/qubes_newaccount-2.png b/cmd/clef/docs/qubes/qubes_newaccount-2.png
new file mode 100644
index 000000000..cd762a193
--- /dev/null
+++ b/cmd/clef/docs/qubes/qubes_newaccount-2.png
Binary files differ
diff --git a/cmd/clef/docs/setup.md b/cmd/clef/docs/setup.md
new file mode 100644
index 000000000..33d2b0381
--- /dev/null
+++ b/cmd/clef/docs/setup.md
@@ -0,0 +1,198 @@
+# Setting up Clef
+
+This document describes how Clef can be used in a more secure manner than executing it from your everyday laptop,
+in order to ensure that the keys remain safe in the event that your computer should get compromised.
+
+## Qubes OS
+
+
+### Background
+
+The Qubes operating system is based around virtual machines (qubes), where a set of virtual machines are configured, typically for
+different purposes such as:
+
+- personal
+ - Your personal email, browsing etc
+- work
+ - Work email etc
+- vault
+ - a VM without network access, where gpg-keys and/or keepass credentials are stored.
+
+A couple of dedicated virtual machines handle externalities:
+
+- sys-net provides networking to all other (network-enabled) machines
+- sys-firewall handles firewall rules
+- sys-usb handles USB devices, and can map usb-devices to certain qubes.
+
+The goal of this document is to describe how we can set up clef to provide secure transaction
+signing from a `vault` vm, to another networked qube which runs Dapps.
+
+### Setup
+
+There are two ways that this can be achieved: integrated via Qubes or integrated via networking.
+
+
+#### 1. Qubes Integrated
+
+Qubes provdes a facility for inter-qubes communication via `qrexec`. A qube can request to make a cross-qube RPC request
+to another qube. The OS then asks the user if the call is permitted.
+
+![Example](qubes/qrexec-example.png)
+
+A policy-file can be created to allow such interaction. On the `target` domain, a service is invoked which can read the
+`stdin` from the `client` qube.
+
+This is how [Split GPG](https://www.qubes-os.org/doc/split-gpg/) is implemented. We can set up Clef the same way:
+
+##### Server
+
+![Clef via qrexec](qubes/clef_qubes_qrexec.png)
+
+On the `target` qubes, we need to define the rpc service.
+
+[qubes.Clefsign](qubes/qubes.Clefsign):
+
+```bash
+#!/bin/bash
+
+SIGNER_BIN="/home/user/tools/clef/clef"
+SIGNER_CMD="/home/user/tools/gtksigner/gtkui.py -s $SIGNER_BIN"
+
+# Start clef if not already started
+if [ ! -S /home/user/.clef/clef.ipc ]; then
+ $SIGNER_CMD &
+ sleep 1
+fi
+
+# Should be started by now
+if [ -S /home/user/.clef/clef.ipc ]; then
+ # Post incoming request to HTTP channel
+ curl -H "Content-Type: application/json" -X POST -d @- http://localhost:8550 2>/dev/null
+fi
+
+```
+This RPC service is not complete (see notes about HTTP headers below), but works as a proof-of-concept.
+It will forward the data received on `stdin` (forwarded by the OS) to Clef's HTTP channel.
+
+It would have been possible to send data directly to the `/home/user/.clef/.clef.ipc`
+socket via e.g `nc -U /home/user/.clef/clef.ipc`, but the reason for sending the request
+data over `HTTP` instead of `IPC` is that we want the ability to forward `HTTP` headers.
+
+To enable the service:
+
+``` bash
+sudo cp qubes.Clefsign /etc/qubes-rpc/
+sudo chmod +x /etc/qubes-rpc/ qubes.Clefsign
+```
+
+This setup uses [gtksigner](https://github.com/holiman/gtksigner), which is a very minimal GTK-based UI that works well
+with minimal requirements.
+
+##### Client
+
+
+On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it.
+
+
+[qubes-client.py](qubes/client/qubes-client.py):
+
+```python
+
+"""
+This implements a dispatcher which listens to localhost:8550, and proxies
+requests via qrexec to the service qubes.EthSign on a target domain
+"""
+
+import http.server
+import socketserver,subprocess
+
+PORT=8550
+TARGET_DOMAIN= 'debian-work'
+
+class Dispatcher(http.server.BaseHTTPRequestHandler):
+ def do_POST(self):
+ post_data = self.rfile.read(int(self.headers['Content-Length']))
+ p = subprocess.Popen(['/usr/bin/qrexec-client-vm',TARGET_DOMAIN,'qubes.Clefsign'],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ output = p.communicate(post_data)[0]
+ self.wfile.write(output)
+
+
+with socketserver.TCPServer(("",PORT), Dispatcher) as httpd:
+ print("Serving at port", PORT)
+ httpd.serve_forever()
+
+
+```
+
+#### Testing
+
+To test the flow, if we have set up `debian-work` as the `target`, we can do
+
+```bash
+$ cat newaccnt.json
+{ "id": 0, "jsonrpc": "2.0","method": "account_new","params": []}
+
+$ cat newaccnt.json| qrexec-client-vm debian-work qubes.Clefsign
+```
+
+This should pop up first a dialog to allow the IPC call:
+
+![one](qubes/qubes_newaccount-1.png)
+
+Followed by a GTK-dialog to approve the operation
+
+![two](qubes/qubes_newaccount-2.png)
+
+To test the full flow, we use the client wrapper. Start it on the `client` qube:
+```
+[user@work qubes]$ python3 qubes-client.py
+```
+
+Make the request over http (`client` qube):
+```
+[user@work clef]$ cat newaccnt.json | curl -X POST -d @- http://localhost:8550
+```
+And it should show the same popups again.
+
+##### Pros and cons
+
+The benefits of this setup are:
+
+- This is the qubes-os intended model for inter-qube communication,
+- and thus benefits from qubes-os dialogs and policies for user approval
+
+However, it comes with a couple of drawbacks:
+
+- The `qubes-gpg-client` must forward the http request via RPC to the `target` qube. When doing so, the proxy
+ will either drop important headers, or replace them.
+ - The `Host` header is most likely `localhost`
+ - The `Origin` header must be forwarded
+ - Information about the remote ip must be added as a `X-Forwarded-For`. However, Clef cannot always trust an `XFF` header,
+ since malicious clients may lie about `XFF` in order to fool the http server into believing it comes from another address.
+- Even with a policy in place to allow rpc-calls between `caller` and `target`, there will be several popups:
+ - One qubes-specific where the user specifies the `target` vm
+ - One clef-specific to approve the transaction
+
+
+#### 2. Network integrated
+
+The second way to set up Clef on a qubes system is to allow networking, and have Clef listen to a port which is accessible
+form other qubes.
+
+![Clef via http](qubes/clef_qubes_http.png)
+
+
+
+
+## USBArmory
+
+The [USB armory](https://inversepath.com/usbarmory) is an open source hardware design with an 800 Mhz ARM processor. It is a pocket-size
+computer. When inserted into a laptop, it identifies itself as a USB network interface, basically adding another network
+to your computer. Over this new network interface, you can SSH into the device.
+
+Running Clef off a USB armory means that you can use the armory as a very versatile offline computer, which only
+ever connects to a local network between your computer and the device itself.
+
+Needless to say, the while this model should be fairly secure against remote attacks, an attacker with physical access
+to the USB Armory would trivially be able to extract the contents of the device filesystem.
+