8

Hello I want to read SHA and MD5 fingerprint value of keystore programmatically of my app from which it was signed.

I'll take either SHA or MD5 value as key for security. This key I will use in the code to encrypt something and decrypt same at server end.

Is there any way to find this or is there any way to do same using different good approach. This should be in such a way nobody other can find this key.

Thanks in advance.

N Sharma
  • 33,489
  • 95
  • 256
  • 444

4 Answers4

11
PackageInfo info;
try {

    info = getPackageManager().getPackageInfo(
        "com.your.package.name", PackageManager.GET_SIGNATURES);

    for (Signature signature : info.signatures) {
        MessageDigest md;
        md = MessageDigest.getInstance("SHA");
        md.update(signature.toByteArray());
        String hash_key = new String(Base64.encode(md.digest(), 0));
    }

} catch (NameNotFoundException e1) {
} catch (NoSuchAlgorithmException e) {
} catch (Exception e) {
}
nbaroz
  • 1,795
  • 13
  • 14
5

try this:

/**
 * 
 * @param pkg packageName
 * @return
 */
public String getSingInfo (String pkg) {
    try {
        PackageInfo packageInfo = getPackageManager().getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
        Signature[] signs = packageInfo.signatures;
        Signature sign = signs[0];
        String s = getMd5(sign);
        return "md5:" + s ;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return "";
}



private String getMd5 (Signature signature) {
    return encryptionMD5(signature.toByteArray());
}

public static String encryptionMD5(byte[] byteStr) {
    MessageDigest messageDigest = null;
    StringBuffer md5StrBuff = new StringBuffer();
    try {
        messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.reset();
        messageDigest.update(byteStr);
        byte[] byteArray = messageDigest.digest();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            } else {
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
            }
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return md5StrBuff.toString();
}
NateZh
  • 81
  • 1
  • 3
4
  1. Find the path of your application's APK file by calling Context.getPackageCodePath()
  2. Copy that APK to a writeable directory of your choice
  3. Use apk-parser to get the information you need from the APK (see example below)

That library is able to decompress the APK file and parse all of its content. An example extracted from the apk-parser's Github page, tailored to your needs:

try {
  ApkParser apkParser = new ApkParser(new File(filePath));
  ApkSignStatus signStatus = apkParser.verifyApk(); // not needed
  List<CertificateMeta> certs = apkParser.getCertificateMetas();
  for (CertificateMeta certificateMeta : certs) {
    System.out.println(certificateMeta.getCertMd5());
  }
} catch (Exception e) {
  e.printStackTrace();
}
Sebastiano
  • 12,289
  • 6
  • 47
  • 80
  • 1
    Is this code can help me to get other application like facebook MD5 value of keystore of which it was signed ? – N Sharma Feb 03 '15 at 14:28
  • That would be a security violation. You can only access your application's private directory, not others'. To do that, root privileges are required. – Sebastiano Feb 03 '15 at 14:29
  • Hmm I see. What you meant "Copy that APK to a writeable directory of your choice" ? – N Sharma Feb 03 '15 at 14:45
  • I'm not sure about this, but `apk-parser` might need a writeable directory in order to extract the contents of the APK. So, just copy the APK file to your external storage directory (typically `/sdcard`) and give `apk-parser` that path. – Sebastiano Feb 03 '15 at 14:50
  • Is it possible to parse any application's APK ?? If I sign my APK with some keystore, can I get SHA 1 fingerprint of that certificate of the APK using the above method? – Bharath Feb 08 '15 at 04:43
  • Yes, because the Manifest file is not encrypted, it is only digitally signed. You won't be able to programmatically access other applications' APKs though, as I mentioned in the previous comments. – Sebastiano Feb 08 '15 at 08:20
0

Added below solution in-case if someone is looking for it for the first time, and don't know how to get it from studio as well. Many times we search and get suggestion links. Easiest Way

  1. Open Android Studio
  2. Open Your Project
  3. Click on Gradle (From Right Side Panel, you will see Gradle Bar)
  4. Click on Refresh (Click on Refresh from Gradle Bar, you will see List Gradle scripts of your Project)
  5. Click on Your Project (Your Project Name form List (root))
  6. Click on Tasks
  7. Click on android
  8. Double Click on signingReport (You will get SHA1 and MD5 in Run Bar)

Check Screenshot below:

enter image description here

Tara
  • 2,598
  • 1
  • 21
  • 30
  • 4
    this is not programmatically – Chad Bingham Sep 30 '17 at 23:55
  • I Agree with @Chad Bingham. It is more than a year now. Not only this, the method only deals with the developer keystore, and not the publisher's or any other external keystore. – Abhinav Saxena Oct 03 '18 at 04:31
  • Although it is not programmatically, but solved my problem in a few clicks! Also if you have already added release keys in your build.gradle then this will also print their fingerprints as well. – Salman Khakwani Nov 21 '19 at 11:27