I was playing around with the App sigining process of android and had some open questions, that are not good documented on the net. I hope this entry changes this issue and makes things more clear.
The Android App Signing Process 17 is only used to check if another package with the same name is allowed to update an existing package.
As you can see in 2, all existing certificates are used. So if there are many certificates existing in the META-INF Folder, all of them need to be in the old APK as well.
There is also no way to "switch" the certificate some day (this is also stated somewhere in the android developer guides...) - so there is in real no reason to use multiple certificates. But people do, or try to do 14.
1 describes in more detail how the actual Android Package Manager works. If you pull the /data/system/packages.xml
file from your device,
you can see all installed apps and also their certificates. Note that if you see an entry like <cert index="0" />
it means that the actual certificate key
can be seen above in another package with the same index.
The Android Certificates are actually PKCS#7 Files, in DER 6 Encoding. There are several ways to read the files, like openssl
or keytool
.
If you want to see the certificate in more detail i would use the JavaScript ASN.1 4 Decoder at 3.
There are some resources telling you how to extract the raw certificate and also how to manually verify a signature: 7, 8.
Talking about manual verification here. The keytool prints you all the fingerprints, but where do they come from?
If you look into the package.xml
, the hexdump in the <cert>
entry is the data that is hashed by md5
, sha1
or sha256
(or whatever you want) to create the fingerprint 11.
It is also the same data that is in the certificate file inside the PKCS#7 File (*.RSA
or *.DSA
in the META-INF
folder inside the APK).
So you have to first extract the certificate from the rest of the file. 7 shows you how this goes, or you write your own ASN.1 parser.
The Certificate is the one after the OID 1.2.840.113549.1.7.1
(which stands for PKCS#7 data). There is also this 9 wonderful site, telling you more about the OID you are looking for.
And there are also resources like the MSDN or planetlarg telling you how exactly the data format is for some DER encoded types 10.
So lets summarize this:
- You can, but probably do not need, sign your app with different keys. (this is also explained in the JAVA Manual 15)
- In an update process, android will check for the existing of all the certificates
- You can watch the certificates in the
/data/system/packages.xml
- The Fingerprint is just a hash over the binary (DER Coded) form of the certificate (as in
packages.xml
) - reading DER and ASN.1 is quite a pain...
- ... but there are nice tools to help you! 3
- Content of the Certificate is not interesting for the android system. Google also tells you to generate a key with at least 25 years of validity 18.
But there are still open questions:
- Is one android certificate really unique? Can you produce collisions easily?
- The answer is probably yes it is unique and no you can not create collisions, as asked in 16
- One issue could be shared certificates and repackaging in third party markets and also weak random number generators.
- Because android uses this model, it would be rather bad if any certificate could be faked. I hope google thought about it and only used it if there where little chance that you can generate duplicate certificates.
- What about signature permissions? Can you create an app that has multiple certificates to use multiple signature level permissions?
- I don't know. As in 17 it says the certificate entries are compared - but does it mean compared like all signatures must match, or one of them?