我正在开发一款使用应用内购买的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会签署包含采购订单响应数据的JSON字符串。 Google Play使用与开发者控制台中的应用程序关联的私钥来创建此签名。
我对加密不是很好,但我的理解是RSA签名的工作原理是将字符串的SHA1哈希值签名,然后使用私钥加密以产生签名。当想要验证字符串的来源时,使用公钥解密签名(证明它是使用私钥加密的),并将解密的散列与消息的散列进行比较,以查看它们是否匹配。
然而,这里有一个问题。签名本身包含在发送到我的应用程序的JSON字符串中。您无法在签名后更改字符串,因此当Google表示他们“签署包含响应数据的JSON字符串”时,他们并不意味着我收到的整个JSON字符串。他们必须签署字符串的某些部分并将签名附加到该字符串。我的问题是我无法弄清楚该字符串的哪个部分已签名。使用this question中描述的签名验证实现我尝试删除了删除了签名属性的JSON字符串,括号,只有收据部分等。为了好的措施,我尝试了整个字符串,包括签名。我似乎无法找到可以使用我的公钥进行加密验证的此JSON字符串的任何部分。是否有我应该使用的字符串的一部分,或者我只是不明白签名是如何工作的?
答案 0 :(得分:2)
对于使用java通过公钥验证Google付费签名的任何人, DO 会注意:
签名数据是json字符串仅 仅 仅包含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"
}
}
然后,您将检查签名的签名数据是仅,如下所示:
{
"orderId": "your.order.id",
"packageName": "your.package.name",
"productId": "your.product.id",
"purchaseTime": 1526476218113,
"purchaseState": 0,
"purchaseToken": "your.purchase.token"
}
希望这篇文章对任何需要它的人都有所帮助。
答案 1 :(得分:0)
正如经常发生的那样,在StackOverflow上发布的30分钟内,我发现了它。
问题源于我在PhoneGap中开发此应用程序并使用in-app-purchasing plugin执行此事务的事实。当它给我上面的JSON字符串时,该插件对我有点说谎。 Google将响应数据发送到一个JSON字符串,将签名发送到另一个JSON字符串,而插件将其包装到上面的单个字符串中。正确的方法是验证收据&#39;项目,如下所示。
{
"orderId":"<The Order ID>",
"packageName":"com.example.skeleton",
"productId":"credit.basic",
"purchaseTime":1436546971245,
"purchaseState":0,
"purchaseToken":"<The Purchase Token>"
}
问题中列出的python实现验证了此JSON字符串的签名。