Friday, December 2, 2011

Keystores

------ General notes:  -----------------------------

 - The quick way to sign existing apk:
java -jar signapk.jar platform.x509.pem platform.pk8 app.apk signed_app.apk 
You can find signapk.jar from : out/host/linux-x86/framework/signapk.jar
You can find platform.x509.pem and platform.pk8 : build/target/product/security


- How to generate keystore to sign apk from eclipse:
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:android -name androiddebugkey
keytool -importkeystore -deststorepass android -destkeystore ./platform.jks -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass android

 ------------------------------------------------------
The Android system requires that all applications must be signed. Detailed description about signing applications could be found at http://developer.android.com/guide/publishing/app-signing.html

Google provide the following standard test keys:
testkey -- a generic key for packages that do not otherwise specify a key.
platform -- a test key for packages that are part of the core platform.
shared -- a test key for things that are shared in the home/contacts process.
media -- a test key for packages that are part of the media/download system.

They are located at: android\build\target\product\security
There is mentioned that these test keys are used strictly in development.
Usually they are used to sign applications when you create “eng” platform build.
To sign application in Eclipse it is necessary to create keystores from keys.

How to create keystores from keys

openssl  (cryptography and SSL/TLS toolkit) and keytool (Key and Certificate Management Tool from JDK) will be used.

1. run keys_cr.sh in android\build\target\product\security to generate *.p12 files
#!/bin/sh

FILES=`find . -name "*.pk8"`

for FILE in $FILES 
do
FILE_NAME=`echo $FILE | awk -F.pk8 '{print $1}'`
if [ -f ${FILE_NAME}.pem ] 
then
    echo "file ${FILE_NAME}.pem exists"
else
`openssl pkcs8 -inform DER -nocrypt -in ${FILE} -out ${FILE_NAME}.pem`
fi

`openssl pkcs12 -export -in ${FILE_NAME}.x509.pem -out ${FILE_NAME}.p12 -inkey ${FILE_NAME}.pem -password pass:android -name androiddebugkey`

done
 
2. use the following commands to create keystores:
keytool -importkeystore -deststorepass android -destkeystore ./shared.jks -srckeystore ./shared.p12 -srcstoretype PKCS12 -srcstorepass android
keytool -importkeystore -deststorepass android -destkeystore ./testkey.jks -srckeystore ./testkey.p12 -srcstoretype PKCS12 -srcstorepass android
keytool -importkeystore -deststorepass android -destkeystore ./media.jks -srckeystore ./media.p12 -srcstoretype PKCS12 -srcstorepass android
keytool -importkeystore -deststorepass android -destkeystore ./platform.jks -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass android

Using Keytool IUI to create keystore

