Question

YES, I've read all the docs @ developer.android.com and I do understand it all with one basic exception - what it was introduced for.

Since all order responses from Google Play come signed by inaccessible-by-anyone private key and are being verified by paired public key (in my case on external server, so it is also inaccessible for third person) there's simply (almost) no way to spoof.

All those nonces are just redundant way of securing the purchases. And what's more, the docs say nothing about the situation, when:

  1. I purchase an item;
  2. Generate nonce and send it to Google Play;
  3. Have a crash, so all my known nonces are lost;
  4. Have my app restarted and got callback from Google Play;
  5. ...And reject this call due to having not recognized nonce!

In described above situation user pays for an item and never gets it, what it's shameful. Of course I can store nonces in some file and re-read it when my app gets back, but it violates all the principles for nonces.

IMHO someone just said "Hey, the verification process is too simple, let's add something more with randomness, it's gonna be way more cool!". So someone did.

Or, would you open my mind to some other use-case am I missing? Otherwise I'm removing whole nonces part from my code.

Was it helpful?

Solution

You don't need to store the nonce 'to disk' to account for an app crash.

When your app crashes yes you will lose your list of known nonces. However when your app restarts and you receive an IN_APP_NOTIFY you then have to do another GET_PURCHASE_INFORMATION when you do this GET_PURCHASE_INFORMATION you will generate a new nonce and add it to the list known nonces.

What you have to remember is the nonce is one per GET_PURCHASE_INFORMATION (which returns you multiple purchased items) not one nonce per item that is bought.

AS you've said you've implemented your own way to avoid Replay Attacks, but using a nonce is once such secure method

OTHER TIPS

You should be saving the generated nonces before sending them. Android apps can crash or be shut down at any point so in general everything should be saved.

The reason for using nonces is to prevent replay attacks. I´m far from qualified to answer whether to using the nonce is neccesary or not but I assume it's there for a reason.

Imagine your user purchases an item for lets say $100. Your app is notified that there is payment data available, the app requests the data and the AppStore answers with a PURCHASE_STATE_CHANGED. The user records the message (!) from the AppStore and keeps it save.

Later, the user fakes a notification to your app, telling it that payment data is available (anyone can fake that, as this notification is not signed). The app thinks "oh, hey, maybe I just crashed and lost all information about a purchase that my user just made!? Let's see what the AppStore has to say". So it requests data from the app store. The user interrupts that request and sends the previously recorded message to your app. The app sees the message, verifies it and finds that it is valid (because it's signed and all). So the app will give you another valuable $100 item. And another. As often as the user replays the recorded message. Therefore called: a replay attack.

There is however one thing that prevents such an attack: the nonce. If your app sends a nonce in its request for payment data, it expects to receive that same nonce in the PURCHASE_STATE_CHANGED reply. As a nonce is only used once, you can't replay previously recorded messages, because they won't match with the nonce that was used in the request.

"The nonce acts like a salt on the transaction, similar to how *nix systems store passwords. The nonce is used to add entropy to the value that is encrypted with your key, largely eliminating the chance that two transactions are encrypted and result in the same signature, and other similar cryptographic attacks."

see the answer by queso

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top