Tuesday, May 02, 2017

Understanding APK (Android Package Kit) signing

Android requires that all APKs be digitally signed with a certificate before they can be installed. When you publishing an application or a custom artifact you need to sign the .apk or .zip files with a certificate using a private key. The Android system uses the certificate to identify the author of an application and establish trust relationships between applications.

The Classic Way:
The classic way of doing this was to use keytool then sign it with apksigner. keytool (https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html) is a java tool that manages a keystore (database) of cryptographic keys, X.509 certificate chains and trusted certificates. You can use keytool to generate the private key. For example:

keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

This above command will prompts you for passwords for the keystore and key, and to provide the distinguished name fields for your key. It then generates the keystore as a file called my-release-key.jks, saving it in the current directory (you can move it wherever you'd like). The keystore contains a single key that is valid for 10,000 days.

apksigner is a Andrioid SDK Builds Tool which allows you to sign APKs and to confirm that an APK's signature will be verified successfully. For example:

apksigner sign --ks my-release-key.jks --out my-app-release.apk my-app-unsigned-aligned.apk

That's the classic way of doing APK sigining. An easy and alternative method (most used) is to use "SignApk.jar".

The Easy Way:
SignApk.jar is a tool included with the Android platform source bundle. To use SignApk.jar you have to create a private key with it’s corresponding certificate/public key. To create private/public key pair, you can use Openssl.

How to create private/public key pair using openssl

# Generate an RSA private key, 1024 is the size of the private key to generate in bits
openssl genrsa -out key.pem 1024

# Creates and processes certificate requests in PKCS#10 format
# -new: generates a new certificate request.
# -key: Specifies the file to read the private key from
openssl req -new -key key.pem -out request.pem

# The x509 command is a multi purpose certificate utility. It can be used to display
# certificate information, convert certs to various forms, sign certificate
# -req: Specify a certificate request is expected on input (default input is certificate)
# -days: Number of days the certificate is valid for
# -signkey: Specify the certificate request to be self signed using supplied private key.
openssl x509 -req -days 9999 -in request.pem -signkey key.pem -out certificate.pem

# pkcs8 processes private keys in PKCS#8 format
# -topk8: Reads traditional format private key and writes a PKCS#8 format key.
# -outform: Specifies the output format.
# -inform: Specifies the input format.
# -nocrypt: PKCS#8 keys generated or input are normally PKCS#8 EncryptedPrivateKeyInfo structures using an
# appropriate password based encryption algorithm. With this option an
# unencrypted PrivateKeyInfo structure is expected or output.
openssl pkcs8 -topk8 -outform DER -in key.pem -inform PEM -out key.pk8 -nocrypt

Sign APK or Zip files using SignApk.jar
Since you have generated the certificate and private key, now you can sign your files:
java -jar signapk.jar certificate.pem key.pk8 your-app.apk  your-signed-app.apk
java -jar signapk.jar certificate.pem key.pk8 your-update.zip your-signed-update.zip

No comments: