New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC: Claim Holder #735

Open
frozeman opened this Issue Oct 9, 2017 · 61 comments

Comments

Projects
None yet
@frozeman
Member

frozeman commented Oct 9, 2017

EIP: 735
Title: Claim Holder
Author: Fabian Vogelsteller (@frozeman)
Type: Standard
Category: ERC
Status: Discussion
Created: 2017-10-09

Abstract

The following describes standard functions for adding, removing and holding of claims.
These claims can attested from third parties (issuers) or self attested.

Motivation

This standardised claim holder interface will allow Dapps and smart contracts to check the claims about a claim holder. Trust is here transfered to the issuers of claims.

Definitions

  • 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: A claim is an information an issuer has about the identity holder. This contains the following:
    • topic: A uint256 number which represents the topic of the claim. (e.g. 1 biometric, 2 residence (ToBeDefined: number schemes, sub topics based on number ranges??))
    • scheme: The scheme with which this claim SHOULD be verified or how it should be processed. Its a uint256 for different schemes. E.g. could 3 mean contract verification, where the data will be call data, and the issuer a contract address to call (ToBeDefined). Those can also mean different key types e.g. 1 = ECDSA, 2 = RSA, etc. (ToBeDefined)
    • issuer: The issuers identity contract address, or the address used to sign the above signature. If an identity contract, it should hold the key with which the above message was signed, if the key is not present anymore, the claim SHOULD be treated as invalid. The issuer can also be a contract address itself, at which the claim can be verified using the call data.
    • signature: Signature which is the proof that the claim issuer issued a claim of topic for this identity. it MUST be a signed message of the following structure: keccak256(address identityHolder_address, uint256 _ topic, bytes data) // or keccak256(abi.encode(identityHolder_address, topic, data)) ?
    • data: The hash of the claim data, sitting in another location, a bit-mask, call data, or actual data based on the claim scheme.
    • uri: The location of the claim, this can be HTTP links, swarm hashes, IPFS hashes, and such.

Specification

Claim Holder

claim structure

The claims issued to the identity. Returns the claim properties.

struct Claim {
    uint256 topic;
    uint256 scheme;
    address issuer; // msg.sender
    bytes signature; // this.address + topic + data
    bytes data;
    string uri;
}

getClaim

Returns a claim by ID.

function getClaim(bytes32 _claimId) constant returns(uint256 topic, uint256 scheme, address issuer, bytes signature, bytes data, string uri);

getClaimIdsByTopic

Returns an array of claim IDs by topic.

function getClaimIdsByTopic(uint256 _topic) constant returns(bytes32[] claimIds);

addClaim

Requests the ADDITION or the CHANGE of a claim from an issuer.
Claims can requested to be added by anybody, including the claim holder itself (self issued).

_signature is a signed message of the following structure: keccak256(address identityHolder_address, uint256 topic, bytes data).

Claim IDs are generated using keccak256(address issuer_address + uint256 topic).

This COULD implement an approval process for pending claims, or add them right away.

Possible claim topics:

  • 1: Biometric data
  • 2: Permanent address

(TODO: add more in the initial standard? 3: Claim registry?)

Returns claimRequestId: COULD be send to the approve function, to approve or reject this claim.

Triggers if the claim is new Event and approval process exists: ClaimRequested
Triggers if the claim is new Event and is added: ClaimAdded
Triggers if the claim index existed Event: ClaimChanged

function addClaim(uint256 _topic, uint256 _scheme, address _issuer, bytes _signature, bytes _data, string _uri) returns (uint256 claimRequestId)

removeClaim

Removes a claim.
Can only be removed by the claim issuer, or the claim holder itself.

Triggers Event: ClaimRemoved

function removeClaim(bytes32 _claimId) returns (bool success)

Events

ClaimRequested

COULD be triggered when addClaim was successfully called.

event ClaimRequested(uint256 indexed claimRequestId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri)

ClaimAdded

MUST be triggered when a claim was successfully added.

event ClaimAdded(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri))

ClaimRemoved

MUST be triggered when removeClaim was successfully called.

event ClaimRemoved(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri))

ClaimChanged

MUST be triggered when changeClaim was successfully called.

event ClaimChanged(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri)

Solidity Interface

pragma solidity ^0.4.18;

contract ERC735 {

    event ClaimRequested(uint256 indexed claimRequestId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
    event ClaimAdded(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
    event ClaimRemoved(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);
    event ClaimChanged(bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri);

    struct Claim {
        uint256 topic;
        uint256 scheme;
        address issuer; // msg.sender
        bytes signature; // this.address + topic + data
        bytes data;
        string uri;
    }

    function getClaim(bytes32 _claimId) public constant returns(uint256 topic, uint256 scheme, address issuer, bytes signature, bytes data, string uri);
    function getClaimIdsByTopic(uint256 _ topic) public constant returns(bytes32[] claimIds);
    function addClaim(uint256 _topic, uint256 _scheme, address _issuer, bytes _signature, bytes _data, string _uri) public returns (uint256 claimRequestId);
    changeClaim(bytes32 _claimId, uint256 _topic, uint256 _scheme, address _issuer, bytes _signature, bytes _data, string _uri) returns (bool success);
    function removeClaim(bytes32 _claimId) public returns (bool success);
}

Constraints

  • A claim can only be one per topic per issuer.

Additional References

@frozeman frozeman added the ERC label Oct 9, 2017

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 9, 2017

Member

This is implemented by #725

Member

frozeman commented Oct 9, 2017

This is implemented by #725

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 9, 2017

Member

I added uint256 signatureType

Member

frozeman commented Oct 9, 2017

I added uint256 signatureType

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Oct 9, 2017

Collaborator

I'm still not sure why you're using signatures here, and thus restricting things to only externally owned accounts using ECDSA sigs. Wouldn't it be more general to rely on caller address?

Collaborator

Arachnid commented Oct 9, 2017

I'm still not sure why you're using signatures here, and thus restricting things to only externally owned accounts using ECDSA sigs. Wouldn't it be more general to rely on caller address?

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 9, 2017

Member

In order to auto-verify an claim - which could have been added by anybody - each claim needs to contain a in smart contract verifiable signature from one key of an issuers identity. The signature must sign, claim type, claim holder address and claim reference hash.

This way any contract can auto-verify claims.

There is no way to enforce this standard, and if a supposed claim holder added a claim with address issuer somebody, but that somebody never made that claim, there is no way to proof that, except using signatures.

I added the uint256 signatureType to also allow different signature in the future.

And yes you need an external owned account, or key to sign, to allow fully on chain verification. Or do you have any other method in mind, how we could solve that problem?

I will repost a pure on chain claim verification process:

  1. getClaim by index, which is the type for a trusted issuer. Index is generated: (keccak256(address issuer_address + uint256 _claimType))
  2. Ecrecover signature, retrieve address k
  3. Check if k is still a key hold by the claim issuers identity contract (issuer address)
Member

frozeman commented Oct 9, 2017

In order to auto-verify an claim - which could have been added by anybody - each claim needs to contain a in smart contract verifiable signature from one key of an issuers identity. The signature must sign, claim type, claim holder address and claim reference hash.

This way any contract can auto-verify claims.

There is no way to enforce this standard, and if a supposed claim holder added a claim with address issuer somebody, but that somebody never made that claim, there is no way to proof that, except using signatures.

I added the uint256 signatureType to also allow different signature in the future.

And yes you need an external owned account, or key to sign, to allow fully on chain verification. Or do you have any other method in mind, how we could solve that problem?

I will repost a pure on chain claim verification process:

  1. getClaim by index, which is the type for a trusted issuer. Index is generated: (keccak256(address issuer_address + uint256 _claimType))
  2. Ecrecover signature, retrieve address k
  3. Check if k is still a key hold by the claim issuers identity contract (issuer address)
@3esmit

This comment has been minimized.

Show comment
Hide comment
@3esmit

3esmit Oct 9, 2017

@frozeman Would be something like this?

pragma solidity ^0.4.15;
import "https://gist.githubusercontent.com/AugustoL/9ddf7996e23a01c6599323761c0deeef/raw/17ae59c3dc2c82df791b2e48e5d05a5c012fec42/ECRecover.sol"; //todo: change to repo
contract IdentityRegistry {
    //(... other logic)
    enum SignatureType {
        DirectCall,
        SignedMessage
    }
    function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _claim, string _uri) returns (uint256 claimId){
        
        if (signatureType == SignatureType.DirectCall) {
            require(issuer == msg.sender);
        } else if (signatureType == SignatureType.SignedMessage) {
            bytes32 signedMsg = keccak256(address(this), _claimType, _claim);
            require(issuer == ECRecover.ecrecovery(_signature, signedMsg));
        } else { revert(); }
        //(... store claim and do stuff)
    }
    //(... more other logic)
}

With this user could call directly without using signed message, and other account could register the user using the signed message?

3esmit commented Oct 9, 2017

@frozeman Would be something like this?

pragma solidity ^0.4.15;
import "https://gist.githubusercontent.com/AugustoL/9ddf7996e23a01c6599323761c0deeef/raw/17ae59c3dc2c82df791b2e48e5d05a5c012fec42/ECRecover.sol"; //todo: change to repo
contract IdentityRegistry {
    //(... other logic)
    enum SignatureType {
        DirectCall,
        SignedMessage
    }
    function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _claim, string _uri) returns (uint256 claimId){
        
        if (signatureType == SignatureType.DirectCall) {
            require(issuer == msg.sender);
        } else if (signatureType == SignatureType.SignedMessage) {
            bytes32 signedMsg = keccak256(address(this), _claimType, _claim);
            require(issuer == ECRecover.ecrecovery(_signature, signedMsg));
        } else { revert(); }
        //(... store claim and do stuff)
    }
    //(... more other logic)
}

