Improving the APK Signing Procedure

Using Hardware Security Modules for APK Signing

Ideally the OpenPGP card could be used for both jarsigner and OpenPGP signing. That means a card that can do both PKCS#11 and GnuPG. Otherwise there would have to be a PKCS#11 card for Java and an OpenPGP card for GnuPG. OpenSC now seems to provide PKCS#11 access to the OpenPGP card. Via OpenSC, keytool can see the key/certificate on the OpenPGP card via opensc 0.13, but jarsigner does not cooperate.

Relevant Discussions and Documentation

Related Software

Hardware We're Looking At

Getting Info about the Signatures

Here is the https://androidobservatory.org import code for displaying cert info. It should run in isolation of the Observatory code, but it's largely untested & undocumented.

Generating a New Signing Key

The default way to generate APK signing keys is with Java's keytool. It is widely used and not too hard to use. We recommend using at least OpenJDK 7, since it includes much improved versions of keytool and jarsigner. If you are willing to get your hands dirty, it is probably better to generate your key with openssl then import it with keytool (see below).

On Debian/Ubuntu/Mint/etc., you can keep OpenJDK 6 as the default JRE and JDK for compatibility while using keytool and maybe jarsigner from OpenJDK 7. Use sudo update-alternatives --config FOO, where FOO is: java javac jar jarsigner keytool

Using openssl to Generate the Key

An alternate way to generate the key is to use openssl. When it comes to generating, openssl has a better security track record than Java. Also, it is a less common combination so that exploits that might work with Java/keytool/jarsigner might not work with a key generated with openssl then imported using keytool. The downside is that there might also be weaknesses exposed by this trick, but that seems less likely than Java/keytool having problems. Additionally, we recommend generating your key using /dev/random because this is a long-lived key and therefore more sensitive. This does make generating the key take a lot longer.

openssl genrsa -out secretkey.pem -aes128 -rand /dev/random 4096
openssl req -new -key secretkey.pem -out request.pem
openssl x509 -req -days 9999 -in request.pem -signkey secretkey.pem -out certificate.pem
openssl pkcs12 -export -out certificate.p12 -in certificate.pem -inkey secretkey.pem

keytool -importkeystore \
    -srckeystore certificate.p12 -srcstoretype PKCS12 \
    -destkeystore certificate.jkr -deststoretype JKS

This should be possible with using GnuPG's gpgsm instead of openssl, but that requires GnuPG 2.1, which is not easily installable, and still in beta. So we'll save that HOWTO for later. You can follow the progress of all this work in our git repo: https://github.com/guardianproject/smartcard-apk-signing