Arvo Virtual Hardware Wallet

101 views
Skip to first unread message

Basile Genève

unread,
Oct 17, 2020, 4:15:37 AM10/17/20
to urbit-dev
~timluc-miptev
As I move ahead with the BTC provider/wallet bounty, it's starting to feel like a "virtual hardware wallet" is doable and desirable in Urbit, although there may be implementation/security considerations that I'm unaware of.

## Background
It's turned out to be easier/faster than I anticipated to port BTC transaction building and signing functionality to Urbit; I have pretty much everything working now that is needed to handle standard transactions (i.e. non-multisig/exotic scripts) from/to any of the 3 address types.  We can also now derive any address type from xpubs internally.

The win here is that everything except address balance querying and transaction broadcasting can now be done inside your Urbit.  This allows for a lot of potential schemes to eventually obfuscate the source of broadcasts and address balance queries, and also makes RPC providers more fungible/less load-bearing.

## Proposal
Given how much can be done internally, it seems logical to implement functionality in Arvo that:
- stores a keypair
- allows calls of the form: (hash, pubkey), where hash is a hash to be signed, and pubkey is the pubkey of the keypair (for lookup in that Arvo module)
- returns the signed hash

One could also, if desired, give the module access to Bitcoin transaction logic, so that it could tell the user the proposed inputs and outputs before consenting to signing. This part may be overkill if the core BTC userspace app is vetted, trusted, and infrequently updated.

This seems similar-ish to Jael, although I don't think that that has a generalized interface of this kind.

Obviously hardware wallets would continue to the be the standard for wallets with larger balances, but for wallets in the < $2K value range, this scheme would be a useability win imo, and also conceptually makes sense.  It also would dovetail with proposed ideas to generate wallets from the Azimuth master ticket.

I'm guessing there has been internal thought on this already, so very open to input. I'm probably also missing some security concerns, so let me know what comes to mind.

Basile Genève

unread,
Oct 17, 2020, 4:30:08 AM10/17/20
to urbit-dev, Basile Genève
Couple quick extra thoughts:
- "pubkey"s above would likely be BIP32 paths, with the mnemonic or an xprv stored initially in Arvo

- a big threat vector is phishing style attacks, where rogue userspace apps try and get you to sign things. One approach here would be to limit access to this Arvo module to only one userspace app (or a configurable set). Then that app (likely a wallet) would have its own set of approved Gall agents, and would proxy requests only for them.

Liam Fitzgerald

unread,
Oct 18, 2020, 7:26:06 PM10/18/20
to Basile Genève, urbit-dev
Your second point really outlines the need for some kind of agent
isolation in Gall. Consider the following quick sketch,
https://gist.github.com/liam-fitzgerald/a7efd327d3e6d1e2853f965b68a1d5a0
. When you say Arvo, do you mean kernelspace? I firmly think this
kind of functionality is squarely in userspace land. If you want to
keep private keys out of the event log, then Airlock is always a
viable option. You could even call out to a HSM for signing
transactions.
——
~hastuc-dibtux

https://urbit.org

Galen Wolfe-Pauly

unread,
Oct 22, 2020, 1:14:46 PM10/22/20
to Liam Fitzgerald, Basile Genève, urbit-dev
This is interesting. 

I've always felt like we want to avoid putting 'real' keys into Urbit for some time. We're working on auditing Ames, but there must be a 0 day or four lurking around the system. Perhaps the way to find them is to have people start 'living dangerously' — so I think this kind of thing is worth thinking about but should have some degree of warning thrown in if we actually encourage people to use it.

The way I've imagined doing this, in the short term, is to do exactly what you're talking about on the client-side. That is, alter our client to accept a master ticket and then create an API by which Urbit can request that the client sign something. The API would be similar to what you describe: a pubkey (and perhaps its location in the wallet hierarchy) and a hash to sign. Then the client could return the signed hash. The part of the client-side code that does the signing could be delivered in the initial download of the client (over https), and should not be possible to upgrade via urbit itself. Since your Urbit is updated over the air, the advantage of doing this client side is in part that we know where you got the 'virtual hardware wallet' code. As you might imagine, I always figured we'd do this as part of a standalone app. The app container would contain the virtual hardware wallet and some very basic machinery for logging in / connecting to your urbit, then we'd let urbit point to the most recent JS bundle for landscape as-needed.

