w3c / vc-data-model

W3C Verifiable Credentials v2.0 Specification
https://w3c.github.io/vc-data-model/
Other
287 stars 103 forks source link

Data Model in Context of Keys, Signatures & Countersignatures #118

Closed ChristopherA closed 6 years ago

ChristopherA commented 6 years ago

One of my challenges with the current data model focus of the WG is how it connects to the signatures of that data model. As an implementor, I find that confuses me when I consider claim + one or more signatures.

Lets take a simple verifiable claim (from the Verifiable Claims Playground, which may not be current):

{
  "@context": "https://schema.org/",
  "claim": {
    "id": "did:ALICE",
    "name": "Alice",
    "knows": {
      "id": "did:BOB",
      "name": "Bob"
    }
  }
}

When signed by one of the signing keys that is available from Alice's set of DID signing keys, it is a claim from an issuer, and has the trust level / authority that you give to that issuer. Is a claim signed any other way invalid?

When both signed by one of the signing keys that is available from Alice's set of DID signing keys AND SEPARATELY by one of the signing keys that is available from Bob's set of DID signing keys, I think this may have greater authority, as if you trust either Bob or Alice it has trust level authority of them individually, but with both signatures it has the trust authority of both.

If signed by Alice, and the entire structure (including signature) is signed by Bob, what does that mean differently than the previous?

When signed ONLY by one of the signing keys that is available from Bob's set of signing keys, but not Alice's, what is it?

When it also signed by a third party (in addition to either Alice's or Bob's keys), that could be a witness claim.

But when it is signed by a third party (w/o Alice's or Bob's keys), what is that? An evidence claim?

When a signed claim above also has a time signature in it (a verifiable time stamp), what does that mean?

I presume if it was signed by an otherwise valid key, but not one that is designated as a signing key, then that claim should be considered invalid?

So in general, as an implementor, how do I know that the signing expresses the intent of the signer about the claim?

dlongley commented 6 years ago

Only skimmed this briefly right now but it seems like the use of a new term in Linked Data Proofs, proofPurpose, would be useful here. It's a term that can be included in the signature meta data that indicates the purpose of the proof/signature and links a verifier to a predicate where they can find the appropriate application suite and key material for verification from the signer.

dlongley commented 6 years ago

