ERC-1775: App Keys, application specific wallet accounts
Simple Summary
Among others cryptographic applications, scalability and privacy solutions for ethereum blockchain require that an user performs a significant amount of signing operations. It may also require her to watch some state and be ready to sign data automatically (e.g. sign a state or contest a withdraw). The way wallets currently implement accounts poses several obstacles to the development of a complete web3.0 experience both in terms of UX, security and privacy.
This proposal describes a standard and api for a new type of wallet accounts that are derived specifically for a each given application. We propose to call them app keys
. They allow to isolate the accounts used for each application, thus potentially increasing privacy. They also allow to give more control to the applications developers over account management and signing delegation. For these app keys, wallets can have a more permissive level of security (e.g. not requesting user's confirmation) while keeping main accounts secure. Finally wallets can also implement a different behavior such as allowing to sign transactions without broadcasting them.
This new accounts type can allow to significantly improve UX and permit new designs for applications of the crypto permissionned web.
Abstract
In a wallet, an user often holds most of her funds in her main accounts. These accounts require a significant level of security and should not be delegated in any way, this significantly impacts the design of cryptographic applications if a user has to manually confirm every action. Also often an user uses the same accounts across apps, which is a privacy and potentially also a security issue.
We introduce here a new account type, app keys, which permits signing delegation and accounts isolation across applications for privacy and security.
In this EIP, we provide a proposal on how to uniquely identify and authenticate each application, how to derive a master account (or app key) unique for the domain from an user private key (her root private key or any other private key of an account derived or not from her root one). This EIP aims at becoming a standard on how to derive keys specific to each application that can be regenerated from scratch without further input from the user if she restores her wallet and uses again the application for which this key was derived. These app keys can then be endowed a different set of permissions (through the requestPermission model introduced in EIP-2255). This will potentially allow an user to partly trust some apps to perform some crypto operations on their behalf without compromising any security with respect to her main accounts.
Motivation
Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, (see the discussion here). Web3 wallets have implemented in a roughly similar way the rpc eth api. EIP-1102 introduced privacy through non automatic opt-in of a wallet account into an app increasing privacy.
However several limitations remain in order to allow for proper design and UX for crypto permissioned apps.
Most of GUI based current wallets don't allow to:
- being able to automatically and effortlessly use different keys / accounts for each apps,
- being able to sign some app's action without prompting the user with the same level of security as sending funds from their main accounts,
- being able to use throwable keys to improve anonymity,
- effortlessly signing transactions for an app without broadcasting these while still being able to perform other transaction signing as usual from their main accounts,
- All this while being fully restorable using the user's mnemonic or hardware wallet and the HD Path determined uniquely by the app's ens name.
We try to overcome these limitations by introducing a new account's type, app keys, made to be used along side the existing main accounts.
These new app keys can permit to give more power and flexibility to the crypto apps developers. This can allow to improve a lot the UX of crypto dapps and to create new designs that were not possible before leveraging the ability to create and handle many accounts, to presign messages and broadcast them later. These features were not compatible with the level of security we were requesting for main accounts that hold most of an user's funds.
Specification
Applications
An app is a website (or other) that would like to request from a wallet to access a cryptographic key specifically derived for this usage. It can be any form of cryptography/identity relying application, Ethereum based but not only.
Once connected to a wallet, an application can request to access an account derived exclusively for that application using the following algorithm.
Private App Key generation algorithm
We now propose an algorithm to generate application keys that:
- are uniquely defined, with respect to the account that the user selected to generate these keys,
- and thus can be isolated when changing the user account, allowing persona management (see next section),
- are specific to each application,
- can be fully restored from the user master seed mnemonic and the applications' names.
Using different accounts as personas
We allow the user to span a different set of application keys by changing the account selected to generate each key. Thus from the same master seed mnemonic, an user can use each of her account index to generate an alternative set of application keys. One can describe this as using different personas. This would allow potentially an user to fully isolate her interaction with a given app across personas. One can use this for instance to create a personal and business profile for a given's domain both backup up from the same mnemonic, using 2 different accounts to generate these. The app or domain, will not be aware that it is the same person and mnemonic behind both. If an application interacts with several main accounts of an user, one of these accounts, a master account can be used as persona and the others as auxiliary accounts.
This EIP is agnostic about the way one generates the private keys used to span different app keys spaces. However for compatibility purposes and for clean disambiguation between personas and cryptocurrency accounts, a new EIP, distinct from this one but to be used alongside, will be proposed soon introducing clean persona generation and management.
Applications' Unique Identifiers
Each application is uniquely defined and authenticated by its origin, a domain string. It can be a Domain Name Service (DNS) name or, in the future, an Ethereum Name Service (ENS) name or IPFS hash.
For Ipfs or swam origins, but we could probably use the ipfs or swarm addresses as origin or we could require those to be pointed at through an ENS entry and use the ENS address as origin, although this would mean that the content it refers to could change. It would thus allow for different security and updatibility models.
We will probably require for protocol prefixes when using an ENS domain to point to an IPFS address:
ens://ipfs.snap.eth
Private App Key generation algorithm
Using the domain name of an application, we generate a private key for each application (and per main account) :
const appKeyPrivKey = keccak256(privKey + originString)
where +
is concatenation, privKey
is the private key of the user's account selected to span the application key and originString
represents the origin url from which the permission call to access the application key is originated from.
This is exposed as an RPC method to allow any domain to request its own app key associated with the current requested account (if available):
See here for an implementation: https://github.com/MetaMask/eth-simple-keyring/blob/master/index.js#L169
App keys and Hierarchical Deterministic keys
The app keys generated using the algorithm described in the previous section will not be BIP32 compliant. Therefore apps will not be able to create several app keys or use non-hardening and extended public keys techniques directly. They get a single private key (per origin, per persona). Yet they can use this as initial entropy to span a new HD tree and generate addresses that can be either hardened or not. Thus we should not be losing use cases.
Rationale
Sharing application keys across domains:
While this does not explicit cover cases of sharing these app keys between pages on its own, this need can be met by composition:
Since a domain would get a unique key per persona, and because domains can intercommunicate, one domain (app) could request another domain (signer) to perform its cryptographic operation on some data, with its appKey as a seed, potentially allowing new signing strategies to be added as easily as new websites.
This could also pass it to domains that are loading specific signing strategies. This may sound dangerous at first, but if a domain represents a static hash of a trusted cryptographic function implementation, it could be as safe as calling any audited internal dependency.
Privacy and the funding trail
If all an application needs to do with its keys is to sign messages and it does not require funding, then this EIP allows for privacy through the use of distinct keys for each application with a simple deterministic standard compatible across wallets.
However if these application keys require funding, there can be trail and the use of app keys would not fully solve the privacy problem there.
Mixers or anonymous ways of funding an ethereum address (ring signatures) along with this proposal would guarantee privacy.
Even if privacy is not solved fully without this anonymous funding method, we still need a way to easily create and restore different accounts/addresses for each application
Backwards Compatibility
From a wallet point of view, there does not seem to be compatibility issues since these are separate accounts from those that were used previously by wallets and they are supposed to be used along-side in synergy.
However, for applications that associated in some way their users to their main accounts may want to reflect on if and how they would like to leverage the power offered by app keys
to migrate to them and leverage on the new app designs they permit.
Implementation
Here is an early implementation of app keys for standard (non HW) MetaMask accounts. https://github.com/MetaMask/eth-simple-keyring/blob/6d12bd9d73adcccbe0b0c7e32a99d279085e2934/index.js#L139-L152
See here for a fork of MetaMask that implements app keys along side plugins: https://github.com/MetaMask/metamask-snaps-beta https://github.com/MetaMask/metamask-snaps-beta/wiki/Plugin-API
Example use cases
-
signing transactions without broadcasting them https://github.com/MetaMask/metamask-extension/issues/3475
-
token contract https://github.com/ethereum/EIPs/issues/85
-
default account for dapps https://ethereum-magicians.org/t/default-accounts-for-dapps/904
-
non wallet/crypto accounts EIP1581: Non-wallet usage of keys derived from BIP32 trees
-
state channel application
-
privacy solution
-
non custodian cross cryptocurrency exchange...
Acknowledgements
MetaMask team, Christian Lundkvist, Counterfactual team, Liam Horne, Erik Bryn, Richard Moore, Jeff Coleman.
References
HD and mnemonics
BIPs
Derivation path for eth
Previous proposals and discussions related to app keys
Copyright
Copyright and related rights waived via CC0.