ethereum/EIPs-1078 Universal login / signup using ENS subdomains
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1078.md
eip | title | author | discussions-to | status | type | category | created | requires |
---|---|---|---|---|---|---|---|---|
1078
|
Universal login / signup using ENS subdomains
|
Alex Van de Sande <avsa@ethereum.org>
|
Draft
|
Standards Track
|
ERC
|
2018-05-04
|
1077, 725, 681, 191
|
这个EIP是与EIP-1077结合使用的
Abstract
This presents a method to replace the usual signup/login design pattern with a minimal ethereum native scheme, that doesn’t require passwords, backing up private keys nor typing seed phrases. From the user point of view it will be very similar to patterns they’re already used to with second factor authentication (without relying in a central server), but for dapp developers it requires a new way to think about ethereum transactions.
提出了一种能够代替传统的注册/登录设计模式的新方法,不需要密码,不用备份密钥或seed phrases。从使用者的角度,这个方法与他们已经使用过的第二种因素授权的模式相似(不用依靠中心服务器),但是对于dapp开发者来说,它需要一种新的方法去思考以太坊的交易
Simple Summary
The unique identifier of the user is a contract which implements both Identity and the Executable Signed Messages ERCs. The user should not need provide this address directly, only a ens name pointing to it. These types of contracts are indirectly controlled by private keys that can sign messages indicating intents, which are then deployed to the contract by a third party (or a decentralized network of deployers).
这种用户独特的识别是即实现了identity又实现了Executable Signed Messages这两个ERCs的一种contract。使用者不用再直接地提供他们的address,只用使用他们的ENS就行。这种类型的合约并不直接被用来签名能够显示意图的信息的私钥所控制,信息又第三方部署到合约上。
In this context, therefore, a device "logging into" an app using an identity, means that the device will generate a private key locally and then request an authorization to add that key as one of the signers of that identity, with a given set of permissions. Since that private key is only used for signing messages, it is not required to hold ether, tokens or assets, and if lost, it can be simply be replaced by a new one – the user's funds are kept on the identity contract.
一个设备使用identity(即identity contract)来登录设备,说明设备将会在本地生成一个私钥然后调用一个授权去添加该key使其成为identity中signers的一员。这个私钥仅仅用来加密messages,不拥有ether、token或assert,所以不怕丢,丢了就重新再生成一个。用户的资金都存放在identity contract中。
In this context, ethereum accounts are used in a manner more similar to auth tokens, rather than unique keys.
The login process is as follows:
登录的过程如下所示
1) Request a name from the user
The first step of the process is to request from the user the ENS name that points to their identity. If the user doesn’t have a login set up, the app should–if they have an integrated identity manager–provide an option to provide a subdomain or a name they own.
给identity contract提供一个ENS name
UX Note: there are many ways to provide this interface, the app can ask if they want to signup/login before hand or simply directly ask them to type the name. Note that since it’s trivial to verify if a username exists, your app should adapt to it gracefully and not require the user to type their name twice. If they ask to signup and provide a name that exists then ask them if they want to login using that name, or similarly if they ask to connect to an existing name but type a non-existent name show them a nice alert and ask them if they want to create that name now. Don’t force them to type the same name twice in two different fields.
2.a) Create a new identity
当app的用户没有identity时,创建一个
If the user doesn’t have an identity, the app should provide the option to create one for them. Each app must have one or more domains they control which they can create immediate subdomains on demand. The app therefore will make these actions on the background:
- Generate a private key which it will keep saved locally on the device or browser, the safest way possible.首先创建一个私钥并存储在设备(手机)或浏览器中
- Create (or set up) an identity contract which supports both ERC720 and ERC1077创建一个identity contract
- Register the private key created on step 1 as the only admin key of the contract (the app must not add any app-controlled key, except as recovery option - see 5) 登记在第一步中生成的私钥为合约其唯一的管理key
- Register the requested subdomain and transfer its ownership to the contract (while the app controls the main domain and may keep the option to reassign them at will, the ownership of the subdomain itself should belong to the identity, therefore allowing them to transfer it)登录ENS域名并将其作为合约的名字
- (Optionally) Register a recovery method on the contract, which allows the user to regain access to the contract in case the main key is lost.在合约上提出一个recovery方法,使得用户能够重新进入该合约,以免主钥丢失
All those steps can be designed to be set up in a single ethereum transaction. Since this step is not free, the app reserves the right to charge for registering users, or require the user to be verified in a sybil resistant manner of the app’s choosing (captcha, device ID registration, proof of work, etc)
The user shouldn’t be forced to wait for transaction confirmation times. Instead, have an indicator somewhere on the app the shows the progress and then allow the user to interact with your app normally. It’s unlikely that they’ll need the identity in the first few minutes and if something goes wrong (username gets registered at the same time), you can then ask the user for an action.
Implementation note: in order to save gas, some of these steps can be done in advance. The app can automatically deploy a small number of contracts when the gas price is low, and set up all their main variables to be 0xFFFFFF...FFFFF. These should be considered ‘vacant’ and when the user registers one, they will get a gas discount for freeing up space on the chain. This has the added benefit of allowing the user a choice in contract address/icon.
2.b) Connect to an existing identity
当用户有identity时,如何连接(其实就是在另一个app中使用时)
If the user wants to connect with an existing identity, then the first thing the app needs to understand is what level of privilege it’s going to ask for:
首先要了解用户请求的权限的等级
Manager the higher level, allows the key to initiate or sign transactions that change the identity itself, like adding or removing keys. An app should only require this level if it integrates an identity manager. Depending on how the identity is set up, it might require signature from more keys before these transactions can be deployed.
可以改变identity本身,如添加或删除key。只有当用户是identity管理员时才给气这个权限
Action this level allows the key to initiate or sign transactions on address other than itself. It can move funds, ether, assets etc. An app should only require this level of privilege if it’s a general purpose wallet or browser for sending ethereum transactions. Depending on how the identity is set up, it might require signature from more keys before these transactions can be deployed.
Encryption the lower level has no right to initiate any transactions, but it can be used to represent the user in specific instances or off-chain signed messages. It’s the ideal level of privilege for games, chat or social media apps, as they can be used to sign moves, send messages, etc. If a game requires actual funds (say, to start a game with funds in stake) then it should still use the encryption level, and then require the main wallet/browser of the user to sign messages using the ethereum URI standard.
Once the desired level is known, the app must take these steps:
- Generate a private key which it will keep saved locally on the device or browser, the safest way possible.首先创建一个私钥并存储在设备(手机)或浏览器中
- Query ens to figure the existing address of the identity通过ENS去查看identity的address
- Generate the bytecode for a transaction calling the function
addKey(PUBLICKEY,LEVEL)
调用addKey
函数 - Broadcast a transaction request on a whisper channel or some other decentralized network of peers. Details on this step require further discussions广播该transaction
- If web3 is available then attempt calling web3.eth.sendTransaction. This can be automatic or prompted by user action.
- Attempt calling a URI if the app supports URL format for transaction requests EIP then attempt calling this. This can be automatic or prompted by user action.
- Show a QR code: with an EIP681 formatted URL. That QR code can be clickable to attempt to retry the other options, but it should be done last: if step 1 works, the user should receive a notification on their compatible device and won't need to use the QR code.
Here's an example of a EIP681 compatible address to add a public key generated locally in the app:
ethereum:bob.example.eth?function=addKey(address='0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',uint=1)
If adding the new key requires multiple signatures, or if the app receiving that request exclusiveky deals with executeable signed messages and has no ether on itself, then it should follow the steps in the next section on how to request transactions.
如果添加新key需要多重签名,或者如果接收到这个请求的app处理可执行的签名消息,并且本身没有ether,那么就跟着下面的步骤来请求交易。
As before, the user shouldn’t be forced to wait for transaction confirmation times. Instead, have an indicator somewhere on the app the shows the progress and then allow the user to interact with your app normally.
在这之前要意识到不应该强迫用户等待交易的认证,相反,在app中应该在某些地方又显示器来展示进程并允许用户与app正常交互
3) Request transactions
After step 2, the end result should be that your app should have the identity address of the user, their main ens name and a private key, whose public account is listed on the identity as one of their keys, with roles being either manager, action or encryption. Now it can start using that information to sign and execute transactions.
在上面的步骤后,你的app应该拥有了用户的identity contract的合约地址,它的ENS名字以及私钥。user的公共账号列举在identity中作为其中的一个key。然后现在就可以使用上面的信息来进行签名以及执行交易了。
Not all transactions need to be on chain, actually most common uses of signed messages should be off chain. If you have a chat app, for instance, you can use the local key for signing messages and sending it to the other parties, and they can just query the identity contract to see if that key actually comes from the user. If you have a game with funds at stake, only the first transaction moving funds and setting up the initial game needs to be executed by the identity: at each turn the players can sign a hash of the current state of the board and at the end, the last two plays can be used to determine the winner. Notice that keys can be revoked at any time, so your app should take that in consideration, for instance saving all keys at the start of the game. Keys that only need this lower level of privilege, should be set at level 4 (encryption).
不是所有的交易都需要写到链上(比如那些查询数据的交易),事实上很多的签名信息都是在链下的。比如如果你有聊天软件。你可以使用当地的key去签名信息并发送它到别的parties,然后parties就会到identity contract处去查询这个key是不是真的来自这个user(即这个identity contract,因为交易的from中写的是contract的地址,就是contract去查它的keys中有没有进行签名的这个key)。注意:key是能够被注销的。
Once you decided you actually need an on-chain transaction, follow these steps:
- Figure out the TO, FROM, VALUE and DATA. These are the basics of any ethereum transaction.
from
is the compatible contract you want the transaction to be deployed from. - Check the privilege level you need: if the
to
andfrom
fields are the same contract, ie, if the transaction requires the identity to act upon itself (for instance, when adding or removing a key) then you need level 1 (management), otherwise it's 2 (action). Verify if the key your app owns correspond to the required level.如果from和to都是同一个contract,比如交易让identity做添加或删除key等影响自己的操作,那就需要management level。否则就是action level的。并且核查你app拥有的key 的level是不是与你需要的一致。 - Verify how many keys are required by calling
requiredSignatures(uint level)
on the target contract查看需要多少个keys - Figure out gasLimit: Estimate the gas cost of the desired transaction, and add a margin (recommended: add 100k gas)设置gasLimit
- Figure out gasToken and gasPrice: Check the current gas price considering network congestions and the market price of the token the user is going to pay with. Leave gasToken as 0 for ether. Leave gasPrice as 0 if you are deploying it yourself and subsidizing the costs elsewhere.
- Sign an executable signed transaction by following that standard.
After having all the signed executable message, we need to deploy it to the chain. If the transaction only requires a single signature, then the app provider can deploy it themselves. 如果交易只需要一个签名,那么app就可以自己部署该交易Send the transaction to the from
address and attempt to call the function executeSigned
, using the parameters and signature you just collected.就是把交易发送到from地址然后调用函数executeSigned
If the transaction need to collect more signatures or the app doesn't have a deployable server, the app should follow these steps:
如果交易不仅仅只需要一个签名或者app没有部署服务器,那么就:
- Broadcast the transaction on a whisper channel or some other decentralized network of peers. Details on this step require further discussions广播该交易
- If web3 is available then attempt calling web3.eth.personal_sign. This can be automatic or prompted by user action.
- Show a QR code: with the signed transaction and the new data to be signed. That QR code can be clickable to attempt to retry the other options, but it should be done last: if step 1 works, the user should receive a notification on their compatible device and won't need to use the QR code.
The goal is to keep broadcasting signatures via whisper until a node that is willing to deploy them is able to collect all messages.
Once you've followed the above steps, watch the transaction pool to any transaction to that address and then take the user to your app. Once you seen the desired transaction, you can stop showing the QRcode and proceed with the app, while keeping some indication that the transaction is in progress. Subscribe to the event ExecutedSigned
of the desired contract: once you see the transaction with the nonce, you can call it a success. If you see a different transaction with the same or higher nonce (or timestamp) then you consider the transaction permanently failed and restart the process.
Implementation
No working examples of this implementation exists, but many developers have expressed interest in adopting it. This section will be edited in the future to reflect that.
Conclusion and future improvements
This scheme would allow much more lighter apps, that don't require to hold ether, and can keep unlocked private keys on the device to be able to send messages and play games without requesting user prompt every time. More work is needed to standardize common decentralized messaging protocols as well as open source tools for deployment nodes, in order to create a decentralized and reliable layer for message deployment.
将会允许更多轻量级的app出现,能够将私钥存储在设备上,并且能够发送消息与玩游戏而不需要每次都请求用户的prompt。