Google 播放结算响应签名验证

Google Play Billing Response Signature verification

我正在开发一个使用应用内购买的 android 应用。用户购买后,Play 商店以 JSON 字符串形式发送响应。该响应看起来像这样(当然,没有编辑敏感信息):

{  
   "type":"android-playstore",
   "id":"<My Application ID>",
   "purchaseToken":"<The Purchase Token>",
   "receipt":{  
      "orderId":"<The Order ID>",
      "packageName":"com.example.skeleton",
      "productId":"credit.basic",
      "purchaseTime":1436546971245,
      "purchaseState":0,
      "purchaseToken":"<The Purchase Token>"
   },
   "signature":"Im27prAnxYwdRoug..."
}

Google Play billing security documentation 表示

Google Play signs the JSON string that contains the response data for a purchase order. Google Play uses the private key that is associated with your application in the Developer Console to create this signature.

我不太擅长加密,但我的理解是 RSA 签名的工作原理是采用要签名的字符串的 SHA1 哈希值,然后使用私钥对其进行加密以生成签名。当要验证字符串的来源时,使用 public 密钥解密签名(证明它是用私钥加密的)并将解密的哈希值与消息的哈希值进行比较,看它们是否比赛。

但是,这里有一个问题。签名本身包含在发送到我的应用程序的 JSON 字符串中。您不能在签名后更改字符串,因此当 Google 说他们 "Sign the JSON string that contains the response data" 时,他们不能表示我收到的整个 JSON 字符串。他们必须签署字符串的某些部分并将签名附加到该部分。我的问题是 我无法弄清楚字符串的哪一部分被签名了。 使用 this question 中描述的签名验证实现我尝试验证 JSON 字符串删除了签名 属性,没有括号,只有收据部分等。为了更好的衡量,我尝试了整个字符串,包括签名。我似乎找不到这个 JSON 字符串的任何部分,可以用我的 public 密钥进行密码验证。是否有我应该使用的字符串的某些部分,或者我只是不明白签名是如何工作的?

正如经常发生的那样,在 Whosebug 上发帖后的 30 分钟内,我就弄明白了。

问题源于我在 PhoneGap 中开发此应用程序,并使用 in-app-purchasing plugin 执行此事务。当插件给我上面的 JSON 字符串时,它有点在骗我。 Google 在一个 JSON 字符串中发送响应数据,在另一个字符串中发送签名,而插件将其包装到上面的单个字符串中。正确的做法是验证'receipt'项,如下所示。

{  
      "orderId":"<The Order ID>",
      "packageName":"com.example.skeleton",
      "productId":"credit.basic",
      "purchaseTime":1436546971245,
      "purchaseState":0,
      "purchaseToken":"<The Purchase Token>"
 }

问题中列出的 python 实现验证此 JSON 字符串的签名。

任何使用java通过public密钥验证google支付签名的人,DO注意: 签名数据是一个 json 字符串 ONLY ONLY ONLY 包含 orderId, packageName, productId, purchaseTime, purchaseState, purchaseToken.

例如: 如果来自 google pay 的响应数据如下:

{
    "nameValuePairs": {
        "orderId": "your.order.id",
        "packageName": "your.package.name",
        "productId": "your.product.id",
        "purchaseTime": 1526476218113,
        "purchaseState": 0,
        "purchaseToken": "your.purchase.token"
    }
}

那么您将检查签名的签名数据是ONLY,如下所示:

{
    "orderId": "your.order.id",
    "packageName": "your.package.name",
    "productId": "your.product.id",
    "purchaseTime": 1526476218113,
    "purchaseState": 0,
    "purchaseToken": "your.purchase.token"
}

希望本文post对需要的人有所帮助。