With this user could call directly without using signed message, and other account could register the user using the signed message?

@Arachnid

This comment has been minimized.

Show comment
Hide comment
@Arachnid

Arachnid Oct 9, 2017

Collaborator

In order to auto-verify an claim - which could have been added by anybody - each claim needs to contain a in smart contract verifiable signature from one key of an issuers identity. The signature must sign, claim type, claim holder address and claim reference hash.

Why not just have a registry of claims, whose smart contract code ensures that only valid claims can be stored there?

Collaborator

Arachnid commented Oct 9, 2017

In order to auto-verify an claim - which could have been added by anybody - each claim needs to contain a in smart contract verifiable signature from one key of an issuers identity. The signature must sign, claim type, claim holder address and claim reference hash.

Why not just have a registry of claims, whose smart contract code ensures that only valid claims can be stored there?

@christianlundkvist

This comment has been minimized.

Show comment
Hide comment
@christianlundkvist

christianlundkvist Oct 9, 2017

@frozeman - interesting stuff! On-chain attestations is an important use case and this is a good outline. I think the general idea of having claim types or categories are good, and the specifications you outlined are also useful. We’ve had some similar ideas in uPort although we have mainly focused on off-chain attestations.

I tend to agree with @Arachnid that the claim architecture would be more general if we were to allow any transaction to define a claim by using the msg.sender construct. Having a registry where claims are registered and where rules are enforced would allow any ethereum address to be the subject of a claim, and it would allow any smart contract capable of sending a transaction to issue a claim.

christianlundkvist commented Oct 9, 2017

@frozeman - interesting stuff! On-chain attestations is an important use case and this is a good outline. I think the general idea of having claim types or categories are good, and the specifications you outlined are also useful. We’ve had some similar ideas in uPort although we have mainly focused on off-chain attestations.

I tend to agree with @Arachnid that the claim architecture would be more general if we were to allow any transaction to define a claim by using the msg.sender construct. Having a registry where claims are registered and where rules are enforced would allow any ethereum address to be the subject of a claim, and it would allow any smart contract capable of sending a transaction to issue a claim.

@3esmit

This comment has been minimized.

Show comment
Hide comment
@3esmit

3esmit Oct 10, 2017

I have a use case for this where a registry is using Oraclize, for example with Oraclize+GitHubGists=user register, and also there will be the organizations in that registry (also by oraclize), so oraclize would be the "claimer", and by default it's a direct message call (not sure if is possible other way). Also they provide a 'bytes proof', which should be stored together with claim? Or this case might be out of ERC735 scope?

3esmit commented Oct 10, 2017

I have a use case for this where a registry is using Oraclize, for example with Oraclize+GitHubGists=user register, and also there will be the organizations in that registry (also by oraclize), so oraclize would be the "claimer", and by default it's a direct message call (not sure if is possible other way). Also they provide a 'bytes proof', which should be stored together with claim? Or this case might be out of ERC735 scope?

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 10, 2017

Member

@3esmit the check shouldn’t be at the addClaim happen, but rather when the claim is verified by third party. There the signature of the claim needs to be checked. The signature type went to support different signatures in the future, e.g. it could hold non ecdsa siagntures as well.

@christianlundkvist good that your are here ;)
Yes sure a registry would allow for “adding” rules and this could be a useful addition, but it could get complicated when we introduce sharding , as all of those calls between the shards need then to go through an async transaction then. Though there could certainly additional registries for claims, but I think the in-contract claims are important for other off chain use cases.

Claims are not only meant to be only from other smart contracts (but they can come from any), but any off chain entity, as long as they attach a valid signature they could even go through a proxy to add claims to contracts.

Concerning adding claims for external accounts, yes that not possible. But I think it’s not really wanted either, your identity should have more than just a public key, which can be lost or stolen.

The reason why I kept the claim so flexible (e.g. sigtype, bytes for claim etc) is to allow all kind of claim type and verification to be added in the future. Only on chain verifications need the signature check. But claims can slow be checked off chain. Issuers could even attest claims about external accounts, but those doesn’t need to be stored in the Blockchain, this can be a transfer of those claims between two parties only. E.g. if I want to have a claim about me form an issuer, but I don’t want that the person which will verify the claim later can connect it to my on chain identity. In this case only the claim issuer need to be able to make that connection.

I will present tomorrow this ERC at the London ethereum Meetup, and there will be a video of that later on attached to this ERC.

I am also available for a call to discuss the details of how I think this works in a skype call. @christianlundkvist and @Arachnid you should have my skype already.

Member

frozeman commented Oct 10, 2017

@3esmit the check shouldn’t be at the addClaim happen, but rather when the claim is verified by third party. There the signature of the claim needs to be checked. The signature type went to support different signatures in the future, e.g. it could hold non ecdsa siagntures as well.

@christianlundkvist good that your are here ;)
Yes sure a registry would allow for “adding” rules and this could be a useful addition, but it could get complicated when we introduce sharding , as all of those calls between the shards need then to go through an async transaction then. Though there could certainly additional registries for claims, but I think the in-contract claims are important for other off chain use cases.

Claims are not only meant to be only from other smart contracts (but they can come from any), but any off chain entity, as long as they attach a valid signature they could even go through a proxy to add claims to contracts.

Concerning adding claims for external accounts, yes that not possible. But I think it’s not really wanted either, your identity should have more than just a public key, which can be lost or stolen.

The reason why I kept the claim so flexible (e.g. sigtype, bytes for claim etc) is to allow all kind of claim type and verification to be added in the future. Only on chain verifications need the signature check. But claims can slow be checked off chain. Issuers could even attest claims about external accounts, but those doesn’t need to be stored in the Blockchain, this can be a transfer of those claims between two parties only. E.g. if I want to have a claim about me form an issuer, but I don’t want that the person which will verify the claim later can connect it to my on chain identity. In this case only the claim issuer need to be able to make that connection.

I will present tomorrow this ERC at the London ethereum Meetup, and there will be a video of that later on attached to this ERC.

I am also available for a call to discuss the details of how I think this works in a skype call. @christianlundkvist and @Arachnid you should have my skype already.

@3esmit

This comment has been minimized.

Show comment
Hide comment
@3esmit

3esmit Oct 11, 2017

Wouldn't be equivalent, or more flexible to have function getClaimIdsByType(uint256 _claimType) constant returns(bytes32[]) over function getClaimsByType(uint256 _claimType) constant returns(Claim[]);?

Also,
function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _claim, string _uri) returns (uint256 claimId) to returns (bytes32 claimId)?

3esmit commented Oct 11, 2017

Wouldn't be equivalent, or more flexible to have function getClaimIdsByType(uint256 _claimType) constant returns(bytes32[]) over function getClaimsByType(uint256 _claimType) constant returns(Claim[]);?

Also,
function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _claim, string _uri) returns (uint256 claimId) to returns (bytes32 claimId)?

@m-schmoock

This comment has been minimized.

Show comment
Hide comment
@m-schmoock

m-schmoock Oct 12, 2017

@frozeman
Imagine a claim was self-claimed ('self-signed'), i.e. because a users sets up his identity and claims initial data (like real name and such):

  1. The approval process for this would not be required, correct?
  2. How would a second party 'sign' a self-claim, meaning claiming that the self-claimed data is correct?
  3. How would a third party iterate through the chain of claims?

Maybe you can provide some pseudo code of how this would look like..

m-schmoock commented Oct 12, 2017

@frozeman
Imagine a claim was self-claimed ('self-signed'), i.e. because a users sets up his identity and claims initial data (like real name and such):

  1. The approval process for this would not be required, correct?
  2. How would a second party 'sign' a self-claim, meaning claiming that the self-claimed data is correct?
  3. How would a third party iterate through the chain of claims?

Maybe you can provide some pseudo code of how this would look like..

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 13, 2017

Member

@3esmit Thanks for the catches, i fixed it and change the function to getClaimIdsByType, which is something we can certainly make work in todays ABI.

I changed the bytes claim to bytes data in the claim, to adhere to @holiman critic of claim being used twice in different contexts.

@m-schmoock for self assigned claims one wouldn't need the approval process and not even a signature, if the address issuer address is the same as the contract itself, there is no verification necessary, as the contract itself holds and returns the claim.

for 3. you could get claims but type using getClaimIdsByType or your know which claim issuer your trust and which claim type you want, then you can recalculate the index using keccak256(address issuer_address + uint256 _claimType) and retrieve the claim directly using getClaim

Member

frozeman commented Oct 13, 2017

@3esmit Thanks for the catches, i fixed it and change the function to getClaimIdsByType, which is something we can certainly make work in todays ABI.

I changed the bytes claim to bytes data in the claim, to adhere to @holiman critic of claim being used twice in different contexts.

@m-schmoock for self assigned claims one wouldn't need the approval process and not even a signature, if the address issuer address is the same as the contract itself, there is no verification necessary, as the contract itself holds and returns the claim.

for 3. you could get claims but type using getClaimIdsByType or your know which claim issuer your trust and which claim type you want, then you can recalculate the index using keccak256(address issuer_address + uint256 _claimType) and retrieve the claim directly using getClaim

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 13, 2017

Member

I added a Additional References section.

Member

frozeman commented Oct 13, 2017

I added a Additional References section.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Oct 13, 2017

A disputeClaim function would be a nice feature. This would allow for an issuer to assert a claimType n that is negative in nature (late payments, poor conduct) that could be pertinent to both claiming identity and character, however, is inaccurate. While in dispute, the claim would be unavailable to getClaim and possibly third party arbitration assigned or timeout to remove the lock.

realcodywburns commented Oct 13, 2017

A disputeClaim function would be a nice feature. This would allow for an issuer to assert a claimType n that is negative in nature (late payments, poor conduct) that could be pertinent to both claiming identity and character, however, is inaccurate. While in dispute, the claim would be unavailable to getClaim and possibly third party arbitration assigned or timeout to remove the lock.

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 14, 2017

Member

@realcodywburns according to this standard you approve any claim addition, and you can remove claims at any point. So there is no dispute necessary.
But you sure can’t do anything claiming something about you in other places. Like in social media today.

Member

frozeman commented Oct 14, 2017

@realcodywburns according to this standard you approve any claim addition, and you can remove claims at any point. So there is no dispute necessary.
But you sure can’t do anything claiming something about you in other places. Like in social media today.

@andrewrd

This comment has been minimized.

Show comment
Hide comment
@andrewrd

andrewrd Oct 14, 2017

@frozeman @realcodywburns Another use case for a disputeClaim would be to flag identities which have been compromised.

andrewrd commented Oct 14, 2017

@frozeman @realcodywburns Another use case for a disputeClaim would be to flag identities which have been compromised.

@realcodywburns

This comment has been minimized.

Show comment
Hide comment
@realcodywburns

realcodywburns Oct 14, 2017

Yes, the inability to remove some claims would be the goal. For example: an issuer assets a claim that identity 0xdeadbeaf has participated in their auction contract and is known to the community. As time passes , addational claims are asserted that timely payments have been received as per terms of the contract; these claims would further add credibility to both the character and validity of the identity. In the event that a shipment comes missing, the issuer then adds a claim to this effect. As the history exists, the issuer has attested that 0xdeadbeaf is trustworthy and can remove any derogatory claims with impunity. Anyone interacting with 0xdeadbeef would not know of her more recent bad actions.

If the situation arises by mistake, 0xdeadbeaf could disputeClaim, resolve the situation, and retain the longstanding credible claim. If 0xdeadbeef has actually done wrong, the claim both establishes identity and character and should be kept as record for sometime.

Allowing only positive assertions my establish identity but may not capture the full picture of an individual. At the same time, one should have the right to self defense

realcodywburns commented Oct 14, 2017

Yes, the inability to remove some claims would be the goal. For example: an issuer assets a claim that identity 0xdeadbeaf has participated in their auction contract and is known to the community. As time passes , addational claims are asserted that timely payments have been received as per terms of the contract; these claims would further add credibility to both the character and validity of the identity. In the event that a shipment comes missing, the issuer then adds a claim to this effect. As the history exists, the issuer has attested that 0xdeadbeaf is trustworthy and can remove any derogatory claims with impunity. Anyone interacting with 0xdeadbeef would not know of her more recent bad actions.

If the situation arises by mistake, 0xdeadbeaf could disputeClaim, resolve the situation, and retain the longstanding credible claim. If 0xdeadbeef has actually done wrong, the claim both establishes identity and character and should be kept as record for sometime.

Allowing only positive assertions my establish identity but may not capture the full picture of an individual. At the same time, one should have the right to self defense

@MikeD123

This comment has been minimized.

Show comment
Hide comment
@MikeD123

MikeD123 Oct 15, 2017

I'm not sure if I've misunderstood it here @frozeman but I think a common structure for claimType like this would be awesome (if I'm understanding correctly on first glance). I get that this may be out of scope for this EIP in particular, and the list will always grow over time, but something that outlines things like this?

  • 01 - Individual
  • 02 - Business

Then specifying the following:

  • 01 - Social
    • 01 - video
    • 02 - photo
    • 03 - phone
    • 04 - video
    • 05 - platform (e.g. platformURL

//

  • 02 - Sovereign
    • isoNumericM49 // country specification
      • 01 - passport
      • 02 - nationalIdNumber
      • 03 - governmentId
      • 04 - proofOfAddress
      • 05 - bankStatement

//

  • 03 - Device/Machine
    • 01 - ip
    • 02 - os
    • 03 - browser
    • 04 - etc..

Looking up an individual for their sovereign doc, in USA, that is a passport.
function getClaimIdsByType(uint256 010284001) constant returns(bytes32[] claimIds);

Feel like I may have misunderstood something, or this is a bit outside of scope, but either way, really excited for this, and thanks for doing it!

MikeD123 commented Oct 15, 2017

I'm not sure if I've misunderstood it here @frozeman but I think a common structure for claimType like this would be awesome (if I'm understanding correctly on first glance). I get that this may be out of scope for this EIP in particular, and the list will always grow over time, but something that outlines things like this?

  • 01 - Individual
  • 02 - Business

Then specifying the following:

  • 01 - Social
    • 01 - video
    • 02 - photo
    • 03 - phone
    • 04 - video
    • 05 - platform (e.g. platformURL

//

  • 02 - Sovereign
    • isoNumericM49 // country specification
      • 01 - passport
      • 02 - nationalIdNumber
      • 03 - governmentId
      • 04 - proofOfAddress
      • 05 - bankStatement

//

  • 03 - Device/Machine
    • 01 - ip
    • 02 - os
    • 03 - browser
    • 04 - etc..

Looking up an individual for their sovereign doc, in USA, that is a passport.
function getClaimIdsByType(uint256 010284001) constant returns(bytes32[] claimIds);

Feel like I may have misunderstood something, or this is a bit outside of scope, but either way, really excited for this, and thanks for doing it!

@buendiadas

This comment has been minimized.

Show comment
Hide comment
@buendiadas

buendiadas Oct 15, 2017

Great initiative @frozeman, I think using a unique URI field can lead to mistake when different Unique Resource Ids from different protocols are uploaded. Additionally to the collusion risk, as we are aggregating many different protocols, a resolver would not be able to know where to take the resource (should I request from IPFS?).

A solution could be an additional genericbytes32 protocol identifier inside the claim or a real URI creation outside the contract including the protocol distinction.

buendiadas commented Oct 15, 2017

Great initiative @frozeman, I think using a unique URI field can lead to mistake when different Unique Resource Ids from different protocols are uploaded. Additionally to the collusion risk, as we are aggregating many different protocols, a resolver would not be able to know where to take the resource (should I request from IPFS?).

A solution could be an additional genericbytes32 protocol identifier inside the claim or a real URI creation outside the contract including the protocol distinction.

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 17, 2017

Member

@realcodywburns @andrewrd the dispute claim is IMO not necessary. This standard is a shell for your own identity. First of you don't want to have every buy transaction references with your real world identity INSIDE you identity smart contract, that would be a huge privacy issue. And second there can be many reputation systems referencing this identity, this doesn't mean, every step needs to be a claim added to your identity.

Technically everybody can issuer a claim and post it anywhere (e.g. a reputation system, or facebook, twitter, etc) You can't defend yourself from that anyway (and shouldn't, as it might be legit). Allowing a claim on YOUR identity means, YOU approve it. Again don't get me wrong, reputation systems should exists, which allow sellers to verify the credibility of a buyer, but this is outside of this standard, and might just happen in a peer2peer way by sending over reputation claims you collected over time, or referencing your identity AND a reputation system you are using (These two don't have to be publicly connected, as long as you can proof owner ship of both)

@MikeD123 I think you get it a bit wrong. The idea of claimTypes is more of the nature of properties of you, e.g. 1: biometric data will obviously means your a person and not a business. 2. address will show that you are based somewhere, means you have a physical address or reference point. We could add claim types for certain social media, but thats up to discussion.

If you want to verify a claim, you most likely will not look for the type, but for a specific issuer you trust, so you can generate the ID of the claim in advance e.g.:

keccak256(address issuer_address + uint256 _claimType) -> keccak256('0x123456789...' + 1)

will generate you the hash of the claim you can get using getClaim(bytes32 _Id). If the claim doesn't exist, you either look for another, or you have to manually verify that person, or not at all. If the claim exists, you verify the signature inside the claim, and see if that recovered key is still hold by the claim issuer.

As over time, there will be trusted claim issuer, like the US gov, or some decentralised service, people can always know the index of the claims they want to retrieve and even hardcode that in their smart contracts.

On the end in most cases we don't care about the data itself, but that somebody verified it.

Concerning the subTypes. I wouldn't go so detailed, as then people can know why sub type of claim was changed when, which could be a privacy leak. For some data it might make sense to give them a separate type, but for example for biometric data, just that might be enough.

To auto verify a person in front of you, the claim issuer for biometric data needs to have some bio matching services, or zero knowledge proof smart contracts, which can take some takes biometric data, and match it against their data set, and return true or false, should the data match the person claim data reference you gave them.

@buendiadas concerning the URI, it should contain the protocol like ipfs://..., or bzz:// or https://

Member

frozeman commented Oct 17, 2017

@realcodywburns @andrewrd the dispute claim is IMO not necessary. This standard is a shell for your own identity. First of you don't want to have every buy transaction references with your real world identity INSIDE you identity smart contract, that would be a huge privacy issue. And second there can be many reputation systems referencing this identity, this doesn't mean, every step needs to be a claim added to your identity.

Technically everybody can issuer a claim and post it anywhere (e.g. a reputation system, or facebook, twitter, etc) You can't defend yourself from that anyway (and shouldn't, as it might be legit). Allowing a claim on YOUR identity means, YOU approve it. Again don't get me wrong, reputation systems should exists, which allow sellers to verify the credibility of a buyer, but this is outside of this standard, and might just happen in a peer2peer way by sending over reputation claims you collected over time, or referencing your identity AND a reputation system you are using (These two don't have to be publicly connected, as long as you can proof owner ship of both)

@MikeD123 I think you get it a bit wrong. The idea of claimTypes is more of the nature of properties of you, e.g. 1: biometric data will obviously means your a person and not a business. 2. address will show that you are based somewhere, means you have a physical address or reference point. We could add claim types for certain social media, but thats up to discussion.

If you want to verify a claim, you most likely will not look for the type, but for a specific issuer you trust, so you can generate the ID of the claim in advance e.g.:

keccak256(address issuer_address + uint256 _claimType) -> keccak256('0x123456789...' + 1)

will generate you the hash of the claim you can get using getClaim(bytes32 _Id). If the claim doesn't exist, you either look for another, or you have to manually verify that person, or not at all. If the claim exists, you verify the signature inside the claim, and see if that recovered key is still hold by the claim issuer.

As over time, there will be trusted claim issuer, like the US gov, or some decentralised service, people can always know the index of the claims they want to retrieve and even hardcode that in their smart contracts.

On the end in most cases we don't care about the data itself, but that somebody verified it.

Concerning the subTypes. I wouldn't go so detailed, as then people can know why sub type of claim was changed when, which could be a privacy leak. For some data it might make sense to give them a separate type, but for example for biometric data, just that might be enough.

To auto verify a person in front of you, the claim issuer for biometric data needs to have some bio matching services, or zero knowledge proof smart contracts, which can take some takes biometric data, and match it against their data set, and return true or false, should the data match the person claim data reference you gave them.

@buendiadas concerning the URI, it should contain the protocol like ipfs://..., or bzz:// or https://

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 17, 2017

Member

As next steps, it would be good to create a collection of PROs and CONs for having claim issues in a registry vs. having them on your identity contract directly.

Some short ideas i gathered when talking to @Arachnid, I put into this wiki page, which everybody can extend and add to it, so we don't have to do this over a series of issues: https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract

This will allow us gather a good overview over both sides.

Member

frozeman commented Oct 17, 2017

As next steps, it would be good to create a collection of PROs and CONs for having claim issues in a registry vs. having them on your identity contract directly.

Some short ideas i gathered when talking to @Arachnid, I put into this wiki page, which everybody can extend and add to it, so we don't have to do this over a series of issues: https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract

This will allow us gather a good overview over both sides.

@bneiluj

This comment has been minimized.

Show comment
Hide comment
@bneiluj

bneiluj Oct 19, 2017

@frozeman Great idea the wiki page ! https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract. Let's create a vote counting with some eth ! 😅

bneiluj commented Oct 19, 2017

@frozeman Great idea the wiki page ! https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract. Let's create a vote counting with some eth ! 😅

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 20, 2017

Member

Keep in mind both can work hand in hand, so a claim registry could be useful for some cases, and for others the attached claims in the contract itself are more useful. So can one claim referencing the claim registry, maybe with claimType 5 :)

Member

frozeman commented Oct 20, 2017

Keep in mind both can work hand in hand, so a claim registry could be useful for some cases, and for others the attached claims in the contract itself are more useful. So can one claim referencing the claim registry, maybe with claimType 5 :)

@jacqueswww

This comment has been minimized.

Show comment
Hide comment
@jacqueswww

jacqueswww Oct 20, 2017

@frozeman - so one question I had is about the possibility of expiring claims. I can imagine something like a physical address being semi-permanent, and needing re-verification every couple of years. As far as I understand it - with current layout of a Claim one would use the data field in the struct to store a value in the future? OR one would have to look up the date of ClaimAdded in the event log - which we can't do from within another contract right ;)
Simpler option is just returning a date created timestamp as part of the getClaim/claim struct, then a contract/service can decide the the delta from the getClaim call if they are willing to accept the claims' date.
Let me know what you think 😸 (I know it could possibly be scope creep over the standard, however one could argue that timestamping is something that almost anyone would be interested in)

jacqueswww commented Oct 20, 2017

@frozeman - so one question I had is about the possibility of expiring claims. I can imagine something like a physical address being semi-permanent, and needing re-verification every couple of years. As far as I understand it - with current layout of a Claim one would use the data field in the struct to store a value in the future? OR one would have to look up the date of ClaimAdded in the event log - which we can't do from within another contract right ;)
Simpler option is just returning a date created timestamp as part of the getClaim/claim struct, then a contract/service can decide the the delta from the getClaim call if they are willing to accept the claims' date.
Let me know what you think 😸 (I know it could possibly be scope creep over the standard, however one could argue that timestamping is something that almost anyone would be interested in)

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Oct 22, 2017

Member

@jacqueswww Currently there would be two ways to handle that situation:

  1. One way it would be that you make the date part of the data field, as you described.

  2. Or the claim holder signs specific claims with keys he will expire on his identity himself. As everybody who will verify a claim should definitely check that the claim signing key is still valid, any claim issuer could remove that claim key based on a time frame.

Member

frozeman commented Oct 22, 2017

@jacqueswww Currently there would be two ways to handle that situation:

  1. One way it would be that you make the date part of the data field, as you described.

  2. Or the claim holder signs specific claims with keys he will expire on his identity himself. As everybody who will verify a claim should definitely check that the claim signing key is still valid, any claim issuer could remove that claim key based on a time frame.

@adriamb

This comment has been minimized.

Show comment
Hide comment
@adriamb

adriamb Feb 2, 2018

Some random thoughts...

  • Include all data except the signature itself in the signature (so add scheme also)

  • What about adding a validity field to a claim? Since is not possible to "automatically" prove that the ERC735 implementation will allow the claim issuer to remove this claim in the future (due to a bug, or bad intentions), this it's a good way to ensure that this assertion is not going to be valid forever without claim issuer permission.

  • The definition of the signature field is that "which is the proof that the claim issuer issued a claim" but in some cases, like X509 certificates, this signature is part of the claim data itself. There's the option of extracting the signature from the certificate and placing it into the signature field, another is to use this field to create as a proof-of-possession about the public key embedded into the certificate. But it seems that the proof-of-possession makes more sense to be added in ERC #725 since there's a specific key spec for that. What about:

    1. Add a proofOfPossessionType, proofOfPossessionData fields in the Key structure of ERC #725, that in the case of e.g. X509/RSA2048 certificates could be like + proofOfPossessionData=rsa_sha256_signature(publicKey||this.address)`

    2. In the ERC #735 add a way to link the possession of a public key to a claim?

adriamb commented Feb 2, 2018

Some random thoughts...

  • Include all data except the signature itself in the signature (so add scheme also)

  • What about adding a validity field to a claim? Since is not possible to "automatically" prove that the ERC735 implementation will allow the claim issuer to remove this claim in the future (due to a bug, or bad intentions), this it's a good way to ensure that this assertion is not going to be valid forever without claim issuer permission.

  • The definition of the signature field is that "which is the proof that the claim issuer issued a claim" but in some cases, like X509 certificates, this signature is part of the claim data itself. There's the option of extracting the signature from the certificate and placing it into the signature field, another is to use this field to create as a proof-of-possession about the public key embedded into the certificate. But it seems that the proof-of-possession makes more sense to be added in ERC #725 since there's a specific key spec for that. What about:

    1. Add a proofOfPossessionType, proofOfPossessionData fields in the Key structure of ERC #725, that in the case of e.g. X509/RSA2048 certificates could be like + proofOfPossessionData=rsa_sha256_signature(publicKey||this.address)`

    2. In the ERC #735 add a way to link the possession of a public key to a claim?

@cbruguera

This comment has been minimized.

Show comment
Hide comment
@cbruguera

cbruguera Feb 3, 2018

@frozeman Nice job on this effort for standardization of identity. These are just some thoughts on the present discussion:

With regard to "claim expiration", I'm not an advocate of making this an explicit functionality of a claim standard, since "expiry date" of a given claim can be different according to different "relying parties". For example, in the banking KYC scenario: Bank A might require that my latest proof of address is no older than 2 years since issued, but Bank B might be a bit more flexible allowing for an address claim to be just not older than 5 years. In this case, time-based validity of claim is not an attribute of the issuace of it, but an aspect of its verification process, which may differ according to different relying parties.