Keytool IUI is Cryptography GUI tool (http://code.google.com/p/keytool-iui/). It allows create, manage keys and certificates, encrypt and decrypt files.

1.    Keytool IUI -> Create -> Keystore. Select path and set the name of keystore file, set password “android”
2.    Click “Ok”

3.    Keytool IUI -> Import-> Keystore’s entry -> Private key -> PEM file format
Private key file: platform.pem
-    Create platform.pem from platform.pk8 with the following command:
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
Certificates chain file: platform.x509.pem
Keystore file: path to keystore created at point 1
Keystore password: android


4.    Enter new private key entry’s alias: androiddebugkey, password: android


View keystores in Keytool IUI

You can open existing keystores in Keytool IUI using “View keystores” menu.


Use mouse right-click on entry’s row to display popup menu



Certificate fingerprints (MD5) for test keys:

To get MD5 from generated keystore (password: android):
keytool -list -keystore platform.jks
The following fingerprints were generated for Gingerbread testkeys:

platform: Certificate fingerprint (MD5): 8D:DB:34:2F:2D:A5:40:84:02:D7:56:8A:F2:1E:29:F9
test: Certificate fingerprint (MD5): E8:9B:15:8E:4B:CF:98:8E:BD:09:EB:83:F5:37:8E:87
media: Certificate fingerprint (MD5): 19:00:BB:FB:A7:56:ED:D3:41:90:22:57:6F:38:14:FF
shared: Certificate fingerprint (MD5): 5D:C8:20:1F:7D:B1:BA:4B:9C:8F:C4:41:46:C5:BC:C2

How to determine which certificate was used to sign apk

There are at least two ways to determine the certificate that was used to sign application:
1.    Certificate is defined in Android.mk from Application Source folder:
LOCAL_CERTIFICATE := platform

2.    Certificate could be known from *.apk file
-    Unzip apk file and extract META-INF\CERT.RSA file
-    Check md5 with the following command: keytool -printcert -file CERT.RSA

Add Keystore to Eclipse

1.    Window -> Preferences, Android -> Build
2.    Browse your keystore in “Custom debug keystore”
3.    Clean the project to apply new keystore


Another way to sign application

java -jar signapk.jar platform.x509.pem platform.pk8 app.apk signed_app.apk

signapk.jar is located at out\host\linux-x86\framework\signapk.jar


Using Google Maps in application

The Google Maps service requires that each MapView identify itself to the service using a Maps API Key. Before providing Maps tiles to a MapView, the service checks the Maps API Key supplied by the MapView to ensure that it:

•    References a certificate/developer registered with the service, and
•    References a certificate that matches the certificate with which the application (containing the MapView) was signed.

Unless both conditions are met, the service does not provide Maps tiles to the MapView.
Detailed information can be found at: http://code.google.com/android/add-ons/google-apis/mapkey.html
So Maps API Key is generated based on MD5 certificate fingerprint. And you should get new API Key in case of certificate is changed.

Note: if application is a system application and it is located in /system/app folder then there is no matter what API Key is used. System applications have some privileges and there is no check for API key during access to Google Maps Service.

5 comments:

  1. Hi, I've got a problem, at the time when i'm trying to import private keys as new private key entry (cf here : http://4.bp.blogspot.com/-pTzQ7D2KmPI/Ttip0GVCH0I/AAAAAAAAAkQ/ge4XxFulo_8/s1600/alias.PNG), i've got an exception :
    java.lang.Exception: objKpr: not an instance of KeyPair
    at org.ragingcat.kst.util.jarsigner.KTLKprOpenKprFromKprPemAbs._readKprPem(KTLKprOpenKprFromKprPemAbs.java:437)
    at org.ragingcat.kst.util.jarsigner.KTLKprOpenKprFromKprPemAbs._readKpr(KTLKprOpenKprFromKprPemAbs.java:450)
    at org.ragingcat.kst.util.jarsigner.KTLKprOpenKprFromKprPemAbs._doJob_(KTLKprOpenKprFromKprPemAbs.java:493)
    at org.ragingcat.kst.util.jarsigner.KTLKprOpenKprFromKprPemKPAbs._doJobSelectKpr_(KTLKprOpenKprFromKprPemKPAbs.java:144)
    at org.ragingcat.kst.util.jarsigner.KTLKprOpenKprFromKprPemAbs.doJob(KTLKprOpenKprFromKprPemAbs.java:292)
    at org.ragingcat.kst.swing.panel.PTabUICmdKtlKstOpenKprFromKprPem.actionPerformed(PTabUICmdKtlKstOpenKprFromKprPem.java:343)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

    Do you know what happened ?

    Thanks for your very useful tutorial.

    ReplyDelete
  2. I wont able to find this folder "build/target/product/security"

    where this folder reside in pc please help

    ReplyDelete
    Replies
    1. You should download full Android source tree (http://source.android.com/source/downloading.html), or get it from https://android.googlesource.com/platform/build/+/donut-release/target/product/security/

      Delete
    2. is those files works for all devices ?!
      I have galaxy tab A !

      Delete
  3. you have clearly explained the concept as well as picture representation is really awesome and i got clear notes, thank you so much.

    Best Android Training Institute in Chennai

    ReplyDelete