Skip to content

Instantly share code, notes, and snippets.

@danfinlay
Created November 3, 2017 04:29
Show Gist options
  • Select an option

  • Save danfinlay/84f33e232f28764664142b01b89bb7ed to your computer and use it in GitHub Desktop.

Select an option

Save danfinlay/84f33e232f28764664142b01b89bb7ed to your computer and use it in GitHub Desktop.
MetaMask: Multi Signer Types?

Multi Sign-Type Proposal

Intended Audience

Maintainers and influencers of cryptographically-secured peer-to-peer protocols, espeically those concerned with the user experience and thus real adoption of these secure protocols.

Context

Today MetaMask is an Ethereum account manager and blockchain API provider, and it's made Ethereum useful G

The accounts it manages don't need to only be Ethereum-type keys, and with account abstraction, increasingly these key types will need to become more modular than they are today.

API

Here let's re-imagine the method web3.eth.getAccounts(cb). By including an options object, we give the web3 signer liberty to provide any of a variety of key types.

For these code examples, a hypothetical pseudo-web3 object will be used.

const accounts = await web3.requestAccount({
  type: 'ethereum' || 'ssb' || 'rsa2048',
})

Here we show a variety of possible account types that a site might request a user to have. The cool thing about this method, is that the user does not need to have an account of this type created at this point in order to create one now.

The signer browser (MetaMask, Mist, Beaker, whatever) would only need to prompt the user to generate a new account at this time, or select an existing one, and so now "account creation" could be on a per-protocol basis, instead of per-site.

Selective Disclosure

Additionally, this API would be favorable to verifiable claims compatible identity solutions with minor additions.

For example, here let's imagine a uPort-style DID (Decentralized Identifier) based site. There are a variety of projects following a general DID-type format, and so a variety of different account types should all be able to answer similar questions:

const accounts = await web3.requestAccount({
  type: 'ethereum' || 'SOVRN' || 'civic',
  withPersonalInfo: {
    'dob': {
      required: true,
      min: '18y',
    },
    'city': {
      required: false,
    }
  },
})

Here I've laid out a simple basic schema for requesting proof of some personal details, along with a public key of a given type.

This raises a question of the return type. If some additional metadata should be supplied with an account, then the return type should not just be an address. Especially given that a site might not care what type of account you're using, as long as it can return the given personal information:

const accounts = await web3.requestAccount({
  withPersonalInfo: {
    'dob': {
      required: true,
      min: '18y',
    },
    'city': {
      required: false,
    }
  },
})

/*
   {
      type: 'BHRARER', // User selected, who cares?
      id: '0x1234567890abcdef', // An identifier for the given account.
                                // Used for requesting it signs messages.
      details: {
        'dob': { min: '18y', proof: <PROOF_FORMAT> },
      }
   }
*/

That's just a rough example of a request & response for information, without caring about the specifics of the key pair. If a user wants to trust some kind of strange encryption, who cares? It's securing their account, after all, they should be able to decide on their own security model.

For the purpose of key-type agnosticism, all signing methods should define the key or account type as part of the signing request, avoiding specialized key-type-dependent APIs like web3.eth.sendTransaction. Maybe something more like:

const account = await web3.requestAccount(opts)

const opts = {
  value: '0x123',
  to: RECIPIENT,
}

const signature = await web3.signAndHandle(account, opts)

In this context, the account type might dictate the way the opts are interpreted.

User Interface Modularity

Part of the difficulty of implementing this is that different key types have different implications for signing different types of information. For example, a bitcoin key signature mostly needs to render the amount of bitcoin being sent, and a PGP key pair mostly needs to show the information being signed as its native file type.

It may be best that each key type is much like a full module or extension, with its own support team maintaining its own approval screens. I can vouch that representing Ethereum transactions alone is worthy of a team of software developers, and I expect that as protocols evolve and analysis matures, there will be no shortage of ways that thoughtful designers and engineers can make the approval of signatures increasingly informative and useful to people of all skill levels. Consent can not be left to experts. Users should be able to reason about the terms they agree to.

Not only is the method that a signature is represented & conducted important, but some protocols (like blockchains) also include some form of client-managed transmission or storage of that signature. When the specifics of how a proposed transaction is processed, represented, handled, and returned are this open-ended, the value of a modular system becomes increasingly important.

To be honest, I was thinking about a modular ethereum signing mechanism just last year, and I went "simple" on it for the sake of pragmatism. In retrospect, I might've gone even more pragmatic to save myself time, except for the experience & insight I got from pursuing a more modular architecture.

A Pile of Relevant Tools

If something like the proposed interface were to be added to MetaMask, making it a highly generic client-side account manager, we would need a very secure and extensible interface for using any number of keys.

Sandboxing the account's relevant views in iFrames could be a powerful way to control a web site's API access to a higher-level context. For this reason, I think allowing a signing strategy to specify an iFrame URL or set of URLs would likely be a useful tool in creating a highly modular signing framework.

It's also worth noting that every signature does not necessarily require a user confirmation. SSH is a good example, and the analogy can be extended to even the internet of value and blockchains with state channels. An advanced signer might get user approval for transactions of up to a certain limit per day for a certain website. All of this could be managed by a modular account manager, and would not need to be the concern of MetaMask core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment