sobota, 29 stycznia 2011

Working with signatures in apk(s)

Our task in the job was to write some (robotium) test to the application(s) that we were given only apk-s and the debug.keystore.

We had to use the same debug.keystore to be able to run InstrumentationTestCase. When the keys didn't match we get an error similar to this:

java.lang.SecurityException: Permission Denial: starting instrumentation ComponentInfo{net.retsat1.starlab.test/android.test.InstrumentationTestRunner} from pid=4745, uid=4745 not allowed because package net.retsat1.starlab.test does not have a signature matching the target net.retsat1.starlab


The keys have changed in the course of time few times and we soon get into the mess of not being sure which debug keystore was used.

We had to find a way to check which certificate is used.

On android pages you can get some information about signing the apks with the certificates.

http://developer.android.com/guide/publishing/app-signing.html#cert

and about security model used

http://developer.android.com/guide/topics/security/security.html


First thing we tried is the

jarsigner -verify -verbose -certs net.retsat1.starlab-1.apk


which output is

sm 520 Sat Jan 22 23:11:20 CET 2011 res/layout/main.xml

X.509, CN=Android Debug, O=Android, C=US
[certificate is valid from 05.10.10 21:47 to 05.10.11 21:47]


this can be compared to the output of the same command on the apk we are sure with which certificate was signed and look at the validity time. However, this is not very convenient. It would be better to get some number that can be easily compared.

Keytool is capable of displaying a certificate finger print

keytool -keystore ~/.android/debug.keystore -storepass android -list


That gives the output

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

androiddebugkey, 2010-10-05, PrivateKeyEntry,
Certificate fingerprint (MD5): 32:BD:9C:D1:1A:8C:32:95:B1:4F:14:45:B4:5D:86:D6

Which is basically what we were looking for. Now we needed the same for the apk.

After examining some robotium tutorials and this script sign-debug-any-apk.sh we produced a semi-automated script (printfingerprint.sh) for that.


#!/bin/bash

if [ $# -lt 1 ]; then
echo -e "Prints certificate fingerprint of the given apk file.\nUsage: $0 file.apk"
exit 1
fi

APKFILE=`readlink -f $1`

TEMP=`mktemp -d`
cd $TEMP
jar xf $APKFILE
keytool -printcert -file META-INF/CERT.RSA | egrep "^\s+MD5|^\s+SHA"
rm $TEMP -rf


Semi automatic as we need to get the apk from the device first.


printfingerprint.sh ~/tmp3/net.retsat1.starlab-1.apk

which leads us to

MD5: 32:BD:9C:D1:1A:8C:32:95:B1:4F:14:45:B4:5D:86:D6
SHA1: C4:68:47:DD:BF:61:C5:03:27:08:96:1C:7A:75:E1:42:DD:EC:C8:F2

and we can verify if the certificate in apk(s) match.