-
Notifications
You must be signed in to change notification settings - Fork 12
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
transaction authorizations and challenge stringify problem #66
Comments
Thanks for this @eoln. I know we have dismissed this before, but this is exactly what the Perhaps our friend @adrianhopebailie can tune in as he will likely have strong feelings about what should be signed as our 'challenge'. |
How big is the We specifically want something that can be reconstituted from the quote/transfer. So the condition may not be suitable. |
@jgeewax 's decision: hash the |
Perhaps we need to add a |
The ILP packet contains an encoded version of the Transaction object, which contains all the information about the transfer; so it is rich, but potentially quite large. If we want to sign something small, it might be better to use the condition, which is the signed and hashed version of the Transaction object created by the payee DFSP. |
Yes, I think the 'condition' makes sense here.. |
We spoke about that but I think we were lacking some context on how the
condition is derived.
What's important is proving after-the-fact that a signature from an end
user signed something that was "intrinsically representative of the
transaction". This means that it must be completely unique (no two
transactions can share the same one), and it should ideally be something
that we can derive from some human-understandable data. If we have
`signature(condition)` and someone says "I never authorized the
transaction", I want to be able to take the transaction details, use that
to compute the condition, and then show them that they digitally signed
that and therefore cannot argue that Mojaloop did anything wrong. If the
condition works, then that's fine. If we can't easily reproduce it from a
set of transaction details (or decode it to see that it represents a
transfer of $X from A to B), then we should probably use
hash(transactionObject).
In other words, what I'm trying to avoid is a signature of something
arbitrary like the transaction ID. Having a signed transaction ID does
nothing after the fact to prove that A authorized sending $X to B.
… |
The Condition is a signature generated by the Payee DFSP over the Transaction object using its private key. It can't be regenerated by any other party; but it is a reliable representation of the Transaction object which is otherwise accepted by all parties to the transfer, even though none of them could regenerate it independently. So I think that kind of meets your requirements, provided it's OK to substitute "the payer DFSP" for "I" in confirming that the thing signed was in fact a representation of the Transaction object. In addition, the Payee DFSP returns a fulfilment as proof that it has confirmed the transfer. This can be confirmed against the condition by any party who has both values by applying a SHA-256 hash to the fulfilment: the result should be the condition. This is the current form of security between parties in Mojaloop, and I'd like to retain it if we can... |
TL:DR; 👍 to using the Condition |
Just be super clear... If someone says "hey I didn't do that", we need to
be able to say "Yes you did. here's what you signed: <data>. if you don't
believe it, try it yourself (or verify it yourself)".
My memory is a little hazy on HMAC, but I believe the secret must be kept
secret. So when they say "prove that i signed that transaction" we have to
say "welp.. we cant because we cant give you that secret", right? If so , I
think that's bad...
… |
So we have three pieces of information: the Transaction object itself, the condition and the fulfilment. The payee DFSP creates the fulfilment from the Transaction object, and the condition from the fulfilment; and all parties can be confident that it was the Payee DFSP that created the condition because of non-repudiation. This is the basis which the payer DFSP uses to reserve the funds for its customer; and matching the condition with the fulfilment is the basis on which the switch and the payer DFSP will clear funds and record the transfer for settlement. So I think that the condition is a representation of the terms of the transfer which is accepted by all other parties, and should therefore be sufficient for the PISP. True, the condition was produced using a private key which nobody but the payer DFSP knows; but the object itself will be signed by the PISP using the FIDO private key that it holds, and verified by the FIDO server using the matching public key that it holds. So in order to prove that the PISP signed the object, all we need to know is the FIDO keys, since all parties have already accepted the condition as a valid representation of the terms of the transfer... At least, that's what I think |
I am not sure we are still on track. Correct me if I am wrong: User is signing the challenge with his private key, so everybody who knows User's public key can verify pinValue (the challenge signing), especially the User's Payer DFSP. The User can't deny his signing because of the nature of asymmetric cryptography (Priv/Pub key) and challenge which is well known to all involved parties. The problem of this story is what we select as a challenge - am I right? |
Absolutely and completely (I'm tempted to add, of course.) And please excuse my typo in l. 8, which should read "payee DFSP", not "payer DFSP". So I think I'd want to phrase the question as follows: we want to be able to verify that the PISP agreed to the terms of the transfer by signing the challenge (and, in principle, that it displayed those terms to its customer and obtained the customer's consent, but we have no way of verifying that.) Given that this is the case, is it sufficiently reliable for the PISP to sign a value (the condition) which is accepted as a valid representation of the terms of the transfer by all the other parties to the transfer, or do we want to insist that it should sign the actual representation of the terms in the Transaction object? I think that the first is sufficient, but I can certainly see the point of the second... |
I agree that |
Right, my focus is on the verification process for a PISP. The thing that the user is signing should be something that they themselves could reconstruct from the information available without having to trust anything asserted by the DFSP. When I think through the verification process, using the condition for this purpose seems like the PISP will still need to trust the DFSP, whereas in this scenario, the PISP is actively asserting that they DID NOT send the transaction in question. Here's the conversation I expect to happen in that case:
At the end of this interaction, we've gone from "I don't trust you, prove it", to "You have paperwork, but none of that is true proof". If, instead, we just signed a
In short, since HMAC (again, correct me if I'm wrong -- I'm a bit rusty on this...) is unidirectional, it's really only verifiable by those with the secret. We need something that can be generated by both sides, signed, and then that signature used to verify that it, indeed, was sent by an authoritative source (e.g., was definitely sent by the end user). I think that's the transaction itself... |
I think I'd like to get a bit provocative here, because I think that the emphasis has shifted. In particular, the thing that's being contested here is not whether or not the PISP "sent" the money (because it can't,) but whether or not it warranted to the institution that could send the money (the payer DFSP) that the PISP had displayed the agreed terms of the transfer to its customer, and the customer had confirmed that the transfer should go ahead.... Now, that might not make a difference, but let's see how this plays out... PISP: Hi. You said I told Bank A that it was OK to send $500 USD from Acct 1 @ Bank A to Acct 2 @ Bank B. That definitely wasn't me! |
PISP: Well, might do. But then those aren't the eventual terms of the transfer, are they? And I didn't sign them... Am I misrepresenting the state of things? |
While I *think* the interaction you have there will work, it is quite
involved and requires lots of external information. And given the issue we
have here is "someone's lying", the fewer things we have to trust, and the
simpler the verification process, the better IMO. In this case, we have an
ID and assumption that quotes were all true to their purpose and that all
parties are telling the truth. If we know someone is lying, just not sure
who, it's quite involved to figure this out and involves lots of
investigation and communication.
If the PISP was signing the entire transaction hash, we could say very
quickly: here's your public credential you registered, here's the plaintext
transaction info, and here's your signature of that transaction that the
DFSP honored.
If the credential isn't right (but all else is fine), we know the PISP
cheated and intercepted the credential during linking. They are signing
things on our behalf, not getting it signed by our device.
If the plaintext transaction info isn't right (but all else is fine), the
user knows the PISP cheated by lying to the user about where the money is
going or how much was being sent and getting a signature on something
without true consent.
If the signature doesn't check out (but all else is fine), we know the PISP
didn't do anything wrong but instead the DFSP honored a transaction it
shouldn't have, perhaps tampering with the transaction after it was signed.
There are no IDs to deal with. No extra information to double check. No one
else we need to trust that their data wasn't tampered with or take their
word that everything checks out (since they can't give us any secrets to
check ourselves).
And keep in mind that no one is asserting intentional malice by the parties
themselves. They might have been hacked and we need to be able to prove
that quickly and simply.
|
Hi All, thanks for this insightful conversation. I think I'm coming around to @jgeewax 's opinion - signing the actual transaction wherein anybody can do the maths and verify the transaction at a later date does make more sense. I think the allure of using the condition is that we already have it. To generate a Perhaps we can simply use a hash of the |
@jgeewax Reading through Adrian's spec change proposal, it looks like v2 of the API might fix the issue where participants can't verify that the fulfilment is in fact related to the ilppacket without revealing the payee's secret. this section contains more info about the proposed changes |
@jgeewax and I talked about this yesterday. The proposed implementation for generating a challenge will require the generation of Instead of waiting (or requiring) v2.0 of the FSPIOP-API for this, let's just use |
It's probably worth adding that, when we presented the PISP API proposals at the CCB, the Open API for FSP Interoperability people pushed back on the idea of including the Transaction object in open text in the messages. Assuming that nothing moves terribly quickly in this area, an alternative which would allow us to move forward might be:
This doesn't help us, however, with the Participants list. If we want to include the Participants list, and the Open API people don't see the need, then I don't see a realistic alternative to including payee DFSP messages in the PISP API, and hence to insisting that all DFSP participants in a scheme will need to support the PISP API if any of them do. |
what was the rationale? |
Their view (as articulated by Henrik) was that it was a "nice-to-have" rather than "needed-needed". I had a talk with Matt and will be exploring ways round this; but I didn't want this to hold up PISP progress |
Hi @mjbrichards, I did not object to sending the transaction object in open? The requirement that was discussed was being able to link a quote from a transfer, which I said was already possible by reading the ILP Packet, why this specific request of being able link a quote from a transfer could already be done. That the transaction object will be sent in the open in the future has already been agreed in mojaloop/mojaloop-specification#13. I would appreciate if I'm notified in the future if there is anything that we need to discuss in more detail, instead of just referring to me. It is not my purpose to hold up PISP progress, but I would also like to avoid making immediate changes in the FSPIOP API that are not really needed. It would be great if you could explain in more detail in mojaloop/mojaloop-specification#68 why these changes are needed. Kind regards, |
Hi All, Regarding this issue, I think we have a resolution for either FSPIOP API v1.1 or v2.0:
@ehenrka apologies for not updating mojaloop/mojaloop-specification#68 earlier, but I assure you it's on my list of things to do. I want to make sure I have all my ducks in a row so I'm not wasting anyone's time going around in circles. |
Thanks for the update @lewisdaly! I just want to make sure that you (not you personally, you as in PISP) to see the CCB as holding up your progress. For me, an important function of the CCB is to protect existing implementers from "unnecessary" changes as well as allowing new features that are well aligned with the existing API. As long as you can explain why something is needed, and that it cannot be done in a proper way in the existing API, and that it aligns well with the existing API, then I'm happy to approve changes. |
There is a need to clarify some details in the process of transaction authorization agreement phase described here:
https://github.com/mojaloop/pisp/blob/master/docs/out/transfer/api_calls_detailed/PISPTransferDetailedAPI-page2.png
quote
object to be signed by UserauthenticationValue.pinValue
in PUT /authorizationpinValue
and this task is delegated to auth-service via POST/thirdpartyRequests/transactions/{ID}/authorizaiton
endpointchallenge
property where stringifiedquote
object is sent because it is needed for verificationTHE PROBLEM:
quote
object should be stringified before it will be signed and verified by different parties and they have to use the same approach elsewhere verification will always failquote
object - the JSON.stringify isn't safe:JSON.stringify({a:1, b:2}) !== JSON.stringify({b:2, a:1})
PROPOSED SOLUTION:
challenge
string field which will be signed by Userchallenge
on DFSP - with suggestions/requirements that it should contain some info fromquote
- likequote.ilpPacket
for example - or even better salty hashedquote.ilpPacket
where salt is only known to DFSPchallenge
in/thirdpartyRequests/transactions/{ID}/authorizaiton
CONS:
PROS:
ANOTHER APPROACH:
quote
object, or its part only, and be sure this algorithm is well implemented in sign/verification stepsThe text was updated successfully, but these errors were encountered: