Last active
November 7, 2022 19:19
-
-
Save sevaa/73422926e0c9aa0fe905af39c55376bf to your computer and use it in GitHub Desktop.
Hand-checking the digital signature of Android in-app purchase against the Google public key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//The modulus of the IAP public key, as Base64. | |
//The public exponent is 65537, we'll hard-code it. | |
private static final String GMOD = "APXj+9V6Mrp7DwDVLP2yIDhuMiB30R+NQ9JO14jg42S3TcJFhURQZ2RD21GIbp5S7RLy7YDcxOjH765HM7FWUJgJegvL01lYtzFkXv0XRcnL05m5sgTp58i9fYOJt1QKar2k4FI/a6iv7sjT4qGLOcX3drjDx6WKwZdnu6q5rA94rycHoe+BdELsy1eKBp/iI4KIe/Y3WePYfVgynL4mrJOHutf1tvy6WL04zG61yl3PBlwh6uy1K+RBqEXeiznS0ee4Xq3fe3puq6HgEZKw8PQIihxk8odbg1lneqAk51JZ8vuQi9WEZMdvqWK+p4jT+q7mTYQO18NH1MP5y2/fj8k="; | |
//d is the value of the IAP result intent's string extra "INAPP_PURCHASE_DATA" | |
//s is the value of the IAP result intent's string extra "INAPP_DATA_SIGNATURE" | |
private static boolean PowModThenCheck(String d, String c) | |
{ | |
try | |
{ | |
byte []h = MessageDigest.getInstance("SHA1").digest(d.getBytes()); | |
byte [] p = new java.math.BigInteger(1, Util.FromBase64(c)) //Substitute your own FromBase64 function | |
.modPow( | |
java.math.BigInteger.valueOf(65537), | |
new java.math.BigInteger(Util.FromBase64(GMOD)) | |
).toByteArray(); | |
if(p.length != 255 || p[0] != 1) | |
return false; | |
int i; | |
for(i=1;i<219;i++) | |
if(p[i] != -1) | |
return false; | |
final byte []TheOID = new byte[]{0, 0x30, 0x21, 0x30, 9, 6, 5, 0x2B, 0xE, 3, 0x02, 0x1A, 5, 0, 4, 0x14}; | |
for(i=219;i<235;i++) | |
if(p[i] != TheOID[i-219]) | |
return false; | |
for(i=235;i<255;i++) | |
if(p[i] != h[i-235]) | |
return false; | |
return true; | |
} | |
catch(Exception exc) | |
{ | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Companion gist to this blog post. Implements a hand-coded digital signature check on a Google Play in-app purchase. First, the signature is RSA-decoded with a public key (the key that Google publishes), then the result is matched against a well known structure of a SHA1/RSA digital signature, which includes the SHA1 hash of the plaintext.