Verifying signature on android in-app purchase message in Python on Google App Engine
Question: The sample application on the android developers site validates the purchase
json using java code. Has anybody had any luck working out how to validate the
purchase in python. In particular in GAE?

The following are the relevant excerpts from the android in-app billing
[example
program](http://developer.android.com/guide/market/billing/billing_integrate.html#billing-
download). This is what would need to be converted to python using
[PyCrypto](http://www.dlitz.net/software/pycrypto/) which was re-written to be
completely python by Google and is the only Security lib available on app
engine. Hopefully Google is cool with me using the excerpts below.

    
    
    private static final String KEY_FACTORY_ALGORITHM = "RSA";
    private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    String base64EncodedPublicKey = "your public key here";
    
    PublicKey key = Security.generatePublicKey(base64EncodedPublicKey);
    verified = Security.verify(key, signedData, signature);
    
    public static PublicKey generatePublicKey(String encodedPublicKey) {
        try {
            byte[] decodedKey = Base64.decode(encodedPublicKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
            return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
        } catch ...
        }
    }
    public static boolean verify(PublicKey publicKey, String signedData, String signature) {
        if (Consts.DEBUG) {
            Log.i(TAG, "signature: " + signature);
        }
        Signature sig;
        try {
            sig = Signature.getInstance(SIGNATURE_ALGORITHM);
            sig.initVerify(publicKey);
            sig.update(signedData.getBytes());
            if (!sig.verify(Base64.decode(signature))) {
                Log.e(TAG, "Signature verification failed.");
                return false;
            }
            return true;
        } catch ...
        }
        return false;
    }
    


Answer: Here's how i did it:

    
    
    from Crypto.Hash import SHA
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    from base64 import b64decode
    
    def chunks(s, n):
        for start in range(0, len(s), n):
            yield s[start:start+n]
    
    def pem_format(key):
        return '\n'.join([
            '-----BEGIN PUBLIC KEY-----',
            '\n'.join(chunks(key, 64)),
            '-----END PUBLIC KEY-----'
        ])
    
    def validate_purchase(publicKey, signedData, signature):
        key = RSA.importKey(pem_format(publicKey))
        verifier = PKCS1_v1_5.new(key)
        data = SHA.new(signedData)
        sig = b64decode(signature)
        return verifier.verify(data, sig)
    

This assumes that `publicKey` is your base64 encoded Google Play Store key on
one line as you get it from the Developer Console.

For people who rather use m2crypto, `validate_purchase()` would change to:

    
    
    from M2Crypto import RSA, BIO, EVP
    from base64 import b64decode
    
    # pem_format() as above
    
    def validate_purchase(publicKey, signedData, signature):
        bio = BIO.MemoryBuffer(pem_format(publicKey))
        rsa = RSA.load_pub_key_bio(bio)
        key = EVP.PKey()
        key.assign_rsa(rsa)
        key.verify_init()
        key.verify_update(signedData)
        return key.verify_final(b64decode(signature)) == 1
    

