What's in signedData parameter of ILicenseResu

2019-07-13 01:23发布

问题:

Google Play on Android has a service for license checks, com.android.vending.licensing.ILicensingService. It supports a callback interface, ILicenseResultListener. It has a method verifyLicense with three parameters. For a paid app that's been downloaded from Google Play, what comes in the second one, signedData, please?

And this is why I'm wondering.

回答1:

The answer is in android-sdk-windows\extras\google\market_licensing\library\src\com\google\android\vending\licensing\ResponseData.java, in the parse() method.

The signedData string is a sequence of 6 fields, separated by |, optionally followed by colon and a &-separated name=value collection (like a query string). For example:

0|17|com.acme.myapp|1|AAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHH==|1480563297411:GR=10&VT=1480570457760&GT=1481088857760

This one comes from a paid app.

The 6 fields in the first section are:

  • Response code (int) - presumably the same as the verifyLicense's first parameter
  • Nonce (int) - comes straight from the checkLicense call
  • Package name
  • Version code
  • User ID, with a comment "Application-specific user identifier"
  • Timestamp (long) - not sure of what. Definitely not purchase; repeat runs return a different, later value. Probably that of license check itself.

UserID seems to be a Base64-encoded string. Which user does it identify, and how? The license holder, one presumes; but how? Decoding gives a byte array, 25 bytes long.

For a sideloaded app, the basic fields is all there is. For a store bought app, there's extra data. The meaning of extra data fields can be found here. Specifically, with a freshly bought app, the following extra fields come:

  • GR - max retry count
  • VT - license validity timestamp; specifies when the license needs to be rechecked
  • GT - grace period timestamp

Regarding UserID, I did some tests. I have three cases:

  • Package A, side-loaded
  • Package A, downloaded for a fee from Play
  • Package B, downloaded for free from Play (by the same user)

In all three cases, the first 5 bytes of the decoded UserID match, the rest don't. So neither the package unique part nor the user unique part can be easily identified in the UserID. Notably, the remainder is 20 bytes long - could be an MD5 hash. The UserID definitely isn't a string in any sensible encoding, and it doesn't look like a structure with binary integers, either. The seemingly random bit pattern points at either a hash, or a cyphertext. The latter is unlikely.