Search code examples
android.netcryptographyin-app-purchase

Android in-app billing Verification of Receipt in Dot Net(C#)


I have a Android application which provides in-app billing and we have our application server to which android application connects to provide services to the user, on in-app purchase we want to push receipt to the server for verification process.

Now problem is I don't know how to convert Security.java file in dot net(C#) as our server is written in dot net

NOTE: This file comes with android in-app billing same application which provides message signing functions i just need their equivalent in dot net.

More Detail regarding this problem is available at http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/66bb5683-fde6-47ca-92d7-de255cc8655a


Solution

  • I found the solution, to achieve you first have to convert the public key format as dot net uses sort of different Key as an input.

    I don't know the other ways but we can get dot net format key using a java Code which you have to run only once to generate the dot net friendly RSA Public Key. (this is only recommended when the given public do not changes rapidly e.g. in case of Android market in-app billing)

    following Java Code worked for me

    public static DotNetRSA GenerateDotNetKey(String base64PubKey)
                throws IOException, NoSuchAlgorithmException,
                InvalidKeySpecException {
            /*
             * String base64PubKey - 
             * Is a Key retrieved from Google Checkout Merchant Account
             */
            BASE64Decoder decoder = new BASE64Decoder();
    
            byte[] publicKeyBytes = decoder.decodeBuffer(base64PubKey);
    
            EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
            RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
    
            byte[] modulusBytes = publicKey.getModulus().toByteArray();
            byte[] exponentBytes = publicKey.getPublicExponent().toByteArray();
    
            modulusBytes = stripLeadingZeros(modulusBytes);
    
            BASE64Encoder encoder = new BASE64Encoder();
            String modulusB64 = encoder.encode(modulusBytes);
            String exponentB64 = encoder.encode(exponentBytes);
    
            return new DotNetRSA(modulusB64, exponentB64);
        }
    
          private static byte[] stripLeadingZeros(byte[] a) {
            int lastZero = -1;
            for (int i = 0; i < a.length; i++) {
              if (a[i] == 0) {
                lastZero = i;
              }
              else {
                break;
              }
            }
            lastZero++;
            byte[] result = new byte[a.length - lastZero];
            System.arraycopy(a, lastZero, result, 0, result.length);
            return result;
          }
    

    Now to verify the Digital Signature you can use the following code in your dot net program(c#) provided GCHO_PUB_KEY_EXP is your Exponent and GCHO_PUB_KEY_MOD is your Modulus extracted by above Java Code

    public static bool VerifyDataSingature(string data, string sign)
    {
         using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
         {
             RSAParameters rsaKeyInfo = new RSAParameters() 
             { 
                 Exponent = Convert.FromBase64String(GCHO_PUB_KEY_EXP), 
                 Modulus = Convert.FromBase64String(GCHO_PUB_KEY_MOD) 
             };
             rsa.ImportParameters(rsaKeyInfo);
    
             return rsa.VerifyData(Encoding.ASCII.GetBytes(data), 
                                   "SHA1", 
                                   Convert.FromBase64String(sign));
         }
    }
    

    I hope it will work for everyone as worked for me. Thanks

    Credit Goes to Code Project Artical