Following on this regard, I think claims should be timestamped. Thus it's on the side of relying parties to decide how to handle the antiquity of certain claims, if needed. Some claims might include expiration as part of their inherent data (such as a government-issued passport), but then this should be an attribute of the corresponding JSON blob for this claim, which most probably wouldn't even be on-chain. For other cases, there's still the manual removal/revocation of previously issued claims.

Another example on the convenience of timestamped claims is that some relying parties (or just smart contracts part of an identity ecosystem) might want to give certain claims more or less value among others based on their antiquity, not necessarily regarding them as "expired" or "not-valid". For example, a claim-based incentivization/reputation scheme that gives more weight/points to claims which are more recent.

Still looking forward to further comprehend the scope and details of this standardization effort, since it'll be really useful for the Ethereum ecosystem and digital identity in general. Any feedback on the given views is appreciated.

cbruguera commented Feb 3, 2018

@frozeman Nice job on this effort for standardization of identity. These are just some thoughts on the present discussion:

With regard to "claim expiration", I'm not an advocate of making this an explicit functionality of a claim standard, since "expiry date" of a given claim can be different according to different "relying parties". For example, in the banking KYC scenario: Bank A might require that my latest proof of address is no older than 2 years since issued, but Bank B might be a bit more flexible allowing for an address claim to be just not older than 5 years. In this case, time-based validity of claim is not an attribute of the issuace of it, but an aspect of its verification process, which may differ according to different relying parties.

Following on this regard, I think claims should be timestamped. Thus it's on the side of relying parties to decide how to handle the antiquity of certain claims, if needed. Some claims might include expiration as part of their inherent data (such as a government-issued passport), but then this should be an attribute of the corresponding JSON blob for this claim, which most probably wouldn't even be on-chain. For other cases, there's still the manual removal/revocation of previously issued claims.

Another example on the convenience of timestamped claims is that some relying parties (or just smart contracts part of an identity ecosystem) might want to give certain claims more or less value among others based on their antiquity, not necessarily regarding them as "expired" or "not-valid". For example, a claim-based incentivization/reputation scheme that gives more weight/points to claims which are more recent.

Still looking forward to further comprehend the scope and details of this standardization effort, since it'll be really useful for the Ethereum ecosystem and digital identity in general. Any feedback on the given views is appreciated.

@SebastienGllmt

This comment has been minimized.

Show comment
Hide comment
@SebastienGllmt

SebastienGllmt Feb 4, 2018

What was the reasoning behind the following logic for ClaimId

Claim IDs are generated using keccak256(address issuer_address + uint256 _claimType)

Doesn't this block you from having multiple claims of the same claimType on one identity? What if you have multiple addresses or multiple citizenships?

SebastienGllmt commented Feb 4, 2018

What was the reasoning behind the following logic for ClaimId

Claim IDs are generated using keccak256(address issuer_address + uint256 _claimType)

Doesn't this block you from having multiple claims of the same claimType on one identity? What if you have multiple addresses or multiple citizenships?

@JosefJ

This comment has been minimized.

Show comment
Hide comment
@JosefJ

JosefJ Feb 9, 2018

Following up on @jarradh implementation here: https://github.com/status-im/contracts/tree/master/contracts
specifically on

modifier claimSignerOnly {
      require(keys[msg.sender] == CLAIM_SIGNER_KEY);
       _;
}

Should the key with keyPurpose == CLAIM_SIGNER_KEY be considered an ethereum addresses (msg.sender) only?
I had the impression that the CLAIM_SIGNER_KEY types of keys should rather be declaration of "my key pairs" (public keys that you can use to verify claims signed by my private keys), therefore not being limited to Ethereum public keys/addresses only.
=> Use case: The club entrance model that @frozeman described in his presentation at DEVCON3.
"By signing your random message with any of the key pairs which I declared I hold, I prove to you this is indeed my identity contract". Just trying to synchronize my understanding here.

If we are not limiting keys to ethereum key pairs, I think the signature should contain some actual cryptographic signature of the claim data which an identity owner can verify against the keys stored in the identity contract of the issuer.

EDIT 1:
How about instead of 'scheme' we would pass the actual 'key' bound to identity of a claim issuing party and then got the type of the this key from the issuing identity itself through getKey(key).keyType?

EDIT 2:
@frozeman:
the event ClaimAdded() is twice in the suggested interface (with and without the scheme parameter)
&
changeClaim(bytes32 claimId, uint256 claimType, uint256 scheme, address issuer, bytes signature, bytes data, string uri) returns (bool success); is missing

EDIT 3:
Dummy implementation with few changes (adding claims through executions) : https://github.com/JosefJ/IdentityContract/blob/master/contracts/ClaimHolder.sol

JosefJ commented Feb 9, 2018

Following up on @jarradh implementation here: https://github.com/status-im/contracts/tree/master/contracts
specifically on

modifier claimSignerOnly {
      require(keys[msg.sender] == CLAIM_SIGNER_KEY);
       _;
}

Should the key with keyPurpose == CLAIM_SIGNER_KEY be considered an ethereum addresses (msg.sender) only?
I had the impression that the CLAIM_SIGNER_KEY types of keys should rather be declaration of "my key pairs" (public keys that you can use to verify claims signed by my private keys), therefore not being limited to Ethereum public keys/addresses only.
=> Use case: The club entrance model that @frozeman described in his presentation at DEVCON3.
"By signing your random message with any of the key pairs which I declared I hold, I prove to you this is indeed my identity contract". Just trying to synchronize my understanding here.

If we are not limiting keys to ethereum key pairs, I think the signature should contain some actual cryptographic signature of the claim data which an identity owner can verify against the keys stored in the identity contract of the issuer.

EDIT 1:
How about instead of 'scheme' we would pass the actual 'key' bound to identity of a claim issuing party and then got the type of the this key from the issuing identity itself through getKey(key).keyType?

EDIT 2:
@frozeman:
the event ClaimAdded() is twice in the suggested interface (with and without the scheme parameter)
&
changeClaim(bytes32 claimId, uint256 claimType, uint256 scheme, address issuer, bytes signature, bytes data, string uri) returns (bool success); is missing

EDIT 3:
Dummy implementation with few changes (adding claims through executions) : https://github.com/JosefJ/IdentityContract/blob/master/contracts/ClaimHolder.sol

@richard-ramos

This comment has been minimized.

Show comment
Hide comment
@richard-ramos

richard-ramos Feb 22, 2018

@frozeman

Reviewing the interface specification I see that for ClaimIds sometimes bytes32 is used, and sometimes uint256, so I assume the original idea was to have everything using uint256, right?

If that's not the case, the approve function of #725 will get complex to implement since it expects to receive uint256 Ids for both executions and claims and we would have uint256 execution ids, and bytes32 claim ids.

richard-ramos commented Feb 22, 2018

@frozeman

Reviewing the interface specification I see that for ClaimIds sometimes bytes32 is used, and sometimes uint256, so I assume the original idea was to have everything using uint256, right?

If that's not the case, the approve function of #725 will get complex to implement since it expects to receive uint256 Ids for both executions and claims and we would have uint256 execution ids, and bytes32 claim ids.

@computerphysicslab

This comment has been minimized.

Show comment
Hide comment
@computerphysicslab

computerphysicslab Mar 2, 2018

