I’m fortunate to be spending this week at Recurse Center, a fantastic “coder retreat” in Manhattan. Highly recommended!
My goals for this short stay are: (a) dust off some coding skills that started to grow rusty, and (b) become more fluent in my favorite software language.
To those ends, I’ve put together a set of
tools that construct, sign and submit
Ripple Consensus Ledger (RCL)
transactions. There’s a reason I explicitly list
submit. In these tools, each of those responsibilities is
handled by separate process.
For example, constuct a payment with the
rcl-tx tool, but don’t
sign or submit it:
# Send 20 XRP to rRC5GVM3i2wdPmsC3Jga3w5qz1rxvdGzG... rcl-tx send rRC5GVM3i2wdPmsC3Jga3w5qz1rxvdGzG 20/XRP > /tmp/rcl-transaction
Another example, sign that transaction with the
rcl-key tool, but still don’t submit it:
rcl-key sign < /tmp/rcl-transaction
The processes encode and decode transactions through input and output. Here’s an example that shows construct, sign, and submit in one shot (using pipes):
rcl-tx send rRC5GVM3i2wdPmsC3Jga3w5qz1rxvdGzG 20/XRP | rcl-key sign | rcl-tx submit
(The tools and more examples can be found at https://github.com/dncohen/rcl.)
Why three process to submit a single transaction? I’m glad you asked…
One reason is to maintain a bare minimum of signing code. This is the code that will work with secret keys. As such, it needs to be held to a high standard: never leak a secret. A larger codebase with more dependencies means more to audit and test for security.
Code that constructs or submits transactions must communicate with network servers. But signing code doesn’t need to. It can and should be isolated. The highest standard is to keep the signing process, and the secrets it needs, on an air gapped and tamper-proof machine. Merely using a another process, shown above, doesn’t meet that standard, but it does separate the concern of signing from the concerns of preparing and submitting. This means, in principal, the signing task could be moved to a more secure environment.
Poor Man’s Air Gap
I’m a fan of Qubes, a desktop environment
that keeps thing reasonably secure through isolation. Qubes comes
with split-gpg, which
isolates gpg keys into a separate virtual machine from the processes
that rely on encrypted or signed documents. The
example above, can be set up the same way.
Here, briefly, is how that is done. (Full details: here)
Vault VM with Secrets
Use qvm-copy to install
rcl-key in the
On that VM, create
/etc/qubes-rpc/rcl.Sign script to execute
#!/bin/sh /usr/local/bin/rcl-key sign
I can create my RCL signing key here on the
vault VM (the secret key never leaves the vault)…
(Either fund the address created, or configure an account to use that as a regular key. Topics beyond the scope of this post.)
AppVM with RCL Tools
On the appvm where you’ve installed the tools, create
#!/bin/sh signvm=vault qrexec-client-vm $signvm rcl.Sign
On dom0, set up the privileges. This works for me in
/etc/qubes-rpc/policy/rcl.Sign, for an appvm named
rcl vault allow $anyvm vault ask $anyvm $anyvm deny
With this setup, I can replace
rcl-key sign with
rcl-sign-split in my earlier example…
rcl-tx send rRC5GVM3i2wdPmsC3Jga3w5qz1rxvdGzG 20/XRP | rcl-sign-split | rcl-tx submit