Get certificate fingerprint from android app
Asked Answered
D

2

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.

Donation answered 15/2, 2012 at 12:4 Comment(1)
android.content.pm.Signature#getPublicKey()Cepheus
F
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();
}
Festoonery answered 19/3, 2014 at 12:40 Comment(4)
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)Pasha
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.Festoonery
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().Giacobo
Is it still relevant above VERSION_CODES.P? you need to get the GET_SIGNING_CERTIFICATESStreak
D
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();
            } 

    }
}
Donation answered 15/2, 2012 at 13:36 Comment(4)
You might want to look into application licensing. Note, it only works if your app is paid.Melodic
My apps are not paid. I've heard about adware apps repacked, modified (changed ad publisher id) and send to market.Donation
is it the signature fingerprint or just the signature? it is different from the one generated by keytool -printcert -file sign.rsaClown
getInstance("SHA1") - fingerprintDonation

© 2022 - 2024 — McMap. All rights reserved.