Protect APK from resigning with different keystore

1.1k views Asked by At

I have just decompile my signed apk using apkTool and resigned new apk with different keystore using the same decomplied class folder. And then tried to install and override the older apk with new apk in my device and it is working fine.

But now I don't want this apk to get resigned with different keystore. If someone resigned it with different keystore then it should not be override with the older one or it should not get installed.

Commands to create new signed apk :

1. java -jar apktool.jar d test.apk
2. java -jar apktool.jar B test
3. keytool -genkey -v -keystore testrelease.keystore -alias testrelease -keyalg RSA -keysize 2048 -validity 10000
4. jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore testrelease.keystore test_1.apk testrelease

Note : Here I am not using playstore to deploy apk I am just doing it in my device directly by sharing apk via mail.

1

There are 1 answers

4
DrHowdyDoo On

I don't think you can prevent your app from resigning. Nothing can be 100% safe. Although you can verify your app's signature at runtime and perform some action when the signature doesn't match the original one. However this verification code can also be removed easily after decompiling the apk.

Use this to verify signature :

try {

    Signature[] arrSignature;
    PackageInfo signatureInfo;
    SigningInfo signingInfo;
    String SIGNATURE = "Your original signature";
    PackageManager packageManager = this.getPackageManager();

    if(Build.VERSION.SDK_INT < 28) {

      signatureInfo = packageManager.getPackageInfo("package name",PackageManager.GET_SIGNATURES);
      arrSignature =  signatureInfo.signatures;

    }else {

      signingInfo = packageManager.getPackageInfo("package name",PackageManager.GET_SIGNING_CERTIFICATES).signingInfo;
      arrSignature = signingInfo.getApkContentsSigners();

    }

    for(Signature sig : arrSignature){
       final byte[] rawCert = sig.toByteArray();
       InputStream certStream = new ByteArrayInputStream(rawCert);

       MessageDigest md5,sha1,hash,sha256;
       md5 = MessageDigest.getInstance("MD5");
       hash = MessageDigest.getInstance("SHA");
       sha1 = MessageDigest.getInstance("SHA1");
       sha256 = MessageDigest.getInstance("SHA256");
       md5.update(rawCert);

       hash.update(rawCert);
       sha1.update(rawCert);
       sha256.update(rawCert);

       String hash_key = new String(Base64.encode(hash.digest(), 0));

       if (SIGNATURE.equals(hash_key)){
               //Valid Signature
       }
       else {
              // Invalid Signature
           }
       }
}catch (CertificateException | NoSuchAlgorithmException | PackageManager.NameNotFoundException e) {
                e.printStackTrace();
         }
 }

You can compare any signature (MD5,SHA1,SHA256) you want , here i just compared the "sha" of the app.