EIP 1775: App Keys, application specific wallet accounts Source

AuthorVincent Eli, Dan Finlay
TypeStandards Track
Requires 137

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.


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 Hierarchical 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.


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. EIP1102 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.



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]


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.

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):

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.


We allow the user to use different personas in combination to her mnemonic to potentially 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 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

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, reproduced below for convenience 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.
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 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 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 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'




converted to binary (256 bits)


256 bits:

converted to less than or equal to 31 bits indexes:

8 * 31 bits + 1 * 8 bits


and converted to uints


  • Second approach favors an homogeneous decomposition:

Equal length 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

6033 644d 673b 47b3 bea0 4e79 bbe0 6d78 ce76 b8be 2fb8 704f 9c2a 80fd 139c 81d3

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 written 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



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 children 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.


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.


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 across 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), 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 children 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 across 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 and BIP43:

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 Multi-Account Hierarchy for Deterministic Wallets
45 BIP45 Structure for Deterministic P2SH Multisignature Wallets
48 SLIP48 Deterministic Key Hierarchy for Graphene-based Networks
49 BIP49 Derivation scheme for P2WPKH-nested-in-P2SH based accounts
80 BIP80 Hierarchy for Non-Colored Voting Pool Deterministic Multisig Wallets
84 BIP84 Derivation scheme for P2WPKH based accounts
535348 Ledger app ssh  
80475047 GPG/SSH Ledger  
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, 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 also discussed here 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 length 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 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 parameter 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 mentioned 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 mentioned 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

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


Provide some examples of accounts derived from a given mnemonic, persona, application and application’s custom subpath.


[WIP] See here for an early implementation of the HD methods

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…


MetaMask team, Christian Lundkvist, Counterfactual team, Liam Horne, Erik Bryn, Richard Moore, Jeff Coleman.


HD and mnemonics


Derivation path for eth

Accounts Privacy


Copyright and related rights waived via CC0.