As possible examples, a signature may include a proofPurpose with a value of authentication (where a signature is intended to authenticate the signer), issueCredential (where the signature is intended to prove authorship of a credential), endorsement (where a signature is intended to endorse someone else's issuance of a credential), invokeCapability (where a signature is intended to provide proof for invoking an ld-ocap), etc.

jandrieu commented 6 years ago

What we need is clarification of the semantics of a signature and additional examples for the edge cases.

Three constructs, using the example above.

A. Alice signs the above claim (Claim Alpha). That signed claim means

Alice says "'Alice knows DID:Bob' and 'DID:Bob is named Bob'"

resulting in Verifiable Credential Beta (VC Beta). Alice has asserted to the veracity of the two statements, namely that she knows DID:Bob aka Bob.

B. If the entire structure of VC Beta is signed by Bob (creating VC Gamma), that would mean

Bob says that Alice says "'Alice knows DID:Bob' and 'DID:Bob is named Bob'"

This statement does NOT assert the matter of fact of Alice's knowledge of DID:Bob (aka Bob), but rather simply asserts that Alice has made such an assertion.

C. If Bob independently signs the original Claim Alpha (creating VC Delta), that means

Bob says that "'Alice knows DID:Bob' and 'DID:Bob is named Bob'"

This statement mirrors Alice's assertion of VC Beta, claiming that, in fact, Alice knows DID:Bob and that DID:Bob is named Bob. However, it makes no assertion about whether or not Alice has said the same thing.

D. If a third party, Trey, independently signs the original Claim A (creating VC Epsilon), that means

Trey says that "'Alice knows DID:Bob' and 'DID:Bob is named Bob'"

This mirrors VC Alpha and VC Delta as an independent assertion of the underlying fact of Alice's knowledge of DID:Bob and DID:Bob's name "Bob".

F. If Trey signs VC Gamma that would mean

Trey says that >>Bob says that Alice says "'Alice knows DID:Bob' and 'DID:Bob is named Bob'" <<

This means Trey is asserting that Bob said that "Alice said Claim Alpha" without any evaluation of the fact of Claim Alpha nor about Bob's assertion in that statement.

Situations B and F could reasonably be called "Witnessing a Claim" as Bob and Trey are witnessing claims made by others.

Situation C and D could reasonably be called "Corroborating a Claim". I don't think these are examples of "evidence" as @ChristopherA suggested.

When a signed claim above also has a time signature in it (a verifiable time stamp), what does that mean? Depending on the nature of the timestamp, either that the signatory made the assertion at a given point in time, or (if using a ledger timestamp) that the signatory memorialized the assertion on a blockchain with a particular reference pointer (TX or block or whatever) establishing the claim was made in a particular window of time.

I presume if it was signed by an otherwise valid key, but not one that is designated as a signing key, then that claim should be considered invalid?

I don't know what that means. I think you are suggesting that some keys should be considered authoritative for signing particular claims while not for signing others. This makes sense and probably falls under "capabilities", I believe that is technically out of scope for VCs. It probably is in scope for the DID or certain DID method specs where the DID establishes which keys are authorized for which actions.

But, for the VC data-model spec, I believe the authority of a particular signature wrt a particular claim is a separate matter.

So in general, as an implementor, how do I know that the signing expresses the intent of the signer about the claim?

The meaning of signing should be explicitly stated in the spec. In my words, signing a claim means that the signer "says" or "asserts" the content of the highest level of the referenced claim, without assertion about underlying claims. [I'm not happy with that language, but it is a start.]

ChristopherA commented 6 years ago

Another related issue came up at #rwot — you probably should not use information in the signature block to determine data in the data model, in particular the issuer. This came up in the following example:

{
   "claim": {
    "id": "did:btcr:xkyt-fzgq-qq87-xnhn",
    "alternateName": "KimD"
  },
  "proof": {
   ...
    "creator": "did:btcr:xyv2-xzyq-qqm5-tyke:#keys-1",
    "signatureValue": "...."
  }
}

Manu was saying this was a valid claim, but that the creator would be the issuer. I'd really rather see the issuer data be in the claim itself, like:

{
 "issuer": "did:btcr:xyv2-xzyq-qqm5-tyke",
   "claim": {
    "id": "did:btcr:xkyt-fzgq-qq87-xnhn",
    "alternateName": "KimD"
  },
  "proof": {
   ...
    "creator": "did:btcr:xyv2-xzyq-qqm5-tyke:#keys-1",
    "signatureValue": "...."
  }
}

Reason? If you countersign the first without the signature, you end up being the issuer (possibly by accident), whereas if the countersign the second, you are more explicitly saying that you are corroborating or witness the claim made by the original issuer.

dlongley commented 6 years ago

@ChristopherA,

I agree that the issuer information should be in the credential. But also keep in mind that with proofPurpose the purpose of the signature is made explicit:

{
   "issuer": "did:method1:123",
   "claim": {
     "id": "did:method2:456",
     "alternateName": "KimD",
   },
   "proof": [{
     ...,
     "creator": "did:method1:123#issue-key-1",
     "proofPurpose": "credentialIssuance",
     ...
   }, {
     ..., 
     "creator": "did:method1:789#endorse-key-1",
     "proofPurpose": "credentialEndorsement", // or "witness" or whatever we come up with
     ...
  }]
}
jandrieu commented 6 years ago

@dlongley

I don't think "proofPurpose" is appropriate. My analysis may be wrong, but it seems to me that the only valid semantics for signing is to assert the root of the graph as an utterance, i.e. the issuer "says" the claim where the claim starts at the root of the graph and does NOT imply uttering any claims later in the graph. By which I mean IssuerA "saying" that "IssuerB 'said' ABC" is not itself an utterance asserting "ABC".

If one wants to make an assertion about another claim, that is a new claim, in which new statements must be constructed, e.g., "IssuerB countersigns the claim that "IssuerA asserts Joe is a person". This construction, unfortunately, then begs the question of what "countersigns" means.

My concern is that enabling variable semantics for signatures invites ambiguity and flexibility that IMO is the root of why the PGP web of trust failed. The semantics of signing were ambiguous.

dlongley commented 6 years ago

@jandrieu,

My analysis may be wrong, but it seems to me that the only valid semantics for signing is to assert the root of the graph as an utterance...

If one wants to make an assertion about another claim, that is a new claim, in which new statements must be constructed...

Well, endorsement is probably better suited as a proofPurpose in a chained proof rather than a proof set. But I'd refer back to this comment for other use cases where I do think it makes sense to be explicit about the purpose of the proof: https://github.com/w3c/vc-data-model/issues/118#issuecomment-368939061

My concern is that enabling variable semantics for signatures invites ambiguity and flexibility that IMO is the root of why the PGP web of trust failed. The semantics of signing were ambiguous.

Signatures already have variable semantics -- the reason for proofPurpose is to disambiguate the author's reason for signing. Leaving the semantics for why some data was signed up to the data itself can introduce vulnerabilities that can be somewhat mitigated by ensuring that the author is explicit about why they signed it.

jandrieu commented 6 years ago

Without defining endorsement, I don't know what you mean.

If "endorsement" means asserting the same underlying fact, then an independent credential with identical claims is sufficient.

If "endorsement" means asserting that the claim was made by the issuer (as provable in a specific credential), that doesn't feel like an endorsement as much as a "witness".

If "endorsement" means both witnessing a credential AND asserting to the truth of the underlying claims, then simply issue a new credential that says that: include the endorsed VC (witnessing it) and replicate the claims, asserting them directly. Together, that feels like a rigorous endorsement.

None of these interpretations of "endorsement" suggest that a variable meaning for signatures is necessary.

IMO, this is DEEPLY rooted in the issue of provenance and the need for context in RDF. Once it was understood that the context of a triple is necessary to fully assimilate the knowledge embedded in the triple, semantic engineers realized the folly of thinking of RDF statements as statements of "reality" and RDF started working with quads instead of triples. All we EVER have are assertions made by a particular source in a particular context. The root of provenance is always a "he said"/"she said"/"it reported" construct.

Hence, the fundamental semantics of a signature must be in the form of "issuer said X" where X is the signed claim.

Anything else is conflating the root provenance of the claim, as verifiable in the credential, with assertions of facts by the signer, which should more properly be incorporated into actual claims. Remember, we can never actually verify the claims programmatically. All we can do is verify the issuer issued a claim and has not yet revoked it or withdrawn it.

Drabiv commented 6 years ago

I agree with @jandrieu way of thinking. What you want to say should be in a claim not in a signature. So if you want to sign credential with comments on what your signature means, create new credential, reference credential that you want to say something about and add your comments (e.g. "I endorse it", "I witness it", "I agree with it", "I do not agree with it", "I approve it", "I like it", "I complaint about it" etc.) If you just sign/countersign credential that should in general mean (taking aside particular implementations), that you just signed the claim of the credential.

dlongley commented 6 years ago

@Drabiv,

What you want to say should be in a claim not in a signature. So if you want to sign credential with comments on what your signature means, create new credential, reference credential that you want to say something about and add your comments (e.g. "I endorse it", "I witness it", "I agree with it", "I do not agree with it", "I approve it", "I like it", "I complaint about it" etc.)

I think that's all well and good. I am think about scenarios, however, where the signer is fooled into signing information for a different purpose than they intended. If their signature always includes the purpose for signing, this can be mitigated. I believe there are two separate issues here -- and we probably need to employ both approaches.

Drabiv commented 6 years ago

In case when you want to limit/protect the use of credential that you sign, IMO, it would be better to put this limitation into the claim or into credential's meta-data. Something like this : "limitationOnUse": "Distribute with written consent from signer only" OR "Allowed to be distributed on US soil only" etc. Actually, is it not already speced out with "termsOfUse" ?

Drabiv commented 6 years ago

There is also a related scenario. Signer might be tricked to sign information that is different to what he thought he was signing. For example, signing Bitcoin transaction while having the impression of signing some benign credential, or authenticating to site, etc. The best way to mitigate such attack IMO would be to have many keys with different purposes in DD. Keys for financial transactions, keys for unimportant credentials, keys for important credentials. For example: "keyPurpose": "Financial Transactions in Bitcoin", "keyPurpose": "To sign financial and material documents", "keyPurpose": "To sign educational credentials".

Also this property might be very handy for Legal Persons. Legal person will be known by one DID, but many employees might have a need to sign credentials on behalf of it. This need might be met by providing them keys with different purposes. Then when verifier checks the credential, he can understand if it was signed by the key with proper authorization.

dlongley commented 6 years ago

@Drabiv,

There is also a related scenario. Signer might be tricked to sign information that is different to what he thought he was signing.

This is the scenario I'm talking about.

For example, signing Bitcoin transaction while having the impression of signing some benign credential, or authenticating to site, etc. The best way to mitigate such attack IMO would be to have many keys with different purposes in DD. Keys for financial transactions, keys for unimportant credentials, keys for important credentials. For example:

Yes, this is in the design already. The use of proofPurpose solves two problems related to this: "how does the author make their signing intent clear even if they signed the wrong thing AND where do you look for the key"? The proofPurpose tells you the relationship used to specify what the key is for. So, if a signature has:

{
   "proofPurpose": "authentication",
   ...
}

Then in the key owner's document (e.g. DID Document) you look for authentication:

{
  "id": "did:method:1234",
  ...,
  "authentication": [{
     ...,
     "publicKey": [{ /* look for the key here */}]
  }],
  "credentialIssurance": [{
    ...,
    "publicKey": [{ /* don't look here, these keys are for issuing credentials, not authN */ }]
  }],
  /* other purpose relationships... */
}

This way:

  1. The verifier knows exactly where to go looking for the key (key relationship integrity). They literally will not find the key unless it is listed under that relationship, which also helps prevent software bugs that don't properly check a "purpose" field that might be tacked onto key meta data. Implementations are less likely to get things wrong if they don't know where to look unless they use proofPurpose -- and if they won't find the key unless it's in that field.
  2. The verifier knows what the signer intended to do... even if they were fooled into signing something else.
  3. The signer is indemnified against the accusation that they meant to sign something they didn't.
Drabiv commented 6 years ago

@dlongley thanks for clarification. Now I support this idea. The only thing, that I still have issue with, is to call this property "proofPurpose". This property actually conveys "an authorization of the key used to create this proof". The actual and sole purpose of the proof is to signify, that signer agreed with everything that is written in the claim. If he does not agree with what is written in the claim, or have some caveats, he should add them in the claim. Naming this property 'proofPurpose', confuses the understanding of the actual proof purpose. What does this proof mean - the thing that is written in the claim or the thing that is written in "proofPurpose"? (semantics, but IMO very important in the long run).

I'd propose to call this property - "signedWithKeyAuthorizedTo" - not very elegant, but explicit! For example: "signedWithKeyAuthorizedTo": "authentication" "signedWithKeyAuthorizedTo": "SignEducationalCredentials" "signedWithKeyAuthorizedTo": "SignBitcoinTransactions"

dlongley commented 6 years ago

@Drabiv,

I'd propose to call this property - "signedWithKeyAuthorizedTo" - not very elegant, but explicit!

Note: proof is an abstraction for which there may be no "key" but the same principles/mechanisms would apply. So I don't think we should put "key" into the name.

This property actually conveys "an authorization of the key used to create this proof".

I disagree, at least in part. I think this property primarily conveys the intent of the signer: the reason why they were willing to sign. As a secondary feature, we get to reuse it to find the verification key/material. So both of these things are provided -- and I think capturing intent is really important.

What does this proof mean - the thing that is written in the claim or the thing that is written in "proofPurpose"?

This is exactly why both should be present. We want to create a binding, at a minimum, of categorical intent. We want to establish consistency between the claim (which is an input to the signing application) and the proof meta data (which is built into the signing application). When there is an inconsistency that's when you know it is invalid.

As a signer, we want to avoid the problem where we signed something we didn't intend to sign. By binding our intent to the proof (in its meta data) we can do this. Of course, whatever we sign should capture our intent too -- and potentially with greater granularity. But the point is that we can be fooled into signing something different, for a wholly different purpose. That means that our signing application should always include some measure of intent in the proof itself.

As a verifier, we want to ensure that whatever information we are accepting on the basis of the signature was really signed for that purpose. If the signer's intent is included, we can confirm proper linkage with whatever usage terms may be asserted (implicitly or explicitly) in the claim.

(semantics, but IMO very important in the long run).

I agree that the semantics are very important here but I've arrived at the opposite conclusion.

Suppose a signer reuses a key for both authentication and issuing credentials. Then suppose they are fooled by an attacker into signing an authentication message that they thought was a credential to be issued. The authentication message now carries a proof that states either:

  1. It was signed by a key that was authorized to issue a credential.
  2. It was signed for the purpose of issuing a credential by a key authorized to do so.

In case 1, the semantics dictate that the verifier doesn't really need to pay attention to the purpose of the proof -- this concept doesn't even exist. There is only key authorization, so all they need to do is look for the key used in "authentication" field in the signer's document. If they find the key there (which they will in this case) then they will permit the attacker to impersonate the signer. And, by the way, it's still true that the message was signed by a key authorized to issue a credential... there's no "problem". In other words, there's really no need for the field in the proof at all; putting it there offers no additional protection.

In case 2, the semantics dictate that the verifier MUST pay attention to the purpose of the proof. They may not merely look in the "authentication" field in the signer's document. They must first check to make sure that the proof purpose is "authentication" -- that there is a consistent binding between the proof and the signed message or with whatever flow is currently happening. Then, they may look in that field in the signer's document to find the key. Here the attacker will fail to impersonate the signer even though the signer (perhaps foolishly) reused the same key for two different purposes.

Drabiv commented 6 years ago

@dlongley

I'd propose to call this property - "signedWithKeyAuthorizedTo" - not very elegant, but explicit!

Note: proof is an abstraction for which there may be no "key" but the same >principles/mechanisms would apply. So I don't think we should put "key" into the name.

If there is a "signatureValue", then there is a key, hence "signedWithKeyAuthorizedTo" is more or less ok IMO. If we want general name let's call it something like "proofMadeWithToolAuthorizedTo".

This property actually conveys "an authorization of the key used to create this proof".

I disagree, at least in part. I think this property primarily conveys the intent of the signer: the reason why they were willing to sign. ...

OK, property "proofPurpose" as proposed by you, actually contains two properties "intent of signer" and "key authorization". I say, - to have "intent of signer" in proof is not correct. To have "key authorization" in proof is handy, so let's have it and let's call this property "signedWithKeyAuthorizedTo". Yes, this "key authorization" property in proof does not add anything fundamentally new, and it can be in DD only. But it is very handy to have it in proof. That is what I meant when I wrote I support this idea. I do not support adding "intent of signer" in proof. I do not understand the idea of putting "granular meaning" into claim and "general intent/meaning" into proof and then check them against each other. I think it does not bring value, only confusion.

If you want to add "terms of use", "intent of use" to credential - add them in claim. This will be clear and logical.

If you are worried of signing something that you were not intended to sign use different keys with different authorization for different purposes. If you do not want to use different keys add terms of use into all claims that you sign.

As for mitigating the attack of signing wrong credential, nor "intent of signer", nor "key authorization" properties provide full protection. In your 2nd example, you can be tricked, for example on fishing website, to sign authentication credential - hence atacker can still get "intent of signer" - "authentication". The same goes to "key authorization" property - but this approach has better security, because when you are signing something with important key, for example with key authorized for financial transactions you will be more careful. Also, for Legal Persons it will make use of DIDs easier.

Maybe, the reasoning for this "intent of use" property in proof is following - "OK, in practice putting "intent of use" property in proof is simpler and easier than putting it into claim. In practice, to put it into claim is too inconvenient. The creator of credential might reject it, as claim written by them is changed and they do not expect claim to be changed. So, there should be understanding between credential author and signer where to look for 'terms of use' in claim. (This can be further complicated if author signed crdential and wants you to countersign it - now you cannot change claim and it will invalidate their signature). If you add something in proof that will be always ok. So, let's just put it into proof". If there is such logic - I see its merit. But confusion that it will lead to with meaning of the proof, is too big downside. Hence, the proposal to use "signedWithKeyAuthorizedTo". It will have the same effect as proposed "proofPurpose" and will not bring confusion to fundamentals.

ChristopherA commented 6 years ago

There is some long history of why we are moving past the words signature and keys. Please let’s not reopen this — there are emerging multiple forms of proof, many that are not signatures or don’t have keys. We need to future proof ourselves.

Drabiv commented 6 years ago

I am ok, not mention key in the name of this property. It just not easy to come up with name that is short and does not mix notion of "intent of proof" with notion of "authorization scope of the tool used to create this proof". Maybe name - "creatorAuthorizationScope" will be a good fit?

ChristopherA commented 6 years ago

I think we are on the right track, but not quite there. I’m suspect that “issuerAuthorizationScope” is closer, but not sure if there are uses beyond authorization.

Drabiv commented 6 years ago

I think it needs to include "creator", because this is creator's authorization scope.

As per my understanding, issuer of credential is always DID, not a particular key of DID . DID is the owner of all his keys (proof creation tools), hence its authorization is not limited. Whereas authorization of proof creators (keys) can be limited to certain arbitrary areas - "authentication"; "Signing of educational credentials", etc.

Note, "creatorAuthorizationScope" should be understood as - "Creator, who created this proof is authorized to do the following things ("authentication", "sign educational credentials" etc). If this credential is out of scope of things that this creator was authorized to do, then something went wrong. Please, check."

"creatorAuthorizationScope" - should not be understood as "creator created this proof to be used within the following authorized scope...)", because this woud mean that we move meaning/intent of the credential from the claim into proof. Meaning/intent of the credential should be located in the claim or termsOfUse, or similar properties, but not in proof(!), as this would confuse understanding of credential on fundamental level.

When we use "creatorAuthorizationScope" this disctinction is easy to explain, as I just hopefully did above.

Maybe let's call this property "creatorAuthorization" - it's shorter and will go well below 'creator' in proof.

cwebber commented 6 years ago

FWIW I am in complete agreement with what dlongley said here. IMO it's important that we capture the intent of a proof/signature in the proof itself. And the words are clear to me: it's the "purpose" behind the "proof". Couldn't be clearer IMO.

cwebber commented 6 years ago

My main concern isn't terminology at all, but that it seems that we're capturing critical information in the proof itself, and that this critical information can't be expressed in the Verifiable Credentials model due to limitations imposed on this working group. We need to call this out somehow, or at least if we have a hole, leave a clearly defined hole where another mechanism other than ld-proofs/ld-sigs can specify how they provide this same information. I don't know what the right mechanism for doing this is.

On a semi-side note, is the "issuer" field redundant? Does the proofPurpose actually capture this information itself?

Drabiv commented 6 years ago

@cwebber why is it important to capture intent of a proof in the proof itself? Would it not be better to capture intent of a proof in a claim/credential? My understanding was that proof is only there to provide, well, proof that someone agreed with whatever is written in claim/credential.

My main concern isn't terminology at all, but that it seems that we're capturing critical information in the proof itself, and that this critical information can't be expressed in the Verifiable Credentials model due to limitations imposed on this working group.

Could you please clarify these limitations?

On a semi-side note, is the "issuer" field redundant? Does the proofPurpose actually capture this information itself?

As per my understanding "issuer" is always DID, hence it does not provide granularity of "proofPurpose" property (which I propose to call as "creatorAuthorization"; and understand as "proof was created by creator/key who was authorized to do the following thing").

jandrieu commented 6 years ago

As soon as we allow signatures to mean different things, we are moving into open-ended claims about claims. Which is needed, but shouldn't be forced into the semantics of signing.

If signing only ever means that the signer asserts the root claims in the credential as true, then it is unambiguous and there isn't an option for someone to be fooled into signing for the wrong purpose. Because elaborate purpose isn't part of the signature, EVER. If there is a purpose other than the foundational assertion of truth, that is in itself a claim that should be stated explicitly in the credential.

For example, when a notary signs a document, such as a release of ownership interest, they aren't endorsing the underlying document. Nor are they endorsing the release of interest. They aren't even saying that the person who signed the release is who they say they are. They are just saying there was enough evidence to convince them it was true.

What the notary is signing is the assertion that on a specific date, an individual presented a particular id (which appears valid) with a specific name, and then signed the notarized document in front of them (which by inspection is the same name). Here's an example endorsement that's valid in Georgia:

State of Georgia County of _ Signed and sworn to (or affirmed) before me on ____ Date by ____, Printed name(s) of individual(s) making statement who proved to me on the basis of satisfactory evidence to be the person(s) who appeared before me. Personally Known or Produced Identification Type of ID ___

The notary is purely asserting the truthfulness of those statements.

Signing for ANY reason other than the truthfulness of the statements opens a pandora's box to far too much ambiguity. If there is a reason for signing, it should be explicitly stated in the language of the claims, NOT selected from a subset of an arbitrarily limited vocabulary selected by the W3C. Any limited vocabulary will lead to category errors, mistatements, and just plain ambiguity.

Yes, we can have category errors, mistatements, and ambiguity within the claims, precisely where they belong. The semantics of signing should be bulletproof and mean one thing and only one thing: that the signer asserts the truth of the root statements contained therein. THAT is the only thing we actually verify. Presuming to verify the claims themselves (including the "purpose" of signing) would break the integrity guarantee of verifiability.

dlongley commented 6 years ago

I think the point is still being missed here.

This may help:

https://sandstorm.io/news/2015-05-01-is-that-ascii-or-protobuf

Let’s focus on the signature case. Naively, you might say: We need to restrict the format of the message the site presents for signature, so that it cannot be misinterpreted to mean anything else. The message will need a random component, of course, in order to prevent replays, but we can delimit that randomness in ASCII text which states the purpose. (In particular, it’s important that the text specify exactly what web site we’re trying to log into.) So, now we have:

z.example.com login challenge:1Z5ns8ectRGTMNYz3NHdB 699a674d30fc3bd42ec3619cfab13deb

Here is a message that could not reasonably be interpreted as anything except “I want to log in to z.example.com”, right? It’s safe to sign, right?

I’m sorry to say, but there is still a problem. The check was encoded in Google’s binary encoding format Protocol Buffers – we were able to decode it using the protoc tool. ... Oops, it appears you just signed a bank check after all – and you were trying so hard not to! ...Thanks for your $100. Hope you have fun on z.example.com.

A solution per Adam Langley:

I generally recommend that, whenever signing a message, a NUL-terminated, ASCII context string is prepended to the message to ensure that the verifier isn't confused about the context.

Our version of this is to include the "context" or "intent/purpose" in the "proofPurpose" field of the signature.

msporny commented 6 years ago

This issue partially related to: https://github.com/w3c/vc-data-model/pull/155

David-Chadwick commented 6 years ago

You may wish to consider two additional points in this discussion:

1) you can never really know if the signer really did intend to sign the VC, or even if they believe it is a true statement. He/she may have had a gun pointed at their head and told to sign or they would be killed. 2) an issuer can always at a later point in time issue a revocation statement to revoke his/her original signature for any reason.

Thus trying to attach intention semantics to signatures is questionable. All you can infer is the following

"the entity who is in possession of the signing key signed this claim".

You cannot even know who really signed it.