Skip to content

Instantly share code, notes, and snippets.

@nanom1t
Forked from mkorszunsands/SignatureVerifier.java
Created August 23, 2018 08:40
Show Gist options
  • Select an option

  • Save nanom1t/e2deb23374d2029a16f1b2f883c345b2 to your computer and use it in GitHub Desktop.

Select an option

Save nanom1t/e2deb23374d2029a16f1b2f883c345b2 to your computer and use it in GitHub Desktop.
Verify Google Play in-app purchase signatures
import sun.misc.BASE64Decoder;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
/**
* Signature verifier
*/
public class SignatureVerifier {
/**
* @param key Base64 encoded public key
* @param signature Base64 encoded signature
* @param data Signed data
*/
public boolean verify(String key, String signature, String data) throws Exception {
return verify("SHA1withRSA", key, signature, data);
}
/**
* @param algorithm Signature hashing algorithm
* @param key Base64 encoded public key
* @param signature Base64 encoded signature
* @param data Signed data
*/
public boolean verify(String algorithm, String key, String signature, String data) throws Exception {
Signature sig = Signature.getInstance(algorithm);
sig.initVerify(getKey(key));
sig.update(data.getBytes());
BASE64Decoder decoder = new BASE64Decoder();
byte[] sigBytes = decoder.decodeBuffer(signature);
return sig.verify(sigBytes);
}
private static PublicKey getKey(String key) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
BASE64Decoder decoder = new BASE64Decoder();
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(decoder.decodeBuffer(key));
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(X509publicKey);
}
// Example - verify Google Play in-app purchase signature
public static void main(String... args) throws Exception {
String key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgVv152mMs3kn+uvEfU1gbhf0/CcAMhInr3wvS+E4SEaDS/SLtvzeC/XQdoHRLUnOW5Q40074eL7sL0WvKG4fEpnTD4aP85HwkoYNPzW7o2h7TwpxH46pmsCZ4p3rPRNBaNObe/6aKZ9IxrTsy/pUhN5X3sD3wAbXLsCYqbNrJY1VHaoqCWFucvn7VW6GXLLojWFZnprMlTtsdHMwGeHrkJfUOOE1ArQJaVbSCzDjpnuOGh3kZGRCklLXtKk3CTzzrNFT9ONR0BftrB3VviId28HcakZ7bv4DkiRGSTz6+SmYS9UMA6xUoBW3jj7+fNWUMeZ3ds1bFiMtApr7ykw73wIDAQAB";
String signature = "DefUPOQ2/c3LwySfk+fdczZefijWQ+eZKzOOM3bIH2+Dz+XgNUtoUe4A4logwZKKkduIJthAxuKbf5JeCspTQI8yLCBYRU0LBv4vjINNRpjY/vCeXUaFeQd5Sd1iw186pw7vvsUoSdrIdVlf2BaARJ5M2hO8SmeZRBFxaZOlN5Ud8rRNxFQOkMXxDtwY+6ihYViLDKjY4Ej1wi7pFTPPRz9R7I9APGT9UJQ/M47DWqd3bZMlZ84TPSntRXb/Qf0QUswS9fV36pQCFKwFfIXEmnF1hQfIxMTRyyMKOw7SqPT8xazexDGy9mcxaOzskeC0OZL2E4jfTnQSoMY/woCIKg==";
String data = "{\"packageName\":\"com.topdox.android.trivialdrivesample2\",\"productId\":\"topdox_android_monthly_subscription\",\"purchaseTime\":1456139019030,\"purchaseState\":0,\"purchaseToken\":\"edgcacfhmkpekcilnihgdjkb.AO-J1OxnZr_-c4xGioV-wbb9YI4w7gtRzY87CRLsa6CrHuP_nF97WNzHaBjbqCyZeYYf_sZByLD1DKxkMOFlpIsiOJnSeHxu5XIwa303DbJwFQ7Lo-sM6dgY4-4DCEqk61C9qgUx0GsLaOMZJF0zMC0mRS9K8Z2P3-uSDQpUv0qorTGt7xQC42s\",\"autoRenewing\":true}";
System.out.println("Verified: " + new SignatureVerifier().verify(key, signature, data));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment