Closed frozeman closed 2 years ago
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?
@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.
@frozeman Your top-level description still mentions getClaimIdsByType
, I'm guessing it should be getClaimIdsByTopic
?
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 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 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.
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
@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...
I am not sure about the origin implementation. The idea is that the execution request is only fired if the executed function is called. For addClaim it should fire the respective event, which then would make the user call the improve function, with the right ID. There might be some confusion here when execute is used On 29. Jun 2018, 12:
@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.
Id like to see the struct have an Uint256 for expire date time. Most documents have an expiration date.
for scheme rsa, should the public key be attached along with signature?
topic number should be standardised. otherwise every one just use its own numbers. the claim is not portable.
@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
orfalse
, should the data match the person claimdata
reference you gave them.@buendiadas concerning the URI, it should contain the protocol like
ipfs://...
, orbzz://
orhttps://
@frozeman I am looking to engineer secure enclaves (keystone enclave perhaps?) + zkp for attestations at scale. Is this something that you are looking at as well?
Nathan Aw
It doesn‘t look intuitive to me that someone else is claiming something about subject’s identity. Isn’t it more natural that the subject states claims about itself and trustworthy endorsers are confirming these claims. Self issued claim would be a claim that has no endorsers. I also think for standardization purposes that it would be better to have separate registry contracts for seprate claim topics. This way the contract’s address is the topic.
Concerning the topic numbers: http://schema.org/Person could be a good start reference
I like this proposal, but how could be map it exactly ?
Proposal 1
Mapping Schema.org > People => topic in the order. First property on the page is additionalName so = topic 1 and so on. But what if properties get added to Schema.org > People? And additionalName = topic 1 makes no sense.
Proposal 2
We define here a "manual" list for Schema properties that makes sense, like familyName = topic 1, givenName = topic 2, ... Maybe we can find another referential that already has mapped properties to integers, or that is easier to map.
Proposal 3
I like the Schema.org > People reference and I would prefer the mapping to be deterministic. Maybe we could just convert the schema.org property from ASCII to integer.
Example: http://schema.org/Person, givenName property
Storing it from UI to BC
This approach would allow (2^256 - 1) / 3 = about 10^25 triplets = up to 25 characters for properties.
Some properties topic IDs with this conversion:
For properties that have their first character ASCII code beginning with 0, we'll just remove the first zero:
This approach could add many other properties of other schemas, the only limits being:
The other problem with this approach is that it would consume a lot of topics ID distributed more or less randomly according to ASCII to integer conversion and that we have no more ranges for other custom topics not on Schema.org.
One solution could be to treat all those custom topics like if they were in Schema.org with a first ASCII character encoded in integer on 3 decimals but that is not on the alphabet, like for instance | (124).
Example implementation: https://github.com/guix77/erc735example
Example uses a helper module to convert property names from ASCII to BigNumber, and from BigNumber to ASCII: https://github.com/guix77/erc735js
In light of ERC 725 v2, this standard needs a bit of re-work, as now it can sit separate from the ERC725 proxy account, in its own contract.
We would now need to manage the approver different, as well as probably add a subject to the claims. It could also be transformed into a standard claim registry like #780, but with more a sophisticated claim structure.
Seems to have a missing function
before changeClaim
method on the Solidity Interface example code.
Hi All, I like what this EIP is trying to achieve but think it could be better implemented. I discussed the idea of using a salted merkle tree here and I think it is more sensible because it preserves privacy and enables link-ability to the source e.g. drivers license -> DOB -> above 21.
Why does addClaim()
return a uint256
? Everywhere else, claim IDs are of type bytes32
.
Does the plus symbol in keccak256(address issuer_address + uint256 topic)
for generation of claim IDs symbolize concatenation or addition? If it symbolizes concatenation, that could be made more explicit. If it symbolizes addition, that's a bad idea to begin with. It might not be obvious to people implementing the interface that they need to check whether the resulting ID is already in use by a different issuer address.
If an identity contract, it should hold the key with which the above message was signed
Does that mean that the identity contract's owner should be the address used for signature verification? If not: How is the address / the public key specified?
I think that if the identity contract does not "hold the key with which the above message was signed" (whatever this means) anymore, rendering the claim invalid, anyone should be able to remove it. Not just the subject or the issuer. Maybe the standard should even specify a preferred mechanism for removing such claim automatically.
a claim should only be removed by the subject (the identity holder) because only they can decide what should be forgotten about them.
I would prefer to have an addClaim
and a separate updateClaim
function. It reduces the potential for confusion and error. When addClaim
is called for an existing claim, the transaction is reverted. Same thing for an updateClaim
on a missing claim.
I believe it is necessary to separate the revocation of claims from their update. While a revocation is a special kind of update, it MUST be available to both the subject and the issuer WITHOUT a permission. It MUST NOT be possible for the subject to prevent the revocation of a claim.
Arguably it is the only permissible update to a claim. If a claim is not current anymore, it should be removed and a new one should be added. The claimId MUST be unique. Indeed, if applications can trust that a claim can not changed (except for early revocation) they will not need to verify the claim each time it is read.
a claim should only be removed by the subject (the identity holder) because only they can decide what should be forgotten about them.
A claim's issuer should have the authority to retract his assessment. Besides: Your premise is flawed. The blockchain does not forget.
I would prefer to have an
addClaim
and a separateupdateClaim
function. It reduces the potential for confusion and error. WhenaddClaim
is called for an existing claim, the transaction is reverted. Same thing for anupdateClaim
on a missing claim.
addClaim()
can do a perfectly good job at updating a claim. Your idea merely makes the interface fatter.
I believe it is necessary to separate the revocation of claims from their update. While a revocation is a special kind of update, it MUST be available to both the subject and the issuer WITHOUT a permission. It MUST NOT be possible for the subject to prevent the revocation of a claim.
Didn't you just say that only the subject should be able to remove a claim?
Arguably it is the only permissible update to a claim. If a claim is not current anymore, it should be removed and a new one should be added. The claimId MUST be unique. Indeed, if applications can trust that a claim can not changed (except for early revocation) they will not need to verify the claim each time it is read.
Couldn't you just store a hash for that purpose?
A claim's issuer should have the authority to retract his assessment. Besides: Your premise is flawed. The blockchain does not forget.
retracting the assessment is what revocation is for. A deletion makes the claim disappear from the current state.
I believe it is necessary to separate the revocation of claims from their update. While a revocation is a special kind of update, it MUST be available to both the subject and the issuer WITHOUT a permission. It MUST NOT be possible for the subject to prevent the revocation of a claim.
Didn't you just say that only the subject should be able to remove a claim?
revoking and removing are two very different things. A removed claim will not be returned by getClaim(claimId)
whereas a revoked claim will.
Arguably it is the only permissible update to a claim. If a claim is not current anymore, it should be removed and a new one should be added. The claimId MUST be unique. Indeed, if applications can trust that a claim can not changed (except for early revocation) they will not need to verify the claim each time it is read.
Couldn't you just store a hash for that purpose?
Of course you can create workarounds. What is your argument for updating a claim instead of creating a new one?
addClaim()
can do a perfectly good job at updating a claim. Your idea merely makes the interface fatter.
there are a few arguments for making the interface fatter:
upsert
(borrowed from Mongo) or similaradd
in order to create new things, update
to make changes and upsert
when I don't careIs there any reason why the claim id does not contain the identityHolder_address. By including the identityHolder_address the claim id would be globally unique, which comes in handy when tracking claims from multiple 735 instances.
hi all, do we have a beta version of this code just like erc725.. thanks much in advance!
cheers
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.
NOTE: Due to the changes in ERC725, this spec is not fully compatible with the current ERC725v2. If you're interested in adopting this spec to work with 725v2, please comment below, or send a gist with changes.
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
: Auint256
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 auint256
for different schemes. E.g. could3
mean contract verification, where thedata
will be call data, and theissuer
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 calldata
.signature
: Signature which is the proof that the claim issuer issued a claim oftopic
for this identity. it MUST be a signed message of the following structure:keccak256(address identityHolder_address, uint256 _ topic, bytes data)
// orkeccak256(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.
getClaim
Returns a claim by ID.
getClaimIdsByTopic
Returns an array of claim IDs by topic.
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 data2
: Permanent address(TODO: add more in the initial standard?
3
: Claim registry?)Returns
claimRequestId
: COULD be send to theapprove
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
removeClaim
Removes a claim. Can only be removed by the claim issuer, or the claim holder itself.
Triggers Event: ClaimRemoved
Events
ClaimRequested
COULD be triggered when
addClaim
was successfully called.ClaimAdded
MUST be triggered when a claim was successfully added.
ClaimRemoved
MUST be triggered when
removeClaim
was successfully called.ClaimChanged
MUST be triggered when
changeClaim
was successfully called.Solidity Interface
Constraints
Additional References