Android in-app billing verification

2019-04-06 13:19发布

问题:

If I offload verification to a remote server, I think the process will be something like:

Android Market                  Application     Remote Server
       |--------IN_APP_NOTIFY------->|                |
       |                             |-----nonce----->|
       |                             |<----nonce------|
       |<-GET_PURCHASE_STATE_CHANGED-|                |
       |---PURCHASE_STATE_CHANGED--->|                |
       |                             |--verification->|
       |                             |<-verification--|

If I understand correctly, the nonce is to reduce replay attack vulnerability and the verification is to reduce spoofing vulnerability. Also, the reason the docs recommend offloading security processing is that the verification step requires access to my public Android Market publisher's key and the goal of the remote server is to keep said key from needing to be included/computed in my code.

First question, is there a security reason for the remote server to do the nonce generation/check? Pressuming the verification step is done correctly, we'd find out from the remote server if the message was spoofed. So it seems to me that the nonce is just there to detect someone rebroadcasting the IN_APP_NOTIFY.

Second question, why does it matter if our public key is a literal string? The docs say, "you do not want to make it easy for a hacker or malicious user to replace the public key with another key." I'm not clear how someone could exploit my app even if they could edit the binary to include a malicious public key without having to resign the app.

Third question, won't I have all these same problems trying to verify the verification from my remote server (e.g. storing public key to my remote server in the application)?

Fourth question, is all of this extra security for naught if I want to store the results of this purchase verification on the phone (i.e. I don't want to have to verify the purchase state of the unlocked content whenever a user accesses the content)?

回答1:

First question, is there a security reason for the remote server to do the nonce generation/check?

Yes, the server should generate the nonce, and do the check. As a general rule, everything security-related should almost allways be done in the server. A nonce is a "number only used once". So, the correct thing for the server is to:

  1. generate and save a nonce.
  2. receive an answer.
    • if the answer contains a saved nonce, check the signature and process it. ERASE THE NONCE.
    • if the answer contains an unsaved nonce, it is most probably a fabricated/replicated one, so discard.

Second question, why does it matter if our public key is a literal string?

A little if you perform security checks on the aplication, completly irrelevant if you do your work on a server (as you should).

If you perform security in the aplication, then the aplication can be hacked to bypass the security. One technique is to change the public key, wich is easier if it is saved as a single string.

Third question, won't I have all these same problems trying to verify the verification from my remote server (e.g. storing public key to my remote server in the application)?

No you won't. No one can access/change the code of the server. At least as "easy" as the can in the aplication.

Fourth question, is all of this extra security for naught if I want to store the results of this purchase verification on the phone (i.e. I don't want to have to verify the purchase state of the unlocked content whenever a user accesses the content)?

Well, it depends.

The "securest" way to implement in-app purchases having a server implies:

  • you save your "purchasable" content in the server. If a user buys it, you download it to the aplication, and you save it in some way hard to "copy" to another phone.
  • from the server, only send content if the verification process is done correctly IN THE SERVER.
  • from the aplication, if you detect no "saved" content, perform a "restore transactions" operation, and then download everything you need from the server.
  • google play's in-app purchases are not designed to provide content easily, it is designed to perform purchases from a centralised site and so, easyer for the user. We developers end up with a LOT of work to use it.