10 KiB
eip | title | author | discussions-to | status | type | category | created |
---|---|---|---|---|---|---|---|
725 | Proxy Identity | Fabian Vogelsteller (@frozeman) | https://github.com/ethereum/EIPs/issues/725 | Draft | Standards Track | ERC | 2017-10-02 |
Simple Summary
A 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), as well as a proxy function, to act directly on the blockchain.
Motivation
This standardized identity interface will allow Dapps, smart contracts and third parties to check the validity of a person, organization, object or machine through 2 steps as described in the function XXX. Trust is here transferred 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 contracts' 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
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 identitypurpose
:uint256
The key purpose. e.g., 1 = MANAGEMENT, 2 = ACTION, 3 = CLAIM, 4 = ENCRYPTIONkeyType
: The type of key used, which would be auint256
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
struct Key {
uint256 purpose;
uint256 keyType;
bytes32 key;
}
getKey
Returns the full key data, if present in the identity.
function getKey(bytes32 _key) constant returns(uint256 purpose, uint256 keyType, bytes32 key);
keyHasPurpose
Returns TRUE
if a key is present and has the given purpose. If the key is not present it returns FALSE
.
function keyHasPurpose(bytes32 _key, uint256 purpose) constant returns(bool exists);
getKeysByPurpose
Returns an array of public key bytes32 held by this identity.
function getKeysByPurpose(uint256 _purpose) constant returns(bytes32[] keys);
addKey
Adds a _key
to the identity. The _purpose
specifies the purpose of the key. Initially, we propose four purposes:
1
: MANAGEMENT keys, which can manage the identity2
: ACTION keys, which perform actions in this identity's name (signing, logins, transactions, etc.)3
: CLAIM signer keys, used to sign claims on other identities which need to be revocable.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 it's the identity itself, the approval process will determine its approval.
Triggers Event: KeyAdded
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 it's the identity itself, the approval process will determine its approval.
Triggers Event: KeyRemoved
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 accessor for addKey
, removeKey
and replaceKey
and removeClaim
.
Returns executionId
: SHOULD be sent to the approve
function, to approve or reject this execution.
Triggers Event: ExecutionRequested Triggers on direct execution Event: Executed
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 successfully approve an execution.
And COULD require n
of m
approvals of keys purpose 2
, if the _to
of the execution is another contract, to successfully approve an execution.
Triggers Event: Approved Triggers on successfull execution Event: Executed Triggers on successfull claim addition Event: ClaimAdded
function approve(uint256 _id, bool _approve) returns (bool success)
Identity verification
Requires: ERC 735
The following changes to ERC 735 are REQUIRED:
addClaim
This SHOULD create a pending claim, which SHOULD 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 Triggers if the claim index existed Event: ClaimChanged
removeClaim
MUST only be done by the issuer
of the claim, or keys of purpose 1
, or the identity itself. If it's the identity itself, the approval process will determine its approval.
Events
KeyAdded
MUST be triggered when addKey
was successfully called.
event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
KeyRemoved
MUST be triggered when removeKey
was successfully called.
event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)
ExecutionRequested
MUST be triggered when execute
was successfully called.
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.
event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)
Approved
MUST be triggered when approve
was successfully called.
event Approved(uint256 indexed executionId, bool approved)
The following changes to ERC 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 experimentation around identity. By having each identity in a separate contract it allows for cross identity 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 uses a standardized 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 very flexible container for identity.
Implementation
- DID resolver specification
- Implementation by mirceapasoi
- Implementation by Nick Poulden, interface at: https://erc725.originprotocol.com/
Solidity Interface
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 purpose, uint256 keyType, bytes32 key);
function keyHasPurpose(bytes32 _key, uint256 _purpose) public 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 removeKey(bytes32 _key, uint256 _purpose) 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
- In-contract claim VS claim registry
- Identity related reports
- W3C Verifiable Claims Use Cases
- Decentralised Identity Foundation
- Sovrin Foundation Self Sovereign Identity
Copyright
Copyright and related rights waived via CC0.