【发布时间】:2018-07-28 23:25:08
【问题描述】:
使用应用内结算时,您应该验证购买数据,方法是检查 INAPP_PURCHASE_DATA 是否使用来自 Google Play 商店的 base64 编码公钥与 INAPP_DATA_SIGNATURE 签署。
请参阅 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 如果我用给定的验证它能够获得有效的安全检查 公钥。
[更新]。显然,私钥是隐藏的:
Google Play 管理中心会向任何登录到 Play 管理中心的开发者公开用于许可的公钥,但它会将私钥隐藏在安全位置对所有用户隐藏。
见:https://developer.android.com/google/play/licensing/adding-licensing.html
【问题讨论】:
标签: android google-play in-app-purchase in-app-billing android-billing