Load and use Android code signing certificate

This is a step-by-step guide on how to load and use an android code signing key and certificate.

Prerequisites

  • a YubiKey with the PIV application

  • the yubico-piv-tool software, available here or on GitHub or

    brew install yubico-piv-tool
    
  • the OpenSC software, available on GitHub or

    brew install OpenSC
    

    Installing OpenSC on macOS might stop GnuPG from working, check our PGP page for more details and workarounds

  • jarsigner and keytool from the JDK (OpenJDK 8 used here)

Steps

  1. Import the key and cert, do one of the below:

    1. Import the key and cert (PEM format) in slot 9a:

      yubico-piv-tool -s 9a -a import-key -i key.pem
      yubico-piv-tool -s 9a -a import-certificate -i cert.pem
      
    2. Import the key and cert (PKCS12 format) in slot 9a:

      yubico-piv-tool -s 9a -a import-key -a import-cert -i key.p12 -K PKCS12
      
  2. Create a java pkcs11 configuration file:

    • Find out where OpenSC has installed the pkcs11 module. The following command can help with that:

      find /usr/local/ -name opensc-pkcs11*
      
    • Create the file, using the correct path discovered above for the library setting:

      cat > /tmp/pkcs11_java.cfg
      name = OpenSC-PKCS11
      description = SunPKCS11 via OpenSC
      library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
      slotListIndex = 1
      
  3. Check that keytool can see the key:

    keytool -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /tmp/pkcs11_java.cfg \
      -keystore NONE -storetype PKCS11 -list
    Enter keystore password:
    
    Keystore type: PKCS11
    Keystore provider: SunPKCS11-OpenSC-PKCS11
    
    Your keystore contains 1 entry
    
    Certificate for PIV Authentication, PrivateKeyEntry,
    Certificate fingerprint (SHA1): 26:D7:CB:71:6D:42:3C:AB:58:69:E0:9D:F0:16:DF:84:7E:1C:5A:9A
    

    Password here is the PIN of the key (default 123456).

    If the keytool command fails, adding the -debug option might help understand the problem. One common issue is that the slots might be indexed differently (starting from 0, for example), requiring the file created in the step above to be configured in another way.

  4. Sign the apk with jarsigner:

    jarsigner -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /tmp/pkcs11_java.cfg \
      -keystore NONE -storetype PKCS11 app.apk "Certificate for PIV Authentication"
    Enter Passphrase for keystore:
    jar signed.
    
  5. Verify the signature with jarsigner:

    jarsigner -verify app.apk