37

How to get app certificate's fingerprint from inside of this app? I want to check if application is singed with my own certificate or if it was repacked / hacked.

I found part of solution here: Get Certificate from Android Application. So question now is: how to check certificate's fingerprint.

piotrpo
  • 12,398
  • 7
  • 42
  • 58
  • [`android.content.pm.Signature#getPublicKey()`](https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-11.0.0_r1/core/java/android/content/pm/Signature.java#220) – Irfan Latif Sep 05 '21 at 12:04

2 Answers2

92

I put it here - the function gives the same result as keytool does it.

private String getCertificateSHA1Fingerprint() {
    PackageManager pm = mContext.getPackageManager();
    String packageName = mContext.getPackageName();
    int flags = PackageManager.GET_SIGNATURES;
    PackageInfo packageInfo = null;
    try {
        packageInfo = pm.getPackageInfo(packageName, flags);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    Signature[] signatures = packageInfo.signatures;
    byte[] cert = signatures[0].toByteArray();
    InputStream input = new ByteArrayInputStream(cert);
    CertificateFactory cf = null;
    try {
        cf = CertificateFactory.getInstance("X509");
    } catch (CertificateException e) {
        e.printStackTrace();
    }
    X509Certificate c = null;
    try {
        c = (X509Certificate) cf.generateCertificate(input);
    } catch (CertificateException e) {
        e.printStackTrace();
    }
    String hexString = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA1");
        byte[] publicKey = md.digest(c.getEncoded());
        hexString = byte2HexFormatted(publicKey);
    } catch (NoSuchAlgorithmException e1) {
        e1.printStackTrace();
    } catch (CertificateEncodingException e) {
        e.printStackTrace();
    }
    return hexString;
}

public static String byte2HexFormatted(byte[] arr) {
    StringBuilder str = new StringBuilder(arr.length * 2);
    for (int i = 0; i < arr.length; i++) {
        String h = Integer.toHexString(arr[i]);
        int l = h.length();
        if (l == 1) h = "0" + h;
        if (l > 2) h = h.substring(l - 2, l);
        str.append(h.toUpperCase());
        if (i < (arr.length - 1)) str.append(':');
    }
    return str.toString();
}
Community
  • 1
  • 1
matreshkin
  • 2,199
  • 18
  • 28
  • 1
    Hi, its working with debug kestore. But getting this error when used with signed apk java.lang.NoSuchMethodError: No static method setTimeout(Le/a/b/c/d;J)V in class Lorg/apache/http/conn/params/ConnManagerParams; or its super classes (declaration of 'org.apache.http.conn.params.ConnManagerParams' appears in /system/framework/ext.jar) – arjunkn Mar 19 '16 at 11:00
  • 4
    I don't think this error is related to a keystore. Probably another piece of code in your app causes this Exception. Check the function in an empty project with your keystore - this should work. – matreshkin Mar 20 '16 at 13:00
  • 1
    The resulting `byte[]` value of `signatures[0].toByteArray()` is the same as the value of `c.getEncoded()`. It seems it is possible to skip the part of certificate creation and make the SHA hash directly from `signatures[0].toByteArray()`. – petrsyn Feb 20 '18 at 15:16
  • Is it still relevant above VERSION_CODES.P? you need to get the GET_SIGNING_CERTIFICATES – motis10 Jun 30 '22 at 16:21
11

Sorry, I was faster below my solution, thanks for your time;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            PackageManager pm = this.getPackageManager();
            String packageName = this.getPackageName();
            int flags = PackageManager.GET_SIGNATURES;

            PackageInfo packageInfo = null;

            try {
                    packageInfo = pm.getPackageInfo(packageName, flags);
            } catch (NameNotFoundException e) {
                    e.printStackTrace();
            }
            Signature[] signatures = packageInfo.signatures;

            byte[] cert = signatures[0].toByteArray();

            InputStream input = new ByteArrayInputStream(cert);

            CertificateFactory cf = null;
            try {
                    cf = CertificateFactory.getInstance("X509");


            } catch (CertificateException e) {
                    e.printStackTrace();
            }
            X509Certificate c = null;
            try {
                    c = (X509Certificate) cf.generateCertificate(input);
            } catch (CertificateException e) {
                    e.printStackTrace();
            }


            try {
                MessageDigest md = MessageDigest.getInstance("SHA1");
                byte[] publicKey = md.digest(c.getPublicKey().getEncoded());


                StringBuffer hexString = new StringBuffer();
                for (int i=0;i<publicKey.length;i++) {
                    String appendString = Integer.toHexString(0xFF & publicKey[i]);
                    if(appendString.length()==1)hexString.append("0");
                    hexString.append(appendString);
                    }


                Log.d("Example", "Cer: "+ hexString.toString());

            } catch (NoSuchAlgorithmException e1) {
                e1.printStackTrace();
            } 

    }
}
piotrpo
  • 12,398
  • 7
  • 42
  • 58
  • You might want to look into [application licensing](http://developer.android.com/guide/publishing/licensing.html). Note, it only works if your app is paid. – Felix Feb 15 '12 at 13:44
  • My apps are not paid. I've heard about adware apps repacked, modified (changed ad publisher id) and send to market. – piotrpo Feb 15 '12 at 13:52
  • is it the signature fingerprint or just the signature? it is different from the one generated by `keytool -printcert -file sign.rsa` – Zennichimaro Jul 14 '14 at 02:30
  • getInstance("SHA1") - fingerprint – piotrpo Jul 14 '14 at 10:33