Android compare signature of current package with debug.keystore

zmeda picture zmeda · May 25, 2011 · Viewed 11.9k times · Source

As all we do I have application which is signed by debug.keystore (by default) when it is in development mode (build). When it goes production we sign it with our private key. Is there any way to determine at runtime that current package is signed with debug.keystore (is in development mode) or is signed with our private key (is in production mode).

I have tried something like

    PackageManager packageManager = getPackageManager();
    try {
        Signature[] signs = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures;
        for (Signature signature : signs) {
            Log.d(TAG, "sign = " + signature.toCharsString());
        }
    } catch (NameNotFoundException e) {
        e.printStackTrace();
    }

I don't know what to do next? Is this right way of doing this? How to obtain comparable debug.keystore signature?

I know that exists MD5 Fingerprint keytool -list -keystore ~/.android/debug.keystore but in Signature class there is not "md5 fingerprint"-like method. I want to do this because of MapView Key, Logging, LicenseChecker and stuff like this.

Answer

Jcs picture Jcs · Jun 1, 2011

The signature in PackageInfo does not seem to be well named since tha field does not contain the package signature but the signer X509 certificate chain. Note that (most of the time) this chain seems to be limited to one single self-signed certificate.

According to the Android developer page Signing Your Applications the debug signature certificate is generated with this DN: CN=Android Debug,O=Android,C=US

Therefore it is easy to test if the application has been signed in debug mode:

private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US");
/* ... */
Signature raw = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures[0];
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));
boolean debug = cert.getSubjectX500Principal().equals(DEBUG_DN);