libgdx/gdx-pay

Missing data signature in Google Billing

compbatant opened this issue · 4 comments

Hi,
Correct me if I am wrong but I think this line:
transaction.setTransactionDataSignature(purchase.getSignature());

is missing in following method:
PurchaseManagerGoogleBilling.handlePurchase()

That's correct, the line is missing. There are some other issues for googleplay implementation unresolved, so that's apparently not the right place to look for a solution.

As I am not doing server-side verification, I don't know for sure if this line is needed or if there is even more information needed and every implementation would be a shot in the dark, so it is better if this is done by someone who really uses the feature.

Only TransactionDataSignature and TransactionData is needed for purchase veryfication.

in PurchaseVerifierAndroidGoogle add this:

private PublicKey publicKey;

public void setPublicKey(String publicKeyString) {
       KeyFactory keyFactory = KeyFactory.getInstance("RSA");
       X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.decode(publicKeyString));
       publicKey = keyFactory.generatePublic(publicKeySpec);
}

@Override
public boolean isValid (Transaction transaction) {
        return Security.verify(publicKey, transaction.getTransactionData(), getTransactionDataSignature());

}

And here is Security class:

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;


public class Security {

	private static final String KEY_FACTORY_ALGORITHM = "RSA";
	private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";


	/**
	 * 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) {
		Signature sig;
		try {
			sig = Signature.getInstance(SIGNATURE_ALGORITHM);
			sig.initVerify(publicKey);
			sig.update(signedData.getBytes());
			byte[] decodedSig = Base64.decode(signature);
			if (!sig.verify(decodedSig)) {
				// logger.error("Signature verification failed.");
				return false;
			}
			return true;
		} catch (SignatureException e) {

		} catch (Exception e) {
			//L.error(Security.class, "exception", e);
		}
		return false;
	}

}

I am using it and it is working. Replace Base64 in my Security class with Base64Util from com.badlogic.gdx.pay.server.util;

Thank you. I've added the code, please also check it. It is published in the 0.12.0-SNAPSHOT.

Closing because no reaction.