The advantage to doing this client side is that the code footprint is easier to audit and the sandbox (the browser) is well understood. We could even provide affordances for calling out to a hardware wallet if one is available / used to log in.

I've always really liked the idea that the [ship ticket] pair is both identity *and* money, and can be kept in memory pretty easily.

Mark

unread,
Oct 22, 2020, 1:56:46 PM10/22/20
to Galen Wolfe-Pauly, Liam Fitzgerald, Basile Genève, urbit-dev
> https://gist.github.com/liam-fitzgerald/a7efd327d3e6d1e2853f965b68a1d5a0
> How do we allow agents to describe their own permissions?

This feels more "capabilities" than "permissions", but worth bringing up here:

Back in the day, gall applications typically defined the (constrained) type of the moves/cards they would produce in the application code itself. This made it easy to look at the source and see what the application would actually do. (Vanes still do this too, I believe.) These days, we just `+$ card card:agent:gall`, which doesn't really tell you anything.

For example, /app/talk explicitly only sent hall pokes, and only showed sole-effects to subscribers. It could've been more specific, but just to give you an idea:
https://github.com/urbit/urbit/blob/00ed6e59f022461be396ef076e6e7ed12081551b/pkg/arvo/app/talk.hoon#L53-L66

Vanes still do this, actually!
https://github.com/urbit/urbit/blob/e3dcfc637291d922376eb84df87e9bfa6f9e8e7d/pkg/arvo/sys/vane/dill.hoon#L32-L92

You could imagine formalizing this code style and making gall reject any cards you produce that don't match the spec you gave, even if they would fit the broader definition of card:agent:gall.


~palfun-foslup
https://urbit.org

Anton Dyudin

unread,
Oct 22, 2020, 2:11:45 PM10/22/20
to Mark, Basile Genève, Galen Wolfe-Pauly, Liam Fitzgerald, urbit-dev
I mean, you don't even need gall to reject anything, the type system should do it for you. And any app that really wanted could just put card:agent:gall right back into any formal thing.

--
To unsubscribe from this group and stop receiving emails from it, send an email to dev+uns...@urbit.org.

Basile Genève

unread,
Oct 24, 2020, 6:18:23 AM10/24/20
to urbit-dev, ga...@tlon.io, Basile Genève, urbit-dev, Liam
Yeah Galen, I now think that putting the virtual hw wallet outside of Urbit itself initially has advantages, mostly for the reasons you mention. In that case, Urbit would move towards having a very specific API for generating raw transactions to be signed, and the signer would be an implementation detail. (True hw wallet, stored in the client, etc.)

This means that there will be a short ganky period after "BTC Urbit"'s release when there isn't feature parity between true HW wallet signing and other forms, but that can likely be gotten through relatively quickly.

Galen Wolfe-Pauly

unread,
Oct 24, 2020, 12:28:05 PM10/24/20
to Basile Genève, urbit-dev, Liam
Right: so long as the API is simple and well designed, you could have the signing done on the client at first, and eventually move it to Urbit itself without too much pain. 

As far as the BTC work is concerned, I've always wanted to just extend the Urbit HD wallet to include an affordance for holding BTC (not too hard, and should probably include a privacy coin and a stablecoin eventually), and then let the signing and sending happen on the client. If people are bolting on bcoin nodes and offering transaction processing, we'd just be shuttling signed transactions around the network (i.e., over Ames).

I've always thought it'd be fun to write trading algorithms that my Urbit can execute. This is best served if my Urbit can sign and send transactions independently. Moving in that direction is super desirable, as there are plenty of other use cases like this that are easy to imagine.  
Reply all
Reply to author
Forward
0 new messages