At ERC-735 interface definition I guess
function addClaim(uint256 _claimType, uint256 _scheme, address issuer
should be instead
function addClaim(uint256 _claimType, uint256 _scheme, address _issuer
adding an underscore at parameter issuer, right? Thx!

computerphysicslab commented Mar 2, 2018

At ERC-735 interface definition I guess
function addClaim(uint256 _claimType, uint256 _scheme, address issuer
should be instead
function addClaim(uint256 _claimType, uint256 _scheme, address _issuer
adding an underscore at parameter issuer, right? Thx!

@computerphysicslab

This comment has been minimized.

Show comment
Hide comment
@computerphysicslab

computerphysicslab Mar 2, 2018

While claimRequestId is uint256, claimId is bytes32. Why? And why not every claim requested is added inmediatly? Is there any validation process needed to requested claims become added claims? Thx!

computerphysicslab commented Mar 2, 2018

While claimRequestId is uint256, claimId is bytes32. Why? And why not every claim requested is added inmediatly? Is there any validation process needed to requested claims become added claims? Thx!

@tbocek

This comment has been minimized.

Show comment
Hide comment
@tbocek

tbocek Mar 2, 2018

@computerphysicslab The claimRequestId is the id of a request (for adding a claim). Such a claim can be added by approve() from ERC725. The parameter type for the approve function is a uint256. After the approval, the claim gets added, which then can be accessed with the claim id (getClaim), which is a hash over the issuer address and the claim type.

tbocek commented Mar 2, 2018

@computerphysicslab The claimRequestId is the id of a request (for adding a claim). Such a claim can be added by approve() from ERC725. The parameter type for the approve function is a uint256. After the approval, the claim gets added, which then can be accessed with the claim id (getClaim), which is a hash over the issuer address and the claim type.

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman May 2, 2018

Member

CHANGE: I renamed claimType to topic, to be more precise. Implementations should change that accordingly.

@svenstucki Thanks for your comments. The signature does contain the claim holder (formerly named "subject") already, so that claims are subject specific.

@tbocek concerning auto accepting self-claims, this depends. If an attacker overtakes one of your keys he shouldn't be able to add self-claims right away, so going through the approval function might still be important here.

@adriamb Im not sure how a validity would help with validity checking? Im also not clear about the proof-of-possession, could you elaborate? The idea is that the signature contains the data that is necessary to check the validity of a claim, and as you will extract the key from the signature, there is not need to add that signing key specifically to the claim itself.
You would go to the issuer identity contract and check for the key, that your retrieved from the signature.

@cbruguera thats a good point. Blockchains have timestamps basically build in, so you can already know when the claim was added, though you can't check that directly from within a smart contract.

@SebastienGllmt The idea behind that is that claimIDs are deterministic, meaning you can calculate in beforehand whats the claim ID of the claim you want. Its true that this allows only for one claimID per topic and issuer. If you have a good idea how we can get around that, without loosing the predicability, to easily retrieve claims let me know :)

@JosefJ concerning the implementation: Yes keys can be anything so only checking for msg.sender wouldn't really work. This Implementation was probably done before we add the more complex key structure. Though in this example its definitely a bit restrictive, as it assumed that people will only add claims with its claim signer keys, which wont be the case, as the claim issue is what adds the claim, which in return holds a claim signer key.
So the claimSignerOnly check would need to be removed.

concerning the rest of your comment: yes that actually how it is meant. You receive the key from the signature and check if that key is present on the issuer identity contract.

Thanks for the findings in the interface.

@richard-ramos can you point me to the place where its using uint256? As far as i see its using bytes32 everywhere.

@computerphysicslab The claimRequest id is a number that is given to track the claim adding process using an approval process. The reason why claims are not added by default, is that a claim on your identity should be approved by you. Otherwise anybody can make claims about anybody else, and make it look like its agreed by you.
This is different for identity contracts that are not people. Here the claim can be added right aways thats why it says This COULD implement an approval process for pending claims, or add them right away. and not MUST :)

@everyone, how comfortable do you guys feel on adding a list of claim topic numbers already, so that current implementations have some dough to play with?

Im thinking here about number ranges, to allow future "sub topics" to be added as well.
e.g. 1000-2000 could be residence types, where 1000 is "main residence", etc.

We could also say topic 0 means the version of the topic list used, so that every identity is encouraged to add a self claim as first claim stating the topic list version used for this identity?

Member

frozeman commented May 2, 2018

CHANGE: I renamed claimType to topic, to be more precise. Implementations should change that accordingly.

@svenstucki Thanks for your comments. The signature does contain the claim holder (formerly named "subject") already, so that claims are subject specific.

@tbocek concerning auto accepting self-claims, this depends. If an attacker overtakes one of your keys he shouldn't be able to add self-claims right away, so going through the approval function might still be important here.

@adriamb Im not sure how a validity would help with validity checking? Im also not clear about the proof-of-possession, could you elaborate? The idea is that the signature contains the data that is necessary to check the validity of a claim, and as you will extract the key from the signature, there is not need to add that signing key specifically to the claim itself.
You would go to the issuer identity contract and check for the key, that your retrieved from the signature.

@cbruguera thats a good point. Blockchains have timestamps basically build in, so you can already know when the claim was added, though you can't check that directly from within a smart contract.

@SebastienGllmt The idea behind that is that claimIDs are deterministic, meaning you can calculate in beforehand whats the claim ID of the claim you want. Its true that this allows only for one claimID per topic and issuer. If you have a good idea how we can get around that, without loosing the predicability, to easily retrieve claims let me know :)

@JosefJ concerning the implementation: Yes keys can be anything so only checking for msg.sender wouldn't really work. This Implementation was probably done before we add the more complex key structure. Though in this example its definitely a bit restrictive, as it assumed that people will only add claims with its claim signer keys, which wont be the case, as the claim issue is what adds the claim, which in return holds a claim signer key.
So the claimSignerOnly check would need to be removed.

concerning the rest of your comment: yes that actually how it is meant. You receive the key from the signature and check if that key is present on the issuer identity contract.

Thanks for the findings in the interface.

@richard-ramos can you point me to the place where its using uint256? As far as i see its using bytes32 everywhere.

@computerphysicslab The claimRequest id is a number that is given to track the claim adding process using an approval process. The reason why claims are not added by default, is that a claim on your identity should be approved by you. Otherwise anybody can make claims about anybody else, and make it look like its agreed by you.
This is different for identity contracts that are not people. Here the claim can be added right aways thats why it says This COULD implement an approval process for pending claims, or add them right away. and not MUST :)

@everyone, how comfortable do you guys feel on adding a list of claim topic numbers already, so that current implementations have some dough to play with?

Im thinking here about number ranges, to allow future "sub topics" to be added as well.
e.g. 1000-2000 could be residence types, where 1000 is "main residence", etc.

We could also say topic 0 means the version of the topic list used, so that every identity is encouraged to add a self claim as first claim stating the topic list version used for this identity?

@tyleryasaka

This comment has been minimized.

Show comment
Hide comment
@tyleryasaka

tyleryasaka May 10, 2018

@frozeman I like the idea of standardizing topic numbers (at least to some degree) sooner rather than later. It will provide us useful guidance for our implementation at @OriginProtocol. Right now we're just using arbitrary numbers which will most likely not be compatible with others' implementations.

And the claimType -> topic rename makes a lot of sense. We'll be updating our implementation accordingly.

tyleryasaka commented May 10, 2018

@frozeman I like the idea of standardizing topic numbers (at least to some degree) sooner rather than later. It will provide us useful guidance for our implementation at @OriginProtocol. Right now we're just using arbitrary numbers which will most likely not be compatible with others' implementations.

