mirror of https://github.com/status-im/EIPs.git
302 lines
10 KiB
Markdown
302 lines
10 KiB
Markdown
|
---
|
||
|
eip: 725
|
||
|
title: Proxy Identity
|
||
|
author: Fabian Vogelsteller (@frozeman)
|
||
|
discussions-to: https://github.com/ethereum/EIPs/issues/725
|
||
|
status: Draft
|
||
|
type: Standards Track
|
||
|
category: ERC
|
||
|
created: 2017-10-02
|
||
|
---
|
||
|
|
||
|
## Simple Summary
|
||
|
Proxy contract for key management and execution, to establish a Blockchain identity.
|
||
|
|
||
|
## Abstract
|
||
|
The following describes standard functions for a unique identity for humans, groups, objects and machines.
|
||
|
This identity can hold keys to sign actions (transactions, documents, logins, access, etc), and claims, which are attested from third parties (issuers) and self attested ([#ERC735](https://github.com/ethereum/EIPs/issues/735)), as well as a proxy function to act directly on the blockchain.
|
||
|
|
||
|
## Motivation
|
||
|
This standardised identity interface will allow Dapps, smart contracts and thirdparties to check the validity of a person, organisation, object or machine through 2 steps as described in the function XXX. Trust is here transfered to the issuers of claims.
|
||
|
|
||
|
The most important functions to verify an identity are: `XXX`
|
||
|
|
||
|
The most important functions to manage an identity are: `XXX`
|
||
|
|
||
|
|
||
|
## Definitions
|
||
|
|
||
|
- `keys`: Keys are public keys from either external accounts, or contract addresses.
|
||
|
- `claim issuer`: is another smart contract or external account, which issues claims about this identity. The claim issuer can be an identity contract itself.
|
||
|
- `claim`: For details about claims see [#ERC735](https://github.com/ethereum/EIPs/issues/735)
|
||
|
|
||
|
|
||
|
|
||
|
## Specification
|
||
|
|
||
|
|
||
|
### Key Management
|
||
|
|
||
|
Keys are cryptographic public keys, or contract addresses associated with this identity.
|
||
|
The structure should be as follows:
|
||
|
|
||
|
- `key`: A public key owned by this identity
|
||
|
- `purpose`: `uint256[]` Array of the key types, like 1 = MANAGEMENT, 2 = ACTION, 3 = CLAIM, 4 = ENCRYPTION
|
||
|
- `keyType`: The type of key used, which would be a `uint256` for different key types. e.g. 1 = ECDSA, 2 = RSA, etc.
|
||
|
- `key`: `bytes32` The public key. // for non-hex and long keys, its the Keccak256 hash of the key
|
||
|
|
||
|
|
||
|
```js
|
||
|
struct Key {
|
||
|
uint256[] purposes;
|
||
|
uint256 keyType;
|
||
|
bytes32 key;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
#### getKey
|
||
|
|
||
|
Returns the full key data, if present in the identity.
|
||
|
|
||
|
``` js
|
||
|
function getKey(bytes32 _key) constant returns(uint256[] purposes, uint256 keyType, bytes32 key);
|
||
|
```
|
||
|
|
||
|
#### keyHasPurpose
|
||
|
|
||
|
Returns the `TRUE` if a key has is present and has the given purpose. If key is not present it returns `FALSE`.
|
||
|
|
||
|
``` js
|
||
|
function keyHasPurpose(bytes32 _key, uint256 purpose) constant returns(bool exists);
|
||
|
```
|
||
|
|
||
|
|
||
|
#### getKeysByPurpose
|
||
|
|
||
|
Returns an array of public key bytes32 hold by this identity.
|
||
|
|
||
|
``` js
|
||
|
function getKeysByPurpose(uint256 _purpose) constant returns(bytes32[] keys);
|
||
|
```
|
||
|
|
||
|
|
||
|
#### addKey
|
||
|
|
||
|
Adds a `_key` to the identity. The `_purpose` specifies the purpose of key. Initially we propose four purposes:
|
||
|
|
||
|
- `1`: MANAGEMENT keys, which can manage the identity
|
||
|
- `2`: ACTION keys, which perform actions in this identities name (signing, logins, transactions, etc.)
|
||
|
- `3`: CLAIM signer keys, used to sign claims on other identities which need to be revokable.
|
||
|
- `4`: ENCRYPTION keys, used to encrypt data e.g. hold in claims.
|
||
|
|
||
|
MUST only be done by keys of purpose `1`, or the identity itself. If its the identity itself, the approval process will determine its approval.
|
||
|
|
||
|
**Triggers Event:** [KeyAdded](#keyadded)
|
||
|
|
||
|
``` js
|
||
|
function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) returns (bool success)
|
||
|
```
|
||
|
|
||
|
|
||
|
#### removeKey
|
||
|
|
||
|
Removes `_key` from the identity.
|
||
|
|
||
|
MUST only be done by keys of purpose `1`, or the identity itself. If its the identity itself, the approval process will determine its approval.
|
||
|
|
||
|
**Triggers Event:** [KeyRemoved](#keyremoved)
|
||
|
|
||
|
``` js
|
||
|
function removeKey(bytes32 _key, uint256 _purpose) returns (bool success)
|
||
|
```
|
||
|
|
||
|
|
||
|
--------------------------------------------------------
|
||
|
|
||
|
### Identity usage
|
||
|
|
||
|
|
||
|
#### execute
|
||
|
|
||
|
Executes an action on other contracts, or itself, or a transfer of ether.
|
||
|
SHOULD require `approve` to be called with one or more keys of purpose `1` or `2` to approve this execution.
|
||
|
|
||
|
Execute COULD be used as the only accessors for `addKey`, `removeKey` and `replaceKey` and `removeClaim`.
|
||
|
|
||
|
**Returns `executionId`:** SHOULD be send to the `approve` function, to approve or reject this execution.
|
||
|
|
||
|
**Triggers Event:** [ExecutionRequested](#executionrequested)
|
||
|
**Triggers on direct execution Event:** [Executed](#executed)
|
||
|
|
||
|
``` js
|
||
|
function execute(address _to, uint256 _value, bytes _data) returns (uint256 executionId)
|
||
|
```
|
||
|
|
||
|
|
||
|
#### approve
|
||
|
|
||
|
Approves an execution or claim addition.
|
||
|
This SHOULD require `n` of `m` approvals of keys purpose `1`, if the `_to` of the execution is the identity contract itself, to successfull approve an execution.
|
||
|
And COULD require `n` of `m` approvals of keys purpose `2`, if the `_to` of the execution is another contract, to successfull approve an execution.
|
||
|
|
||
|
**Triggers Event:** [Approved](#approved)
|
||
|
**Triggers on successfull execution Event:** [Executed](#executed)
|
||
|
**Triggers on successfull claim addition Event:** [ClaimAdded](#claimadded)
|
||
|
|
||
|
``` js
|
||
|
function approve(uint256 _id, bool _approve) returns (bool success)
|
||
|
```
|
||
|
|
||
|
|
||
|
--------------------------------------------------------
|
||
|
|
||
|
|
||
|
### Identity verification
|
||
|
|
||
|
Requires: [ERC 735](https://github.com/ethereum/EIPs/issues/735)
|
||
|
|
||
|
##### The following changes to [ERC 735](https://github.com/ethereum/EIPs/issues/735) are REQUIRED:
|
||
|
|
||
|
#### addClaim
|
||
|
|
||
|
This SHOULD create a pending claim, which SHOULD to be approved or rejected by `n` of `m` `approve` calls from keys of purpose `1`.
|
||
|
|
||
|
Only Events:
|
||
|
**Triggers if the claim is new Event and approval process exists:** [ClaimRequested](#claimrequested)
|
||
|
**Triggers if the claim index existed Event:** [ClaimChanged](https://github.com/ethereum/EIPs/issues/735)
|
||
|
|
||
|
|
||
|
#### removeClaim
|
||
|
|
||
|
MUST only be done by the `issuer` of the claim, or keys of purpose `1`, or the identity itself. If its the identity itself, the approval process will determine its approval.
|
||
|
|
||
|
|
||
|
--------------------------------------------------------
|
||
|
|
||
|
|
||
|
### Events
|
||
|
|
||
|
|
||
|
#### KeyAdded
|
||
|
|
||
|
MUST be triggered when `addKey` was successfully called.
|
||
|
|
||
|
``` js
|
||
|
event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
|
||
|
```
|
||
|
|
||
|
|
||
|
#### KeyRemoved
|
||
|
|
||
|
MUST be triggered when `removeKey` was successfully called.
|
||
|
|
||
|
``` js
|
||
|
event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
#### ExecutionRequested
|
||
|
|
||
|
MUST be triggered when `execute` was successfully called.
|
||
|
|
||
|
``` js
|
||
|
event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)
|
||
|
```
|
||
|
|
||
|
|
||
|
#### Executed
|
||
|
|
||
|
MUST be triggered when `approve` was called and the execution was successfully approved.
|
||
|
|
||
|
``` js
|
||
|
event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)
|
||
|
```
|
||
|
|
||
|
|
||
|
#### Approved
|
||
|
|
||
|
MUST be triggered when `approve` was successfully called.
|
||
|
|
||
|
``` js
|
||
|
event Approved(uint256 indexed executionId, bool approved)
|
||
|
```
|
||
|
|
||
|
##### The following changes to [ERC 735](https://github.com/ethereum/EIPs/issues/735) are REQUIRED:
|
||
|
|
||
|
#### ClaimRequested
|
||
|
|
||
|
MUST be triggered when `addClaim` was successfully called.
|
||
|
|
||
|
|
||
|
#### ClaimAdded
|
||
|
|
||
|
MUST be triggered when `approve` was called and the claim was successfully added.
|
||
|
|
||
|
|
||
|
## Constraints
|
||
|
|
||
|
- A claim can only be one type per type per issuer.
|
||
|
|
||
|
|
||
|
|
||
|
## Rationale
|
||
|
This specification was chosen to allow most flexibility and experimention around identity. By having each identity in a separate contract it allows for cross idenity compatibility, but at the same time extra and altered functionality for new use cases.
|
||
|
|
||
|
The main critic of this standard is the verification where each identity that issues a claim, also should have a separate CLAIM signing key attached. While [#ERC780](https://github.com/ethereum/EIPs/issues/780) uses a standardised registry to assign claims to addresses.
|
||
|
Both systems could work in conjunction and should be explored.
|
||
|
While also off-chain claims using DID verifiable claims and merkle tries can be added as claims and should be explored.
|
||
|
|
||
|
The rationale of this standard is to function as an open and veryf flexible container for idenity.
|
||
|
|
||
|
|
||
|
## Implementation
|
||
|
|
||
|
- [DID resolver specification](https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-spring2018/blob/master/topics-and-advance-readings/DID-Method-erc725.md)
|
||
|
- [Implementation by mirceapasoi](https://github.com/mirceapasoi/erc725-735)
|
||
|
- [Implementation by Nick Poulden](https://github.com/OriginProtocol/identity-playground), interface at: https://erc725.originprotocol.com/
|
||
|
|
||
|
|
||
|
### Solidity Interface
|
||
|
```js
|
||
|
pragma solidity ^0.4.18;
|
||
|
|
||
|
contract ERC725 {
|
||
|
|
||
|
uint256 constant MANAGEMENT_KEY = 1;
|
||
|
uint256 constant ACTION_KEY = 2;
|
||
|
uint256 constant CLAIM_SIGNER_KEY = 3;
|
||
|
uint256 constant ENCRYPTION_KEY = 4;
|
||
|
|
||
|
event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
|
||
|
event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
|
||
|
event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
|
||
|
event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
|
||
|
event Approved(uint256 indexed executionId, bool approved);
|
||
|
|
||
|
struct Key {
|
||
|
uint256 purpose; //e.g., MANAGEMENT_KEY = 1, ACTION_KEY = 2, etc.
|
||
|
uint256 keyType; // e.g. 1 = ECDSA, 2 = RSA, etc.
|
||
|
bytes32 key;
|
||
|
}
|
||
|
|
||
|
function getKey(bytes32 _key) public constant returns(uint256[] purposes, uint256 keyType, bytes32 key);
|
||
|
function keyHasPurpose(bytes32 _key, uint256 purpose) constant returns(bool exists);
|
||
|
function getKeysByPurpose(uint256 _purpose) public constant returns(bytes32[] keys);
|
||
|
function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) public returns (bool success);
|
||
|
function execute(address _to, uint256 _value, bytes _data) public returns (uint256 executionId);
|
||
|
function approve(uint256 _id, bool _approve) public returns (bool success);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Additional References
|
||
|
|
||
|
- [Slides of the ERC Identity presentation](https://www.slideshare.net/FabianVogelsteller/erc-725-identity)
|
||
|
- [In-contract claim VS claim registry](https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract)
|
||
|
- [Identity related reports](http://www.weboftrust.info/specs.html)
|
||
|
- [W3C Verifiable Claims Use Cases](https://w3c.github.io/vc-use-cases/)
|
||
|
- [Decentralised Identity Foundation](http://identity.foundation)
|
||
|
- [Sovrin Foundation Self Sovereign Identity](https://sovrin.org/wp-content/uploads/2017/06/The-Inevitable-Rise-of-Self-Sovereign-Identity.pdf)
|
||
|
|
||
|
## Copyright
|
||
|
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
|