Abstract
This ERC proposes a standard for wallets to generate and manage exposed application-specific key pairs, building upon the concepts introduced in ERC-1775 and complementing ERC-7716. It defines exposed keys that allow free signing by the current site. This approach enhances flexibility in managing permissions for decentralized applications (dApps) while maintaining a balance with security considerations.
Motivation
As the ecosystem of dApps grows, there's an increasing need for more granular and flexible key management. This ERC simplifies the ideas presented in ERC-1775 and ERC-7715 by providing a standard for exposed app keys that a wallet can use to manage permissions for a dApp:
Exposed Keys (Freely Signable): Allow dApps to sign transactions without repeated user intervention, enabling smoother user experiences for certain operations.
This approach allows for improved user convenience in scenarios where frequent signing is required, giving users and dApps more control over how permissions and identities are handled across different applications.
Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Wallet Interface
Wallets MUST implement the following method:
wallet_getExposedAppKey
This method generates or retrieves an exposed app-specific key for the current dApp.
Parameters
options: An optional object that can include:type: The type of key to generate. Currently supports'ethereum-secp256k1'. Additional types may be supported in future extensions of this standard.nonce: An optional number that allows the site to generate multiple distinct keys. If not provided, it defaults to 0.
Returns
- A Promise that resolves to an object containing:
address: The Ethereum address derived from the exposed app key.publicKey: The public key of the exposed app key.privateKey: The private key of the exposed app key.type: The type of key that was generated.nonce: The nonce used to generate this key.
Exposed App Key Generation Algorithm
The exposed app key generation algorithm is based on a simplified version of BIP-44, without ENS complications. This algorithm ensures that each application receives a unique, deterministic key pair that can be easily regenerated by any compliant wallet.
-
Derive the app-specific path:
- Use the BIP-44 purpose field
44' - Use coin type
60'for Ethereum - Use
0'for account index - Use the first 4 bytes of keccak256 hash of the app's origin (domain) for change level
- Use the provided
nonce(or 0 if not provided) for address index
- Use the BIP-44 purpose field
-
Generate the private key:
- Derive the private key using the app-specific path from the wallet's master seed
-
Compute the public key and address:
- Derive the public key from the private key
- Compute the Ethereum address from the public key
Here's a JavaScript representation of the algorithm using the scure-bip39 library:
import * as bip39 from '@metamask/scure-bip39';
import { wordlist } from '@metamask/scure-bip39/wordlists/english';
import { HDKey } from '@scure/bip32';
import { keccak256 } from 'ethereum-cryptography/keccak';
import { publicToAddress, privateToPublic } from 'ethereum-cryptography/secp256k1';
async function getExposedAppKey(origin, nonce = 0) {
// Generate or retrieve the wallet's master seed
const mnemonic = bip39.generateMnemonic(wordlist);
const seed = await bip39.mnemonicToSeed(mnemonic);
// Derive the app-specific path
const purpose = 44;
const coinType = 60; // Ethereum
const account = 0;
const change = parseInt(keccak256(Buffer.from(origin)).slice(0, 4).toString('hex'), 16);
const addressIndex = nonce;
const path = `m/${purpose}'/${coinType}'/${account}'/${change}/${addressIndex}`;
// Generate the private key
const hdkey = HDKey.fromMasterSeed(seed);
const derivedKey = hdkey.derive(path);
const privateKey = derivedKey.privateKey;
// Compute the public key and address
const publicKey = privateToPublic(privateKey);
const address = '0x' + publicToAddress(publicKey).toString('hex');
return {
address,
publicKey: publicKey.toString('hex'),
privateKey: privateKey.toString('hex'),
type: 'ethereum-secp256k1',
nonce
};
}
// Example usage
getExposedAppKey('example.com', 0).then(console.log);Rationale
Security Considerations
This ERC passes the entire private key to the dApp, which can be used to sign transactions. This is a departure from the current best practice of using a signing method that does not reveal the private key to the dApp.
An alternative and slightly more secure approach is to use a signing method that does not reveal the private key to the dApp. This would improve revokability, but would increase friction especially for mobile apps that don't have a continuous connection to the user's wallet. I am partly drafting this ERC to establish an initial minimal standard which we can iterate on.
Conclusion
This ERC proposes a standardized method for wallets to generate and manage app-specific keys, providing a secure and consistent approach to permission management in decentralized applications. By implementing this standard, wallets can offer enhanced privacy and security for users while enabling more seamless interactions between dApps and user accounts.
The proposed wallet_getAppKey method allows for the creation of unique, deterministic keys for each application, reducing the risk of cross-app tracking and improving overall user privacy. This approach also facilitates easier permission management and potential future upgrades to more advanced account structures.
As the Ethereum ecosystem continues to evolve, standardized approaches to key management and permissions become increasingly important. This ERC aims to contribute to the ongoing development of user-friendly and secure wallet interfaces, fostering innovation in decentralized applications while maintaining strong security practices.
By adopting this standard, wallets and dApps can work together more effectively, providing users with a more streamlined and secure experience in the Web3 environment. As the community continues to refine and expand upon these concepts, we anticipate further improvements in user experience, security, and interoperability across the Ethereum ecosystem.
