- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用应用内结算时,您应该通过使用来自 Google Play 商店的 base64 编码公钥检查 INAPP_PURCHASE_DATA 是否使用 INAPP_DATA_SIGNATURE 对 INAPP_PURCHASE_DATA 进行签名来验证购买数据。
看INAPP_PURCHASE_DATA和INAPP_DATA_SIGNATURE的解释here .有一个Security class您可以用来验证购买:
public class Security {
private static final String TAG = "IABUtil/Security";
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/**
* Verifies that the data was signed with the given signature, and returns
* the verified purchase. The data is in JSON format and signed
* with a private key. The data also contains the {@link PurchaseState}
* and product ID of the purchase.
* @param base64PublicKey the base64-encoded public key to use for verifying.
* @param signedData the signed JSON string (signed, not encrypted)
* @param signature the signature for the data, signed with the private key
*/
public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||
TextUtils.isEmpty(signature)) {
Log.e(TAG, "Purchase verification failed: missing data.");
return false;
}
PublicKey key = Security.generatePublicKey(base64PublicKey);
return Security.verify(key, signedData, signature);
}
/**
* Generates a PublicKey instance from a string containing the
* Base64-encoded public key.
*
* @param encodedPublicKey Base64-encoded public key
* @throws IllegalArgumentException if encodedPublicKey is invalid
*/
public static PublicKey generatePublicKey(String encodedPublicKey) {
try {
byte[] decodedKey = Base64.decode(encodedPublicKey, Base64.DEFAULT);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeySpecException e) {
Log.e(TAG, "Invalid key specification.");
throw new IllegalArgumentException(e);
}
}
/**
* Verifies that the signature from the server matches the computed
* signature on the data. Returns true if the data is correctly signed.
*
* @param publicKey public key associated with the developer account
* @param signedData signed data from server
* @param signature server signature
* @return true if the data and signature match
*/
public static boolean verify(PublicKey publicKey, String signedData, String signature) {
byte[] signatureBytes;
try {
signatureBytes = Base64.decode(signature, Base64.DEFAULT);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Base64 decoding failed.");
return false;
}
try {
Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
sig.initVerify(publicKey);
sig.update(signedData.getBytes());
if (!sig.verify(signatureBytes)) {
Log.e(TAG, "Signature verification failed.");
return false;
}
return true;
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "NoSuchAlgorithmException.");
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key specification.");
} catch (SignatureException e) {
Log.e(TAG, "Signature exception.");
}
return false;
}
}
您必须调用 verifyPurchase
并传递购买数据、给定的签名和来自 Google Play 的 base64PublicKey 公钥。有一个wrapper implementation我可以在我的应用程序中使用购买流程。
如果你查看 IabHelper实现时,他们在构造函数中传递用于验证的公钥。 ctor 的文档说:
* @param base64PublicKey Your application's public key, encoded in base64.
* This is used for verification of purchase signatures. You can find your app's base64-encoded
* public key in your application's page on Google Play Developer Console. Note that this
* is NOT your "developer public key".
*/
我猜他们指的是 Google Play 中许可和应用内结算部分中的 Base64 编码 RSA 公钥:
也许我对密码学了解不够,但我怎么可能使用 Google Play 的公钥来检查据称是用我的“开发者私钥”进行的加密(请参阅第一个链接中的解释)。他们是指我的“我用来签署应用程序的私钥”吗?我不这么认为,因为他们不知道我的(本地)私钥(我用来签署我的应用程序)以及它与来自 Google Play 的这个公钥有什么关系,所以他们对“开发者的私钥”意味着什么".
所以我的问题是:
公钥是来自许可和应用内结算?
我还需要add licensing to my app吗得到这个验证工作或者这项工作应该“开箱即用”,我也可以省略这一步?
Google 用来签署购买数据,我在哪里可以看到它? (我需要运行一些单元测试在我的服务器上检查我的实现,我想加密INAPP_PURCHASE_DATA 获取 INAPP_DATA_SIGNATURE 以及如果我用给定的验证它,能够得到有效的安全检查公钥。
[更新]。显然,私钥是隐藏的:
The Google Play Console exposes the public key for licensing to any developer signed in to the Play Console, but it keeps the private key hidden from all users in a secure location.
参见:https://developer.android.com/google/play/licensing/adding-licensing.html
最佳答案
签名有非对称和对称两种:
Asymm 使用一对 key ,私钥和公钥, key 之间存在数学关系,用私钥签名的数据 block 可以用公钥验证。私钥永远不会发布,但公钥会发布。
然后 Google 为您的应用内结算创建了一对 key ……但您只需要知道公众即可验证。没有私钥,任何主体都不会生成有效签名。
相反,Symm 在两侧使用相同的 key ,这带来了共享 key 的问题和被嗅探的风险,但它具有比 asymm 更快的优势。
更新
Do I also need to add licensing to my app to get this verification working or should this work "out of the box", so can I omit this step?
视情况而定,如果您想知道该应用是否是从官方 Google Play 商店安装的,那么您需要验证许可,如果您的应用是付费应用,则更适用,如果您的应用是免费的,但它有 -应用程序产品重要的是要知道他们是否合法购买了该项目。
对我来说更重要的是在外部服务器上验证购买,你有一个很好的例子https://stackoverflow.com/a/48645216/7690376
关于android - 应用内结算 : Which public and private keys are used for the in-app billing verification?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48854098/
我收到一封来自 Google 的邮件,其中提到“我们将终止对应用内结算第 2 版 API 的支持。在此日期之后,用户将无法再使用您的应用程序进行应用程序内购买,直到您将您的应用程序升级为使用第 3 版
假设我有类似 GATES, Bill.jpg 的文件我想将它们全部重命名为 Bill Gates.jpg .我能捕捉到这两个词 rename 's/^(.*?), (.*?)\./$2 $1\./g'
我的 google play 计费有问题。我有一个 android 应用程序,其中包含应用程序内购买。我维护 SharedPreference 以购买应用程序状态。如果谷歌将购买状态设为成功,那么我会
我正在尝试关注 In-App Billing tutorial on the Android Developer site .我准备提出应用内结算请求。我应该将代码添加到我的项目中: ArrayLis
我是 android 的新手,第一次尝试实现应用内结算。 我正在使用 google play 应用内库。 https://developer.android.com/google/play/billi
在我的应用中设置应用内购买时,我发现有两个与计费相关的权限: 这两种权限有什么区别?似乎大多数在线人都说使用第一个进行应用内购买,但第二个需要什么? 最佳答案 作为引用,如果您已迁移到 Billi
我遇到了应用内结算库(使用 BillingClient )和应用内结算 API(使用 IInAppBillingService )都用于管理订阅,我的问题是在什么情况下必须使用哪个。 我正在使用 In
我正在尝试使用应用内结算: mIabHelper = new IabHelper(this, BILLING_KEY); mIabHelper.startSetup(new IabHe
我已经开设了一个新的谷歌云帐户,我即将在其上设置一个虚拟机。在此之前,我想创建一个存储桶,我将从一个存储桶复制到另一个存储桶。 我能够创建一个存储桶,在复制时我面临如下问题: AccessDenied
我知道“Google Play Billing with AIDL”已弃用,但我正在使用的应用程序非常复杂,我不想更改应用程序的核心部分。 在游戏控制台上,我收到以下消息:- “我们检测到您的应用使用
我已经检查了我的项目,它有一个活跃的 billing account 我正在使用 Node.js var gcloud = require('gcloud'); var gcs = gcloud
我正在开发一个 Firebase Cloud Function,它从存储在 Firebase 存储中的文件中收集元数据 我的代码大致是这样的: const { Storage } = require(
将 billingclient 升级到 2.1.0 时: implementation 'com.android.billingclient:billing:2.1.0'//from 2.0.1 我的
我想知道为什么prometheus不适合计费系统。 普罗米修斯概述页面说 If you need 100% accuracy, such as for per-request billing, Pro
我写了一个基于订阅的网络应用程序,我想(通过信用卡)按月收费。有 3 种不同的计划,一旦他们注册,就应该每月自动向他们收取该金额,直到他们取消为止。有没有一种简单的方法来设置它(可能是某种在线服务?)
我正在尝试使用 'com.android.billingclient:billing:2.0.3' 库实现应用内购买。 该应用在内部测试轨道中发布,并且有一个托管产品和一个测试人员(我的另一个帐户),
BillingClient queryPurchases 方法的谷歌文档说明如下: “出于安全考虑,建议通过调用以下 API 在您的后端(如果有的话)进行购买验证:https://developers
我正在研究使用 google play 在应用计费中实现自动续订订阅的方法。我读了 https://developer.android.com/google/play/billing/billing_
我查看了文档 ( https://www.braintreepayments.com/docs/ruby/subscriptions/overview ),但看不到是否可以更改事件订阅的下一个计费日期
我想为我们使用 Braintree 的计费系统添加一些单元测试,但我不知道如何将订阅期从 1 个月(目前在 Braintree 中的最小值)更改为 1 天。我不能等待 1 个月来执行我的测试。有什么解
我是一名优秀的程序员,十分优秀!