openssi / peer-did-method-spec

A spec for the did:peer DID method.
https://dhh1128.github.io/peer-did-method-spec/index.html
Apache License 2.0
29 stars 17 forks source link

Clarification on TOFU and an intercepted invitation #107

Closed swcurran closed 4 years ago

swcurran commented 5 years ago

I'm trying to clarify the TOFU section. I don't really understand the current wording and am trying to make it that I can.

I understand the out-of-band verification to confirm a connection. I send a code directly to the other party using another channel (say, visual, voice or email) and they confirm that code.

I also understand the use of verifiable credentials to confirm who received/processed the invitation. This handles the MITM scenario of someone other than the expected collaborator responding to the invitation.

However, there is one version of the hack that I can't figure out how to handle with the verifiable credential solution. Here is the scenario:

How can Alice be certain that the proof is from Bob and vice versa?

Assume (for now) we are using Indy for the verifiable credential exchange, and that Mallory is in-between all DIDComm messages between Alice and Bob.

I've tried to think about how to tie what Alice (assumes she) knows about Bob (basically, just a did:peer) with the proof. I'm thinking there might be some way to tie knowledge associated with the proof to the did:peer, but I don't know enough about the mechanics of the proof to determine that. Each thing I've come up with (signing or hashes) can be handled by Mallory reworking the response to use her did:peer DID with Alice.

Thoughts @kdenhartog @TelegramSam @dhh1128 @tplooker?

dhh1128 commented 5 years ago

@lovesh , this would be a good issue for you to weigh in on.

dhh1128 commented 5 years ago

If the proof request asks for either a disclosure or a ZK proof of one of Bob's attributes that Mallory doesn't have, then Mallory will not be able to pretend to be Bob. This is true no matter what credential mechanism they use (Sovrin's seems to underlie your problem description, but a JWT- or JSON-LD-based credential offers the same benefits).

Implicit in your problem description is the assumption that Alice wants to be able to distinguish between Bob and some interloper. This means there must be some attribute that Bob possesses that the interloper does not possess, and that Alice should ask for proof of it. It is not generic proving, but proof of something that Alice cares about, that creates the trust.

swcurran commented 5 years ago

I was thinking more that Mallory can simply relay Bob's proof (as is) to Alice and Alice would be able to verify it. Is there anything that prevents that?

dhh1128 commented 5 years ago

With Sovrin's credential approach, if Mallory relays the proof, Alice will see that it is relayed. That is, she will see a message that contains a proof from someone other than the party she's communicating with. She will thus not impute trust to the sender of the message, but to some other party that the sender is working with. Mallory can't prove that she is the originator of the evidence. This is essentially how Sovrin credential presentations are evaluated by third-party auditors; it is a fundamental requirement that the party showing evidence cannot impersonate the party that generated the evidence.

With non-Sovrin credentials, this non-impersonation feature may be partly duplicated by requiring the verifier to select a nonce which the prover signs. This prevents old evidence from being replayed. However, there are two very deep caveats that I don't see how to get around:

  1. In the case of the perfect MITM that you've described, the nonce for non-Sovrin creds doesn't help. The MITM can decrypt the presentation request message, see the nonce, get the signature of Bob over that nonce on the presentation response, and re-sign the presentation response with that same nonce but new keys. Note that the nonce does help if the MITM shows up after a connection is established; it's only useless with a MITM present from the very beginning.

  2. The current VC spec is a data model spec only--not a protocol spec. Thus, requiring this nonce is out of scope and not described anywhere that I know of. I don't know if any non-Sovrin impls have realized they need such a nonce, or if they have a better solution already.

kdenhartog commented 5 years ago

To prevent it, I have not identified anything. However, there is a way for Bob to be able to detect it.

Let's say Bob receives Mallory's public key in a did doc which is M.key1. (I still haven't gotten the notation down yet, but this is going to be increasingly useful for discussions like this) Then Bob sends a proof request for 3 attributes: name, date of birth, and public key to M.key1 from B.key1. Mallory decrypts the message and reencrypts it for A.key1. Alice would then respond to the proof request with the attributes name from Drivers license, DOB from birth certificate, and A.key1 as a self attested attribute. Then Alice sends that request to M.key1 who decrypts it and reencrypts for B.key1. Bob then verifies that the name and DOB are correct as usual. However there's one difference. Bob would verify that the key in the DID doc is the same as the one in the proof. It wouldn't be because the did doc contains M.key1 where as the proof contains A.key1. Bob's agent would then be able to detect that the person who owns the key is not the person who generated the proof and therefore should not trust the connection.

The reason this works is because the link secrets is used to connect all the attributes together. Therefore, Mallory cannot tamper (such as changing the public key to M.key1) with the proof in any way without making it invalid.

On Mon, Jul 22, 2019, 10:28 AM Stephen Curran notifications@github.com wrote:

I was thinking more that Mallory can simply relay Bob's proof (as is) to Alice and Alice would be able to verify it. Is there anything that prevents that?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/openssi/peer-did-method-spec/issues/107?email_source=notifications&email_token=AFQNYQYMINGU7F76ECZNS6LQAXU5TA5CNFSM4IF2S5N2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2QSOZI#issuecomment-513877861, or mute the thread https://github.com/notifications/unsubscribe-auth/AFQNYQ5S3PZJ2T4CBSLGOV3QAXU5TANCNFSM4IF2S5NQ .

swcurran commented 5 years ago

@dhh1128 - what is the Indy mechanism that does that? I'm not aware of how that works, which is why I'm asking.

kdenhartog commented 5 years ago

Also, I think it's possible to do this with regular VCs assuming the holder of the credentials has a publicly discoverable DID. I haven't written much on the subject yet however and am not certain of it at this point.

Also, it's my opinion that if this holds true like I think it will be we should write an academic paper, include mathematical security proofs, and then have it peer reviewed. This is something that I can't come up with a way to break it, but if we're going to say that it's secure we should do so through proper cryptographic analysis.

On Mon, Jul 22, 2019, 10:55 AM Daniel Hardman notifications@github.com wrote:

With Sovrin's credential approach, if Mallory relays the proof, Alice will see that it is relayed. That is, she will see a message that contains a proof from someone other than the party she's communicating with. She will thus not impute trust to the sender of the message, but to some other party that the sender is working with. Mallory can't prove that she is the originator of the evidence. This is essentially how Sovrin credential presentations are evaluated by third-party auditors; it is a fundamental requirement that the party showing evidence cannot impersonate the party that generated the evidence.

With non-Sovrin credentials, this non-impersonation feature may be partly duplicated by requiring the verifier to select a nonce which the prover signs. This prevents old evidence from being replayed. However, there are two very deep caveats that I don't see how to get around:

1.

In the case of the perfect MITM that you've described, the nonce for non-Sovrin creds doesn't help. The MITM can decrypt the presentation request message, see the nonce, get the signature of Bob over that nonce on the presentation response, and re-sign the presentation response with that same nonce but new keys. Note that the nonce does help if the MITM shows up after a connection is established; it's only useless with a MITM present from the very beginning. 2.

The current VC spec is a data model spec only--not a protocol spec. Thus, requiring this nonce is out of scope and not described anywhere that I know of. I don't know if any non-Sovrin impls have realized they need such a nonce, or if they have a better solution already.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/openssi/peer-did-method-spec/issues/107?email_source=notifications&email_token=AFQNYQ2SSHQ77MYIZU6O223QAXX7LA5CNFSM4IF2S5N2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2QU5ZA#issuecomment-513887972, or mute the thread https://github.com/notifications/unsubscribe-auth/AFQNYQ4XZC3SFB4GWVB2QWLQAXX7LANCNFSM4IF2S5NQ .

dhh1128 commented 5 years ago

@brentzundel and/or @lovesh and/or @mikelodder7, would one of you like to answer @swcurran 's question? I could take a crack at it, but I'd still need your review for accuracy, so it's simpler to go straight to the source.

lovesh commented 5 years ago

@swcurran In

  • Mallory sends Bob a proof request; Bob responds with a proof
  • Mallory sends the proof to Alice to verify the connection

I am assuming you think that when Mallory sends the proof, she can use her signing key to sign. That can be prevented. We don't have the mechanism implemented but it's designed. The idea is that a particular relationship is maintained between the public key and the link secret and to prove that this relationship exists during bootstrapping with a credential, the knowledge of private key and link secret is needed. This is how

  1. Bob has link secret l.
  2. Bob wants to create a new connection and hence he creates a keypair with (secret key, public key) as (sk, P) = (sk, g^sk). Bob also sends creates a value V where V = P^l.
  3. Bob now sends a proof proving the possession of the credential and the V is constructed in the form P^l where l in the link secret in the credential. Alice will then verify this proof and check that the signature on the DIDComm message is verified by public key P.
swcurran commented 5 years ago

So it's possible this could be addressed, but right now it's not, because there is no connection between the link secret used to prove that the holder/prover was issued the credential and the DIDComm proof delivery mechanism. Is that right?

lovesh commented 5 years ago

Yes. But to clarify, this does not require a change in issuing protocol, only proving and verifying.

kdenhartog commented 5 years ago

@swcurran I'm not I understand the problem you described. From what I can identify, you've described a traditional MITM attack. I'm interpreting your comments to be a few different problems though:

How can Alice be certain that the proof is from Bob and vice versa?

When you say "Bob" do you mean a private key used in DIDComm that's owned by Bob, a link secret owned by Bob, attributes that are linked with a link secret owned by Bob, or all?

there is no connection between the link secret used to prove that the holder/prover was issued the credential and the DIDComm proof delivery mechanism

I'm confused by this part where you're describing the DIDComm proof delivery mechanism. I'm not seeing how the delivery mechanism (e.g. JSON format I assume) affects the ability to prove ownership of the private key and credential (by extension the link secret).

From what I understand @lovesh is describing a mechanism to generate proof that the link secret and private key are connected and can be verified in some way to prevent MITM. What I described is a way to detect that a MITM has occurred. However, I'm not sure which problem you're looking to solve. Could you clarify please?

swcurran commented 5 years ago

Classic - I don't know what you don't understand :-). I'll try again with different words.

Alice sent out an invitation intending it to go to Bob. Mallory intercepted and created connections to both.

After DID Exchange, Alice is connected to Mallory (but thinks it's Bob) and Bob is connected to Mallory (but thinks it's Alice). Alice wants to use VCs to confirm that it is Bob (or at least get the name of who it is).

Alice sends out a proof request for a name to her connection - hence, to Mallory. Mallory gets the proof request and sends the identical proof request to Bob, who constructs the proof and sends it back. Mallory takes the proof and uses it to respond to the original request from Alice. Alice verifies the proof and labels the connection she has as "Bob".

Using did:peer, DIDComm and Indy, is there a way that Alice could know that the proof she received was not constructed by the person she received it from?

dhh1128 commented 5 years ago

@swcurran I have an answer for you, but it's too long to write out in the comment stream. Let me write it in a google doc and then I'll link to it here.

kdenhartog commented 5 years ago

Using did:peer, DIDComm and Indy, is there a way that Alice could know that the proof she received was not constructed by the person she received it from?

This is the question I was looking for. I had seen a few questions, so I wasn't sure how they were connected.

The answer to this question is yes when Mallory and the verifier aren't colluding (e.g. Bob is signing a proof for Mallory). It's possible because the attribute that's self attested can be linked to a credential in the same way a credential is can be linked to another credential using a link secret.

If this is confusing, I can jump on a call and explain it in better detail. The reason I thought we were talking past each other is because everyone else is explaining answers in ways that didn't seem relevant to what I was explaining in the TOFU paragraph.(e.g. using nonces and linking keys to link secrets) I assumed I'm interpreting the question wrong because of this and wanted to make sure I was understanding the question right.

Based on the rewording I think we're thinking of the same problem now. Which leaves me with having just poorly explained it in the spec. Let's figure it out and I'll update the explanation based on what we learn from finding a common understanding.

lovesh commented 5 years ago

It's possible because the attribute that's self attested can be linked to a credential in the same way a credential is can be linked to another credential using a link secret.

This sounds incorrect. The way you link 2 credentials is by proving they have the same link secret. The way self attested attributes are connected to the credential is that there is a signature on the "combined message" meaning credential proof + revealed credential attributes + self attested attributes

lovesh commented 5 years ago

@swcurran In

  • Mallory sends Bob a proof request; Bob responds with a proof
  • Mallory sends the proof to Alice to verify the connection

I am assuming you think that when Mallory sends the proof, she can use her signing key to sign. That can be prevented. We don't have the mechanism implemented but it's designed. The idea is that a particular relationship is maintained between the public key and the link secret and to prove that this relationship exists during bootstrapping with a credential, the knowledge of private key and link secret is needed. This is how

  1. Bob has link secret l.
  2. Bob wants to create a new connection and hence he creates a keypair with (secret key, public key) as (sk, P) = (sk, g^sk). Bob also sends creates a value V where V = P^l.
  3. Bob now sends a proof proving the possession of the credential and the V is constructed in the form P^l where l in the link secret in the credential. Alice will then verify this proof and check that the signature on the DIDComm message is verified by public key P.

@dhh1128 @swcurran @kdenhartog. @khovratovich suggested a simpler alternative where the extra V is not needed. Bob while creating a proof, hashes the public key P in the challenge (the way nonce from proof request is hashed into the challenge) and Alice while reconstructing the challenge during proof-verification hashes the public key that she used to verify the signature on the DIDComm message. Though the statement proven by this construction is not that the proof creator knows the private key for P (unlike the previous construction), it suffices for this use case.

mikelodder7 commented 5 years ago

To add to @lovesh's comment. The proof will fail for the verifier. If all anon cred proofs fail, this could indicate a MITM. If any succeed then no MITM. If all anon cred proofs fail, Bob should check with Alice that the public key he has is the one Alice sent. This check should be done out-of-band.

swcurran commented 5 years ago

@mikelodder7 - it's why it will fail that I'm trying to understand. Mallory sent Alice's proof request to Bob. Bob gave back Mallory a proof. Mallory sent the proof to Alice. What is it that resulted in Alice knowing that the proof wasn't created by Mallory? That's the explanation I'm looking for.

mikelodder7 commented 5 years ago

When you add the public key to the challenge hash, the challenge hash is used in the Fiat-Shamir heuristic to verify the signatures. Since the public key is incorrect the challenge hash will be incorrect which means the proof will fail.

swcurran commented 5 years ago

What public key are we adding to the challenge hash? Is this something that is done in the "normal" use of Indy proof creation (same as we have been using for years), or is this something specific to this use case - that Alice would have to know to ask for and check and/or Bob would have to know to provide?

mikelodder7 commented 5 years ago

It’s the verkey of the peer did. This is a recommendation to check for MITM. Instead of a nonce you use the verkey.

swcurran commented 5 years ago

Ah...so we need a protocol between the holder and the verifier of what is being done. That's what I was missing. This is not a feature of the Indy VC model, but something that could be added as part of the protocol.

So my next question is can we/should we make it part of the core proof request/proof process. Perhaps there should be a field in the proof that is the "comms public key" that always ties the delivery channel of the proof with the proof itself, preventing the proof from being reused in any circumstance.

lovesh commented 5 years ago

@swcurran

What public key are we adding to the challenge hash?

The public key of Bob (prover) that Alice (verifier) uses to verify signature on DIDComm message.

lovesh commented 5 years ago

@mikelodder7

Instead of a nonce you use the verkey.

verkey is additional to nonce, you need the nonce since you can have multiple proof requests during the life of connection and secondly how do ensure that the proof does not correspond to an old interaction with another party (some keypair of Bob was stolen that he is not using now).

lovesh commented 5 years ago

@swcurran

So my next question is can we/should we make it part of the core proof request/proof process.

We can have provision in proving/verifying protocol where prover can "put extra things in challenge" do bind those "extra things" to the proof and knowledge of link secret. These "extra things" can be properties of the verifier or comm channel like a public key, IP (assuming you can't spoof), TPM Id, etc.

swcurran commented 5 years ago

Agree that this should not/would not replace the nonce. I would suggest though that we elevate to a first class element of a proof, and use it the way that @lovesh is describing. In typical DIDComm use, it would be the recipientKey of the agent to whom you are sending the proof. When the proof is delivered over other channels, it be something TBD, or perhaps even left off.

mikelodder7 commented 5 years ago

I didn’t mean to say replace the nonce. I meant to say not just the nonce but the public key also

mikelodder7 commented 4 years ago

@swcurran

So my next question is can we/should we make it part of the core proof request/proof process.

We can have provision in proving/verifying protocol where prover can "put extra things in challenge" do bind those "extra things" to the proof and knowledge of link secret. These "extra things" can be properties of the verifier or comm channel like a public key, IP (assuming you can't spoof), TPM Id, etc.

Or self-attested attributes. The protocol should allow the prover to add self-attested information. which can be anything arbitrary that the prover wants to be bound to a proof.

dhh1128 commented 4 years ago

I think this was an excellent discussion, but that it ended up generating insight that's more applicable to handshake protocols, not so much to peer DIDs. I don't think any of the issues we've uncovered here are ignored by KERI, where we're going to align the spec going forward; what remains after we implement pre-rotation of the inception key is an issue for VCs, not the DID method.

If I am wrong, please reopen the ticket, and I'll create something to track the topic in the spec's new home at DIF (https://github.com/decentralized-identity/peer-did-method-spec).