How to sign an APK with more than one certificate?

How do I sign an APK with more than one certificate, so that I can do this when I publish to the Android Market:

Version 1.0 => Signed with Certificate A
Version 2.0 => Signed with Certificate A & B
Version 3.0 => Signed with Certificate B

The Android Market does give me some hope but I am not sure what to make of it, when I upload with a different sign certificate it gives me this message:

"The apk must be signed with at least one certificate in common with the previous version."

Motive:
I have published an app on the market using the Android Signing Tool as part of MotoDev Studio for android. The problem is that it handles the keys itself and there is no way (documented) to get them. I want to change it to use a keystore and certificate that I have more control of and can use even if I don't use MotoDev Studio anymore. Also it seems that MotoDev Studio will lock you out of new features such as shared libraries.

UPDATE 5/3/2011:
They have been actually really quick and prompt at updating MotoDev Studio but it seems like I believe that Google should still provide a work around for those that want to change the certificates of their applications. Updating application to all use the same certificate, creating new ones over time, and possibly creating a new one so that you may hand of the support and distribution of your application to others.


Solution 1:

If you want to sign an APK more than once, just do so.
But note that Google Play does not accept APKs with multiple signatures.

eg. You can sign an APK from the command line using jarsigner like so:
jarsigner -keystore original-keystore my-app-unsigned.apk key-alias alias

Then just repeat this with the second key:
jarsigner -keystore new-signing-keystore my-app-unsigned.apk key-alias

Don't forget to run zipalign afterwards:
zipalign -v 4 my-app-unsigned.apk my-app.apk


I just re-read the part about MotoDev studio. In that case you can just sign the APK first using MotoDev as usual, then sign with your new key on the command line as above.

Solution 2:

I was really pleased to see this post until I saw @ddcruver's comment (2010-06-05) and @cistearns' comment (2011-03-01).

However, there's actually a major security issue with the transition method you describe (if it were to work how you'd expect), making it fairly trivial for an attacker to replace your app if they can get your users to install their stuff:

  • You release your app signed with certificate A.
  • The attacker obtains the apk, additionally signs it with certificate M, and distributes the app.
  • The attacker can then release a malicious app signed with certificate M to replace yours and get access to any data it may be storing.

Normally, if an attacker tried to replace something, the install would refuse unless the original is removed - at which point the data is wiped.

On the other hand, there are still several valid use-cases for transitioning a key/certificate: key renewal, hand over to another developer, etc.

This could be done more securely by authorising the transition to a new key from the old key. Please see the issue in the Android project.

Solution 3:

I had the problem today and here is what I did:

  1. Backup the old motodev.keystore file
  2. Use a recent motodev studio (2.0.1) to change my motodev.keystore password (change it in the motodev view where you can import a keystore)
  3. Convert the motodev keystore file (of type JCEKS) to a regular android keystore file (of type JKS) using the keytool.exe program bundled with java:

keytool -importkeystore -srckeystore motodev.keystore -srckeystoretype JCEKS -destkeystore android.keystore -destkeystoretype JKS

Now the android.keystore file can be used in the Google Eclipse plugins to export your application to a signed APK