EIP-1775 - App Keys, application specific wallet accounts (#1775)

This commit is contained in:
Vincent 2019-05-05 23:09:31 +02:00 committed by Nick Savers
parent b859ddbb46
commit b922d59340
1 changed files with 634 additions and 0 deletions

634
EIPS/eip-1775.md Normal file
View File

@ -0,0 +1,634 @@
---
eip: 1775
title: App Keys, application specific wallet accounts
author: Vincent Eli (@Bunjin), Dan Finlay (@DanFinlay)
discussions-to: https://ethereum-magicians.org/t/eip-erc-app-keys-application-specific-wallet-accounts/2742
status: Draft
type: Standards Track
category: ERC
created: 2019-02-20
requires: 137
---
<!--You can leave these HTML comments in your merged EIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new EIPs. Note that an EIP number will be assigned by an editor. When opening a pull request to submit your EIP, please use an abbreviated title in the filename, `eip-draft_title_abbrev.md`. The title should be 44 characters or less.-->
## Simple Summary
<!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the EIP.-->
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 developpers 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
<!--A short (~200 word) description of the technical issue being addressed.-->
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 the accounts along an Hierachical Deterministic (HD) path restricted for the domain and we finally define an API for applications to derive and use these app keys. This ERC aims at finding a standard that will fit the needs of wallets and application developers while also allowing app keys to be used across wallets and yield the same accounts for the user for each application.
## Motivation
<!--The motivation is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. EIP submissions without sufficient motivation may be rejected outright.-->
Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, [(see the discussion here)](https://github.com/ethereum/EIPs/issues/84). Web3 wallets have implemented in a roughly similar way the rpc eth api. [EIP1102](https://eips.ethereum.org/EIPS/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
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (go-ethereum, parity, cpp-ethereum, ethereumj, ethereumjs, and [others](https://github.com/ethereum/wiki/wiki/Clients)).-->
### Applications
An app is a website (or other) that would like to request from a wallet to access app keys. It can be any form of cryptography/identity relying application, ethereum but not only.
Once connected to a wallet, an application can request to access a set of accounts derived exclusively for that application using the hierarchical deterministic (HD) paths.
### Applications' HD path
Using the BIP32 and BIP43 standards, we propose to use the following HD path for each app keys:
`m / [standardized Path Beginning]' / [persona path]' / [application uniquely assigned path]' / [app's custom subpath]`
Where:
`standardized HD Path Beginning` is based on the EIP number that will be assigned to this EIP and we harden it. We use a different path than 44' since it's not bip44 compliant. At this point, I'm not sure if there is a list of BIP43 codes of standards following the `purpose` field specification of [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki).
`persona path` allows to use applications with different and isolated personas (or in other words accounts) that are tracable by the application. They will still be fully restorable from the same mnemonic.
`application uniquely assigned path` isolate each application along unique branches of the tree through these unique subPath combination.
`app's custom subPath` give freedom to application to use this BIP32 compliant subPath to manage accounts and other needed parameters.
Note that we suggest that each of these indexes, except those belonging to the app's custom subpath, must be hardened to fully isolate the public keys across personas and applications.
### Standardized HD Path Beginning
For the path header, several alternative are possible depending on what the cryptocommunities agree upon.
The least contentious is the following one (as suggested [here in the BIP repository](https://github.com/bitcoin/bips/pull/523)):
` 43' / 60' / 1775 ' `
However, there may be benefits to use only one depth instead of 3. We could use the `EIP Number'` (ie. 1775) or a ` BIP Number'` if we attain some cross crypto agreement that would avoid collision.
### Personas
We allow the user to use different personas in combination to her mnemonic to potentially fully isolate her interaction with a given app accross 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 personnas indexes. The app or domain, will not be aware that it is the same person and mnemonic behind both.
We use a string following BIP32 format (can be hardened) to define personas.
The indexes should be hex under 0x80000000, 31 bits.
E.g. `0'` or `0'/1/2'/0` or `1d7b'/a41c'`
### Applications' Unique Identifiers
#### Applications Names
We need a way to uniquely identify each application. We will use a naming and a hashing scheme.
In our favored spec, each application is uniquely defined and authenticated by its name, a domain string. It can be a Domain Name Service DNS name or and Ethereum Name Service ENS name.
There are a few restrictions however on the characters used and normalisation, each name should be passed through the [NamePrep Algorithm](https://tools.ietf.org/html/rfc3491)
In addition there must be a maximum size to the domain string that we need to determine such that the mapping from strings to nodes remains injective, to avoid collision.
We recommend this standard to be following the [ENS Specs](http://docs.ens.domains/en/latest/implementers.html#namehash), reproduced below for convinience and reference.
```
Normalising and validating names
Before a name can be converted to a node hash using Namehash, the name must first be normalised and checked for validity - for instance, converting fOO.eth into foo.eth, and prohibiting names containing forbidden characters such as underscores. It is crucial that all applications follow the same set of rules for normalisation and validation, as otherwise two users entering the same name on different systems may resolve the same human-readable name into two different ENS names.
```
#### Hashing and Applications UIDs
The ENS uses an hashing scheme to associate a domain to a unique hash, `node`, through the `namehash` function. We will use this hashing scheme both for ENS and for DNS names.
This gives an unique identifier (UID) of 32 bytes.
```
e.g. for foo.bar.eth
app's uid 0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3
```
For reference, here are the specs of ENS:
```
domain - the complete, human-readable form of a name; eg, vitalik.wallet.eth.
label - a single component of a domain; eg, vitalik, wallet, or eth. A label may not contain a period (.).
label hash - the output of the keccak-256 function applied to a label; eg, keccak256(eth) = 0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0.
node - the output of the namehash function, used to uniquely identify a name in ENS.
Algorithm
First, a domain is divided into labels by splitting on periods (.). So, vitalik.wallet.eth becomes the list [vitalik, wallet, eth].
The namehash function is then defined recursively as follows:
namehash([]) = 0x0000000000000000000000000000000000000000000000000000000000000000
namehash([label, …]) = keccak256(namehash(…), keccak256(label))
keccak256(eth) = 0x4f5b812789fc606be1b3b16908db13fc7a9adf7ca72641f84d75b47069d3d7f0
```
We thus propose to use the node of each app's domain as a unique identifier for each app but one can think of other UIDs, we include some alternative specs in the [Rationale](#Rationale) section below.
### Applications' authentication
If the application is using a DNS name then we simply authenticate the application by using the url of the loaded browser webpage.
For applications using ENS, we can authenticate the application through ENS resolution.
The ENS can also allow to register and resolve metadata for the application such as `url`, and other parameters.
If we use for instance this resolver profile defined in [EIP634](https://eips.ethereum.org/EIPS/eip-634) which permits the lookup of arbitrary key-value text data, we can for instance use the key `url` to point to a website.
```
A new resolver interface is defined, consisting of the following method:
function text(bytes32 node, string key) constant returns (string text);
The interface ID of this interface is 0x59d1d43c.
The text data may be any arbitrary UTF-8 string. If the key is not present, the empty string must be returned.
```
One can think of other authentication methods and even use some of them alongside the url-resolution method through ENS. We mention other methods in the [Rationale](#Rationale) section.
We suggest for instance to also add an `authorEthAddress` text metadata field that can be used to authenticate messages from the application, with for instance a sign challenge.
### Applications UID decomposition to get a BIP32 HD path
Since each child index in an HD path only has 31 bits we will decompose the domain's hash as several child indexes, first as hex bytes then parsed as integers.
For the applications's uid we use an `ENS namehash node` of 32 bytes, 256 bits (removing the leading `0x`).
e.g. `foo.bar.eth` which gives the following namehash node: `0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3`
We can decompose it in several ways, here are 2 potential ways:
* First approach could favor having the least indexes:
This requires to first convert the hex uid to 256 bits then decompose it as 8 * 31 bits + 8 bits
```
x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7 || x8
```
where `x0` to `x7` are 31 bits and `x8` is 8 bits
then we convert the `x_i` to uints.
The derivation sub-path would be:
`x0'/x1'/x2'/x3'/x4'/x5'/x6'/x7'/x8'`
```
E.g.
foo.bar.eth
0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3
converted to binary (256 bits)
6033644d673b
011000000011001101100100010011010110011100111011
47b3bea04e79
010001111011001110111110101000000100111001111001
bbe06d78ce76
101110111110000001101101011110001100111001110110
b8be2fb8704f
101110001011111000101111101110000111000001001111
9c2a80fd139c
100111000010101010000000111111010001001110011100
81d3
1000000111010011
256 bits:
0110000000110011011001000100110101100111001110110100011110110011101111101010000001001110011110011011101111100000011011010111100011001110011101101011100010111110001011111011100001110000010011111001110000101010100000001111110100010011100111001000000111010011
converted to less than or equal to 31 bits indexes:
8 * 31 bits + 1 * 8 bits
0110000000110011011001000100110
1011001110011101101000111101100
1110111110101000000100111001111
0011011101111100000011011010111
1000110011100111011010111000101
1111000101111101110000111000001
0011111001110000101010100000001
1111101000100111001110010000001
11010011
and converted to uints
806990374'/1506726380'/2010384847'/465438423'/1181988293'/2025775553'/523785473'/2098437249'/211'
```
* Second approach favors an homogenous decomposition:
Equal lenght indexes would be 16 * 16 bits or in other words 16 * 2 bytes, cleanest and favored spec:
```
x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7 || x8 || x9 || x10 || x11 || x12 || x13 || x14 || x15
where || is concatenation
```
```
E.g.
foo.bar.eth
0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3
6033 644d 673b 47b3 bea0 4e79 bbe0 6d78 ce76 b8be 2fb8 704f 9c2a 80fd 139c 81d3
6033'/644d'/673b'/47b3'/bea0'/4e79'/bbe0'/6d78'/ce76'/b8be'/2fb8'/704f'/9c2a'/80fd'/139c'/81d3'
24627'/25677'/26427'/18355'/48800'/20089'/48096'/28024'/52854'/47294'/12216'/28751'/39978'/33021'/5020'/33235'
```
Between these 2 decomposition approaches, there is a trade-off between computational efficiency (having less depth) and having an homegenous decomposition. We tend to favor the first approach with least indexes.
### Application customisable HD sub path
Finally, the last part of the hd path is under the application's control. This will allow applications developers to use the HD path structure that best fits their needs. Developers can for instance, among any combination of other parameters they like, choose to include a `version` field if they would like to use different signing accounts when updating to a new version. They can then also manage the user accounts in the way they would like, for instance including or not an index for `sets of accounts` (called `accounts` in BIP44), an index for `change` and an index for `account` (called `address_index` in BIP44).
We consider that a given child on the HD tree should be called an `account` and not an `address` since it is composed of a private key, a public key and an address.
Similarly to the persona path, this sub path must follow bip32, with hex under 0x80000000, 31 bits.
It can be hardened depending on each application's needs and can be writen as hex or unsigned integers.
It can include a large number of indexes.
Q [Should we set a limit on the persona and application customsable hd path number of indexes?]
### Example HD paths for app keys:
```
Dummy data:
EIP Number: 1775
personaPath: 0'/712'
application's name: foo.bar.eth
uid: 0x6033644d673b47b3bea04e79bbe06d78ce76b8be2fb8704f9c2a80fd139c81d3
app custom path params: app_version, set_of_accounts_index, account_index
```
`m/43'/60'/1775'/0'/712'/806990374'/1506726380'/2010384847'/465438423'/1181988293'/2025775553'/523785473'/2098437249'/211'/0'/0'/0`
## API:
We propose to introduce new RPC methods but they should be restricted and wrapped such that some parameters (e.g. domain name) are imposed by the wallet on the caller depending on the caller's authentication.
[TBD] Specify scope of RPC methods (some params should be forced to the authenticated domain value) and how to integrate them into web3 api.
### App keys exposure:
* `wallet.appkey.enable(options)`
This method allows to enable app keys (getting user permission to use and allow him to select the persona she would like to use).
[TBD] Could return the account public key from the HD path before `the app's custom subPath`. Hence from this app's root account, one could derive all non hardened childs public keys of the app's keys.
[TBD] where `options` is a javascript object containing the permissions requested for these app keys.
Options could also include a challenge to be signed by the app's root account (would serve as authentication of the users from the app's perspective). The signature should then be also returned.
Options should also include a parameter for the application to indicate which name should be used to compute the domain's HD path. That's required for applications that are loaded through ENS. They could be authenticated either through ENS or through DNS. These applications may like to use the DNS name even when they are resolved through ENS. (e.g. an application that just upgraded to ENS may like to continue using DNS paths to be retro-compatible for its former users).
Uses the persona selected by the user (not known nor controllable by application).
Uses the domain ens namehash (node) that was resolved to load window (not provided by application itself)
### Ethereum accounts methods:
* `appKey_eth_getPublicKey(hdSubPath) returns publicKey 64 bytes`:
`hdSubPath` string with BIP32 format, "index_i / index_(i+1) '", can use hardening
`publicKey` returns e.g. 0x80b994e25fb98f69518b1a03e59ddf4494a1a86cc66019131a732ff4a85108fbb86491e2bc423b2cdf6f1f0f4468ec73db0535a1528ca192d975116899289a4b
* `appKey_eth_getAddress(hdSubPath) returns address 20 bytes`:
`hdSubPath`: string with BIP32 format, "index_i / index_(i+1) '", can use hardening
`address` e.g. 0x9df77328a2515c6d529bae90edf3d501eaaa268e
* `appKey_eth_derivePublicKeyFromParent(parentPublicKey, hdSubPath) returns publicKey 64 bytes`
`hdSubPath`: string with BIP32 format, "index_i / index_(i+1) '", should not use hardening here.
* `appKey_eth_getAddressForPublicKey(publicKey) returns address 20 bytes`
`publicKey` 64 bytes
### Ethereum signing methods:
* `appKey_eth_signTransaction(fromAddress, tx)`
tx is ethereum-js tx object
* `appKey_eth_sign(fromAddress, message)`
* `appKey_eth_personalSign(fromAddress, message)`
* `appKey_eth_signTypedMessage(fromAddress, message)`
EIP712
### Ethereum broadcasting methods:
* `appKey_eth_broadcastTransaction(tx, signedTx)`
tx is ethereum-js tx object
### Other potential methods:
#### Other cryptocurrencies:
We defined for now Ethereum accounts and signing methods. However, one could do the same for other cryptocurrencies deriving accounts along their standards. This may open to some very interesting cross-blockchains application designs.
#### Other cryptographic methods:
Similarly, using entropy provided by the HD Path, one could think of other cryptographic methods such as encryption and also other curve types.
#### Storage:
The HD path for each application can also be used as a key to isolate databases for user's persistent data. We could introduce methods that allow to read and write in a database specific to the application.
Q [Benefit of this compared to using classical browser local storage?]
### API permissions and confirmations from users:
#### Initial permission request and full access afterwards:
Each wallet has freedom in the way they implement their permission system along with this EIP and this API. We tend to favor a design where the applications would request once and for all full access to the applications keys (for their domain) and that the user has to confirm this once. From then on, any account derivation or signing for those applications keys will not prompt a confirmation request on the wallet side.
However applications themselves are free to reproduce some confirmation at their own level if they would like the users to double check the transactions or signatures they are making at the application level. This will be of course dependent on trusting the application code.
#### Paranoia mode:
However, we would like to give users the option to monitor at any point applications keys and how applications user them. We therefore encourage wallets to introduce a `paranoia mode` that users can activate (for instance in the wallet advanced settings) to force confirmations request for all the applications keys actions.
## Rationale
<!--The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->
### Isolated paths but customisable
The proposed specifications permit to have isolation between personas and between applications. Each persona / application combination will yield a unique subtree that can be explored by the application using the structure it would like to use.
Personas are known only by the user and its wallet, application' UID based path is computable by everyone from the application's name. And then the application decides and communicates the final levels of the path.
Only the wallet and the user will know the full tree and where we are in the tree (depth, parents). Applications will have knowledge only of the subtree, starting after the persona.
### API not exposing private keys
Applications can derive accounts and request signing from them but they will not get access to the private keys of these accounts. So when the user closes her wallet entirely, the application can not continue signing for the user. This is of course in order to keep an user's ultimate control over its accounts.
If there is a strong demand, we could add a method that exposes the private keys for the application accounts but it would be an optional to request upon app keys initial setup.
We indeed think that writing applications that don't need to manipulate the user private keys is a better pattern. For instance, if one needs the user to sign data while being offline, one should for instance rather implement a delegation method to an external application's controlled account rather than storing the user private key on a server that stays online.
### Persona isolation accross applications for privacy
The persona path is set by the user-wallet interaction and known only by them. There is thus a strict isolation between 2 different persona subpaths as if they were generated by different mnemonics.
Instead of personas, an alternative proposal would be to make the `application UID based path` a subset of a user's ethereum main accounts)
Most wallets use the following derivation path for ethereum accounts:
`m/44'/60'/a'/0/n`
where a is a set of account number and n is the account index
We could use:
`m/44'/60'/a'/0/n / [Application UID based path] / [App controlled HD subPath]`
This way, we could use accounts as personas.
However it does not necessarily make sense to anchor an application to a single main account. Some applications may like to interact with several "main accounts" or allow the user to change the main account they are using to deposit while keeping the same signing `app keys` accounts. Some applications may even like to use non ethereum accounts.
Also this alternative specification HD path would not be BIP44 compliant but would be using this purpose field.
Also it may add complexity to restore a wallet and the used accounts, one should remember which account is associated with which application and application can not suggest you which account to use because they are not aware of this part of the path.
If we don't harden the level indexes after the main account index, we could however enumerate all app keys of an user given a list a applications. We would first enumerate over the main accounts (assuming the wallet uses an [account gap limit](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#Address_gap_limit)), then over the Applications list and then over the `Application controlled HD subPath` if it allows to do so and has an account gap limit.
For the persona specification this may not be possible, unless we impose some structure on the personas such as using a basic index.
### Hardened and non-hardened indexes: privacy and functionality
Hardening allows to increase privacy. If the extended public key of a parent level in the HD tree is known, public keys of its childs can not be computed if they are hardened. On the contrary if the child indexes are not hardened one can enumerate the child public keys and use that for the application design or to easily restore a wallet and it increases functionality.
For the first parts of the HD tree, we need isolation and privacy. Thus we use hardened indexes for the persona and application paths in case some extended public key leaks at some previous level of the tree, it would protect the sub trees (of course this has no impact if private keys leak).
For instance if we don't harden the application path, in case a persona public key is known and the application subpath does not use hardening either, one could get all `app keys` public keys for every application for this persona.
However the app can use non hardened indexes in their custom path part to be able to benefit from guessing child public keys from parent one (for instance for counterfactual state channel interaction accross 2 peers that would like to use new keys every time they counterfactually instantiate a new sub app).
### Alternatives for the HD derivation path
Our proposed specification follows [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) and [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki):
`m / purpose' / *`
It is of course not be BIP44 compliant which uses the following tree level structure:
`m / purpose' / coin_type' / account' / change / address_index`
One could think of alternative specifications deviating from BIP43 or even BIP32. Or on the contrary, one could try to become BIP44 compliant, although we do not really see the benefit of that for app keys and it would impose serious limitations on how to identify the applications using potentially the `coin_type` field.
### HD derivation path purpose field
If we agree on not using BIP44 but following BIP32 and BIP43, we need to settle on a purpose field. We can either use the 3 depth path proposed here (https://github.com/bitcoin/bips/pull/523) or try to rech agreement on a one depth path. A one depth path should however avoid collision. This can be achieves by either submitting a BIP or by maintening a list of BIP 43 purpose fields.
We did not find a list of BIP43 purpose code so here is what we could gather:
| code | Reference | Title |
|------|--------------------------------------------------------------------------|-------|
| 44 | [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) | Multi-Account Hierarchy for Deterministic Wallets |
| 45 | [BIP45](https://github.com/bitcoin/bips/blob/master/bip-0045.mediawiki) | Structure for Deterministic P2SH Multisignature Wallets|
| 48 | [SLIP48](https://github.com/satoshilabs/slips/issues/49) | Deterministic Key Hierarchy for Graphene-based Networks |
| 49 | [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) | Derivation scheme for P2WPKH-nested-in-P2SH based accounts |
| 80 | [BIP80](https://github.com/bitcoin/bips/blob/master/bip-0080.mediawiki) | Hierarchy for Non-Colored Voting Pool Deterministic Multisig Wallets |
| 84 | [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) | Derivation scheme for P2WPKH based accounts |
| 535348 | [Ledger app ssh](https://github.com/LedgerHQ/ledger-app-ssh-agent/blob/master/getPublicKey.py#L49) | |
| 80475047| [GPG/SSH Ledger](https://github.com/LedgerHQ/ledger-app-openpgp-card/blob/master/doc/developper/gpgcard3.0-addon.rst#deterministic-key-derivation)| |
| 1775 | EIP1775 | App Keys: application specific wallet accounts |
### Application's identification
#### Favoring a deterministic scheme for application uids
Quoting Vitalik in his post [Meta: we should value privacy more](https://ethereum-magicians.org/t/meta-we-should-value-privacy-more/2475), we indeed favor a deterministic scheme for applications specific accounts generation:
```
It would be nice to keep wallet software stateless, so users can easily export and import their keys between wallets; this implies using some deterministic scheme like privkey_for_dapp = hash(master_key + dapp_id). But then what is the dapp_id? How would that work for multi-contract dapps?
```
And we proposed to use the ENS domain hash, or node, as the dapp_id and to use a BIP32 structure instead to derive the private keys.
#### Alternative: using a centraly maintened index of application uids
[EIP1581: Non-wallet usage of keys derived from BIP32 trees](https://eips.ethereum.org/EIPS/eip-1581)
also discussed [here](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4) proposes a scheme that relies on a list of indexes where application should register (similar to SLIP44 list for instance).
We think our approach while also being more englobing benefits from not requiring a centrally maintained registry. In our approach every application has already a potential unique identifier assigned to it.
#### Shortening the Hash node
Our current approach uses identification through an ENS name converted to a hash node and sliced fully but one could potentially keep only the first 16 bytes of the node for instance and slice them similarly. This may increase the chance of app collision but we probably can reduce the lenght while retaining an injective mapping from strings to hashes.
#### Alternative application identification specification
For the application unique identifiers, an alternative specification could favor using an `ethereum author address` and including a signed message challenge for author for authentication.
It would also need to specify how to decompose this address.
The same reasoning as before would apply, if we use an `eth address` of 20 bytes, 160 bits
e.g. 0x9df77328a2515c6d529bae90edf3d501eaaa268e
```
x = x0 || x1 || x2 || x3 || x4 || x5
```
where `x0` to `x4` are 30 bits and `x5` is 10 bits.
or alternatively equal length
```
x = x0 || x1 || x2 || x3 || x4 || x5 || x6 || x7
```
where `x0` to `x7` are 20 bits.
Another alternative could be to use the plain website url and get rid of ens altogether but it would require another way to authenticate applications. See for instance [SLIP13](https://github.com/satoshilabs/slips/blob/master/slip-0013.md) for such a proposal.
### Application's authentication
For authentication we use DNS and ENS resolution, and browsing to a given url resolved. A few comments on this:
A few comments in case of ENS resolution:
* First connection requires the wallet to connect to ethereum mainnet, but once first resolution is done we could use some metadata paramater such as `author address` for a blockchain less authentication of the application (e.g. application server signs a challenge message with the author address resolved in the ENS metadata).
* The url the name resolves to through ENS can change without the user knowing and then a different application/website may be granted access to his app keys. But this means the ENS name owner address was copromised. This would be similar to using a signing challenge authentified by a known public key. If this known public key is compromised we have a similar problem.
* Homoglyph attacks are not a bigger problem for `app keys` than it is for ENS since it will not grant access to `app keys` from the real domain (they would be derived along a different path). However homoglyph applications may lure the user to send funds from her main account to an `app key` of a malicious homoglyphic domain.
Other metadata resolution through ENS that can be used alongside:
* `author address`: already mentionned above
* `contract address`: For app keys that would be designed to interact with a given ethereum contract (for instance app keys for a given token, if one desires to do so), other metadata fields could be used such as contract addresses.
* [TBD]
In relation to the SLIP13 proposal mentionned above, one could think of alternative specifications that would use some certificate for authentication similar to https.
### An Account gap limit standard for application controlled hd sub-path?
If applications don't enumerate through their hd sub-path structure, we won't be able to restore `app keys` accounts by enumeration. However it has benefits to give total freedom to applications over the way they create accounts and use their sub-path. Also, it may be safe to assume that the part of the restoring procedure will be carried by the application itself and not by the wallets. The application will need a way to remember what accounts were derived for each user.
### 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
<!--All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright.-->
From a wallet point of view, there does not seem to be incompatibities 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 ethereum addresses may want to reflect on if and how they would like to leverage the power offered by `app keys` to migrate to them and increase their user's privacy, security and potentially also user-flow.
## Test Cases
<!--Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.-->
[TBD]
Provide some examples of accounts derived from a given mnemonic, persona, application and application's custom subpath.
## Implementation
<!--The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.-->
[WIP]
[See here for an early implementation of the HD methods](https://github.com/Bunjin/appKeys)
## 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](https://eips.ethereum.org/EIPS/eip-1581)
* 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
* [BIP32: Hierarchical Deterministic Wallets:](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
* [BIP39: Mnemonic code for generating deterministic keys:](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
* [BIP43: Purpose Field for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)
* [BIP44: Multi-Account Hierarchy for Deterministic Wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#Address_gap_limit)
* [SLIP44: Registered coin types for BIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)
* [Is there a comprehensive list of registered BIP43 purposes?](https://bitcoin.stackexchange.com/questions/60470/is-there-a-comprehensive-list-of-registered-bip43-purposes)
#### Derivation path for eth
* [Issue 84](https://github.com/ethereum/EIPs/issues/84)
* [Issue 85](https://github.com/ethereum/EIPs/issues/85)
* [EIP600 Ethereum purpose allocation for Deterministic Wallets](https://eips.ethereum.org/EIPS/eip-600)
* [EIP601 Ethereum hierarchy for deterministic wallets](https://eips.ethereum.org/EIPS/eip-601)
#### Accounts Privacy
### ENS
* [EIP137: Ethereum Domain Name Service - specification](https://eips.ethereum.org/EIPS/eip-137)
* [EIP165: Standard Interface Detection](https://eips.ethereum.org/EIPS/eip-165)
* [EIP634: Storage of text record in ENS](https://eips.ethereum.org/EIPS/eip-634)
* [ENS docs about namehash:](http://docs.ens.domains/en/latest/implementers.html#namehash)
### Previous proposals and discussions related to app keys
* [Meta: we should value privacy more](https://ethereum-magicians.org/t/meta-we-should-value-privacy-more/2475)
* [EIP1102: Opt-in account exposure](https://eips.ethereum.org/EIPS/eip-1102)
* [EIP1581: Non-wallet usage of keys derived from BIP-32 trees](https://eips.ethereum.org/EIPS/eip-1581)
* [EIP1581: discussion](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4)
* [SLIP13: Authentication using deterministic hierarchy](https://github.com/satoshilabs/slips/blob/master/slip-0013.md)
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).