And the claimType -> topic rename makes a lot of sense. We'll be updating our implementation accordingly.

@mirceapasoi

This comment has been minimized.

Show comment
Hide comment
@mirceapasoi

mirceapasoi May 19, 2018

@frozeman Your top-level description still mentions getClaimIdsByType, I'm guessing it should be getClaimIdsByTopic?

mirceapasoi commented May 19, 2018

@frozeman Your top-level description still mentions getClaimIdsByType, I'm guessing it should be getClaimIdsByTopic?

@NEO2756

This comment has been minimized.

Show comment
Hide comment
@NEO2756

NEO2756 Jun 25, 2018

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.
@frozeman
If we need to accommodate this change, how would someone come to know that we are in approve function for the execution of any pending transaction OR its approval for claim addition?
OR I am going totally in wrong direction.

NEO2756 commented Jun 25, 2018

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.
@frozeman
If we need to accommodate this change, how would someone come to know that we are in approve function for the execution of any pending transaction OR its approval for claim addition?
OR I am going totally in wrong direction.

@m-schmoock

This comment has been minimized.

Show comment
Hide comment
@m-schmoock

m-schmoock Jun 25, 2018

@NEO2756
since you mentioned addClaim:
so when we have a pending addClaim execution request, is it correct that fronend has to parse the the function call (function signature hash and parameter encoding) for that pending execution request? For security reasons this seems plausible to me, but its very clumsy to implement (imho).

m-schmoock commented Jun 25, 2018

@NEO2756
since you mentioned addClaim:
so when we have a pending addClaim execution request, is it correct that fronend has to parse the the function call (function signature hash and parameter encoding) for that pending execution request? For security reasons this seems plausible to me, but its very clumsy to implement (imho).

@NEO2756

This comment has been minimized.

Show comment
Hide comment
@NEO2756

NEO2756 Jun 25, 2018

@m-schmoock
If we have to adhere to draft and implement n of m approval scheme, I think we need to do this.
we only emit event for frontend (executionId) for further required approval(s) against executionId.

NEO2756 commented Jun 25, 2018

@m-schmoock
If we have to adhere to draft and implement n of m approval scheme, I think we need to do this.
we only emit event for frontend (executionId) for further required approval(s) against executionId.

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Jun 27, 2018

Member

Concerning the addClaim, as far as is understand the spec conventions SHOULD means can, but not must, MUST means must, and COULD means totally optional.

So if its 1 out of 1, the execution could go through immediately, but should still fire the events.

Im not understanding why you want to parse the function hash?

Concerning the topic numbers: http://schema.org/Person could be a good start reference and we sign numbers or number ranges for such. e.g. memberOf could be range 5000000, meaning we have 5M possible membership topics.

@mirceapasoi thanks for the catch, i changed it

Member

frozeman commented Jun 27, 2018

Concerning the addClaim, as far as is understand the spec conventions SHOULD means can, but not must, MUST means must, and COULD means totally optional.

So if its 1 out of 1, the execution could go through immediately, but should still fire the events.

Im not understanding why you want to parse the function hash?

Concerning the topic numbers: http://schema.org/Person could be a good start reference and we sign numbers or number ranges for such. e.g. memberOf could be range 5000000, meaning we have 5M possible membership topics.

@mirceapasoi thanks for the catch, i changed it

@m-schmoock

This comment has been minimized.

Show comment
Hide comment
@m-schmoock

m-schmoock Jun 29, 2018

@frozeman @NEO2756

anybody can add an execution request for a function that is implemented by the ClaimHolder imlpementing contract, right? This includes: addClaim (obviously), but also removeClaim, possibly malicious encoded event execution (Im not yet sure about this one), possibly functions that are offered by this specific (bad/extensive) implementation of the ERC735 contract, and maybe other attack vectors. As per design "execution requests" may be used to execute modified/malicious code on behalf of the user.

Even if it would only be addClaim and removeClaim, one would still have to parse the execution request signature in order to show the correct GUI dialog, since add and remove are two functions with a different expected outcome for the user.

When looking at out in the wild test implementations (i.e. Origin Protocal - https://github.com/OriginProtocol/identity-playground/blob/master/contracts/ClaimHolder.sol ) we see that also an "addKey(...)" could be called as they implement erc735 and KeyHolder (725) in the same contract.

Hopefully this is just a stupid misunderstanding by me...

m-schmoock commented Jun 29, 2018

@frozeman @NEO2756

anybody can add an execution request for a function that is implemented by the ClaimHolder imlpementing contract, right? This includes: addClaim (obviously), but also removeClaim, possibly malicious encoded event execution (Im not yet sure about this one), possibly functions that are offered by this specific (bad/extensive) implementation of the ERC735 contract, and maybe other attack vectors. As per design "execution requests" may be used to execute modified/malicious code on behalf of the user.

Even if it would only be addClaim and removeClaim, one would still have to parse the execution request signature in order to show the correct GUI dialog, since add and remove are two functions with a different expected outcome for the user.

When looking at out in the wild test implementations (i.e. Origin Protocal - https://github.com/OriginProtocol/identity-playground/blob/master/contracts/ClaimHolder.sol ) we see that also an "addKey(...)" could be called as they implement erc735 and KeyHolder (725) in the same contract.

Hopefully this is just a stupid misunderstanding by me...

@frozeman

This comment has been minimized.

Show comment
Hide comment
@frozeman

frozeman Jun 29, 2018

Member
Member

frozeman commented Jun 29, 2018

@NEO2756

This comment has been minimized.

Show comment
Hide comment
@NEO2756

NEO2756 Jun 29, 2018

@m-schmoock @frozeman
I am also not aware of origin implementation. But I don't want anybody to add claim to my identity without my permission/approval. So i recommend to have MUST in case claim issuer is not MANAGEMENT key holder (i.e. no approval required for self claim) and approval process (via claimRequested event ) for any other execution for claim addition.

NEO2756 commented Jun 29, 2018

@m-schmoock @frozeman
I am also not aware of origin implementation. But I don't want anybody to add claim to my identity without my permission/approval. So i recommend to have MUST in case claim issuer is not MANAGEMENT key holder (i.e. no approval required for self claim) and approval process (via claimRequested event ) for any other execution for claim addition.

tyleryasaka added a commit to OriginProtocol/origin-js that referenced this issue Sep 21, 2018

Remove overloaded, unused event signature
We had an overloaded `ClaimAdded` event with a `signatureType` parameter. I'm not sure what the deal on this is - the parameter name is mentioned in some ERC735 comments (ethereum/EIPs#735 (comment)) but is not in the solidity interface or in mirceapasoi's implementation (https://github.com/mirceapasoi/erc725-735/blob/master/contracts/ERC735.sol). We are also not using the `signatureType` parameter.

I would have left this event there, but it is causing the `getPastEvents` lookup to fail when you search for `ClaimAdded`. No events are returned. Apparently, it gets confused by overloaded events and just doesn't return anything.

Simplest solution seems to be to remove the unused event signature.
@bitcoinbrisbane

This comment has been minimized.

Show comment
Hide comment
@bitcoinbrisbane

bitcoinbrisbane Sep 22, 2018

Id like to see the struct have an Uint256 for expire date time. Most documents have an expiration date.

bitcoinbrisbane commented Sep 22, 2018

Id like to see the struct have an Uint256 for expire date time. Most documents have an expiration date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment