Skip to content

AndroidPackageSignatures

Paul Louis NECH edited this page Feb 22, 2015 · 8 revisions

Android Packaging Signatures

JAR/APK Signature internals

Android APK packages are signed in almost the same way Java jar files are signed. Both APK and normal jar file are a collection
of files contained in a zip archives. This zip file contains a special directory called META-INF. You can list the content
of an apk or jar by unzipping it.

unzip -l com.rovio.angrybirds.apk
Archive:  com.rovio.angrybirds.apk
  Length      Date    Time    Name
---------  ---------- -----   ----
    62857  2011-02-07 17:12   META-INF/MANIFEST.MF
    62910  2011-02-07 17:12   META-INF/CERT.SF
     1714  2011-02-07 17:12   META-INF/CERT.RSA
    55050  2011-02-07 17:10   assets/data/audio/sfx/redbird_yell03.wav
   806436  2011-02-07 17:12   assets/data/images/864x480/MENU_ELEMENTS_1.pvr
    24278  2011-02-07 17:10   assets/data/audio/sfx/wood damage a1.wav
     6027  2011-02-07 17:12   assets/data/levels/pack6/LevelP3_224.lua
    60572  2011-02-07 17:10   assets/data/audio/music/game_complete.mp3
   253792  2011-02-07 17:12   classes.dex
---------                     -------
 35780825                     653 files

META-INF/MANIFEST.MF contains the list of files present in the APK and their
digest of their content. The default digest used is
SHA-1 its representation in the the
manifest is the base64 encoded binary value (unix tools like sha1sum or openssl
sha1 display the hexadecimal encoded binary value)

Manifest-Version: 1.0
Created-By: 1.0 (Android SignApk)

Name: assets/data/audio/sfx/redbird_yell03.wav
SHA1-Digest: 5bu0IsTrS29K1B/cZohBUYZx5tk=

Name: classes.dex
SHA1-Digest: edkyVsHyY7d4Y7TFgGhazz6PypY=

META-INF/CERT.SF (Signature file) In the manifest file, the SHA digest value
for each source file is the digest (hash) of the binary data in the source file.
In the .SF file, on the other hand, the digest value for a given source file is
the hash of the three lines in the manifest file for the source file. The lines
are “dos” terminated.

e.g.

"
Name: assets/data/audio/sfx/redbird_yell03.wav
SHA1-Digest: 5bu0IsTrS29K1B/cZohBUYZx5tk=


" | sha1sum | awk '{print $1}'

equals
 echo cA3IBIE3ymvliK9s6Xm9JUz3WGg= | base64 -d | hexdump -C
Signature-Version: 1.0
Created-By: 1.0 (Android SignApk)
SHA1-Digest-Manifest: OkpBSsYl4MCoSfK/3jE4lXjluJ0=

Name: assets/data/audio/sfx/redbird_yell03.wav
SHA1-Digest: cA3IBIE3ymvliK9s6Xm9JUz3WGg=

Name: classes.dex
SHA1-Digest: t96vCMTEN4hD4eIPvfHAKEaQEAE=

META-INF/CERT.RSA The .SF file is signed and the signature is placed in
the .RSA file. The .RSA file also contains, encoded inside it, the certificate
or certificate chain from the keystore which authenticates the public key
corresponding to the private key used for signing.

You can print out the certificates using the following lines of code:

openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

keytool -printcert -file CERT.RSA

jarsigner -verify -certs -verbose out/production/PlatformHacking/PlatformHacking.apk

Listing platform keys on the other hand happens using openssl

openssl x509 -in platform.×509.pem -noout -text

APK verification

I am assuming the following:

  • A package is signed
  • During install the signer is checked to grant permissions, after that dex
    optimisation is performed
  • dexopt is performed
  • When starting code that run in a package android checks the package crc32 and
    timestamp agains the cache to determine if it is needed to dexopt again.
    If not needed android assumes the data is “valid” no APK verification is
    performed

Links

Clone this wiki locally