Android APK Signature Comparison
Friends who have released Android apps should be aware that the Android APK release needs to be signed. The signature mechanism plays an important role in Android applications and frameworks.
For example, the Android system prohibits updating an apk with inconsistent installation signatures, and if the app requires system permissions, it must ensure that the APK signature is consistent with the framework signature, and so on. In the "apk Crack" article, we learned that to hack an apk, it is necessary to re-sign the APK. This signature, in general, is no longer consistent with the original signature of the APK. (Unless the APK original author's private key leaks, it is another level of software security issues.) )
Simply put, the signature mechanism identifies the APK issuer. Therefore, from the point of view of software security, we can determine whether this apk is issued by the "official", rather than the "pirated software" that has been tampered with and re-signed by the APK signature situation.
Android signature mechanism
To illustrate the validity of the APK signature comparison to the software security, it is necessary to understand the signing mechanism of the Android APK. To make it easier for everyone to understand, we start with a batch command of the Auto-sign tool.
In the "apk Crack" article, we learned that to sign a non-signed APK, you can use a tool called Auto-sign. The Auto-sign tool actually runs a batch command called Sign.bat. Opening this batch file with a text editor, we can see that the command that implements the signature function is basically this line of command:
Java-jar Signapk.jar Testkey.x509.pem testkey.pk8 update.apk update_signed.apk
The meaning of this command is: by Signapk.jar this executable jar package, "TESTKEY.X509.PEM" This public key file and "Testkey.pk8" This private key file to the "update.apk" signature, the signed file is saved as " update_signed.apk ".
There is no further introduction to the way the private key and public key are generated here. We can find a lot of information in this respect. What we're going to talk about here is what Signapk.jar has done.
Signapk.jar is a signature tool in the Android source package. Because Android is an open source project, so, very happy, we can directly find Signapk.jar source! The path is/build/tools/signapk/signapk.java.
In contrast to an unsigned apk and a signed apk, we will find that there is a more folder called Meta-inf in the signed APK package. Inside there are three files, named MANIFEST.MF, CERT, respectively. SF and Cert.rsa. Signapk.jar is the creation of these files (no other files have changed.) So we can easily remove the original signature information).
By reading the signapk source code, we can sort out the entire process of signing the APK package.
1. Generate MANIFEST.MF File:
The program iterates through all the files in the UPDATE.APK package (entry), generates SHA1 digital signature information for non-folder non-signed files, and then encodes it with Base64. Specific code See this method:
private static Manifest Adddigeststomanifest (Jarfile jar)
The key code is as follows:
1 for (Jarentry entry:byName.values ()) {
2 String name = Entry.getname ();
3 if (!entry.isdirectory () &&!name.equals (jarfile.manifest_name) &&
4!name.equals (Cert_sf_name) &&!name.equals (cert_rsa_name) &&
5 (Strippattern = = NULL | |! Strippattern.matcher (name). Matches ())) {
6 InputStream data = Jar.getinputstream (entry);
7 while (num = data.read (buffer)) > 0) {
8 md.update (buffer, 0, num);
9}
Ten Attributes attr = null;
one if (input = null) attr = input.getattributes (name);
attr = attr! = null? New Attributes (attr): New Attributes ();
Attr.putvalue ("Sha1-digest", Base64.encode (Md.digest ()));
Output.getentries (). Put (name, attr);
15}
16}
The resulting signature is then written to the MANIFEST.MF file. The key code is as follows:
1 Manifest Manifest = adddigeststomanifest (Inputjar);
2 JE = new Jarentry (jarfile.manifest_name);
3 Je.settime (timestamp);
4 Outputjar.putnextentry (JE);
5 Manifest.write (Outputjar);
Here is a brief introduction to the SHA1 digital signature. Simply put, it is a secure hashing algorithm, similar to the MD5 algorithm. It turns the input of any length into a fixed-length output by hashing the algorithm (here we call "summary information"). You cannot restore the original information by simply using this summary information. In addition, it ensures that the summary information of different information differs from each other. So, if you change the files in the APK package, then in the APK installation check, the changed file summary information and MANIFEST.MF test information is different, so the program will not be installed successfully.
2. Generate CERT.SF File:
For the manifest generated in the previous step, use the SHA1-RSA algorithm to sign with the private key. The key code is as follows:
1 Signature Signature = signature.getinstance ("Sha1withrsa");
2 signature.initsign (Privatekey);
3 JE = new Jarentry (cert_sf_name);
4 Je.settime (timestamp);
5 Outputjar.putnextentry (JE);
6 Writesignaturefile (Manifest,
7 New Signatureoutputstream (Outputjar, signature));
RSA is an asymmetric encryption algorithm. The digest information is encrypted with the private key through the RSA algorithm. You can only use the public key when you install to decrypt it. After decryption, it is compared to unencrypted summary information, and if it matches, the content is not modified by exception.
3. Generate Cert.rsa File:
The build MANIFEST.MF does not use key information, and the generated CERT.SF file uses the private key file. Then we can easily guess, CERT. The generation of RSA files is definitely related to the public key.
CERT. The RSA file holds information such as the public key, the encryption algorithm used, and so on. The core code is as follows:
1 JE = new Jarentry (cert_rsa_name);
2 Je.settime (timestamp);
3 Outputjar.putnextentry (JE);
4 Writesignatureblock (signature, PublicKey, Outputjar);
The code for Writesignatureblock is as follows:
1 private static void Writesignatureblock (
2 Signature Signature, X509Certificate publickey, outputstream out)
3 throws IOException, Generalsecurityexception {
4 SignerInfo signerinfo = new SignerInfo (
5 New X500name (Publickey.getissuerx500principal (). GetName ()),
6 Publickey.getserialnumber (),
7 Algorithmid.get ("SHA1"),
8 Algorithmid.get ("RSA"),
9 signature.sign ());
10
PKCS7 PKCS7 = new PKCS7 (
New algorithmid[] {algorithmid.get ("SHA1")},
New ContentInfo (contentinfo.data_oid, NULL),
New x509certificate[] {PublicKey},
New signerinfo[] {signerinfo});
16
Pkcs7.encodesigneddata (out);
18}
Well, after analyzing the signature process of the APK package, we can clearly realize:
1. The Android signature mechanism is a verification mechanism that is unique to the APK package integrity and publishing organization.
2. The Android signature mechanism cannot prevent the APK package from being modified, but the modified re-signature cannot be consistent with the original signature. (except where the private key is owned).
3, the APK package encrypted public key is packaged in the APK package, and different private keys corresponding to different public keys. In other words, the different private key signatures of the APK public key will also not be the same. So we can judge whether the private key is consistent according to the public key.
How to implement the APK signature comparison
Well, through the analysis of the Android signature mechanism, we have proved from the theory that the APK's publisher can be judged by the comparison of its public key. And the agency is hard to disguise, and we can think of it as non-disguised for the time being.
With a theoretical foundation, we can begin to practice. So how do I get the public key information to the APK file? Because the Android system installer will definitely get the APK information for comparison, so we can get some ideas and help through the Android source code.
There is a hidden class in the source code for the APK package parsing. This class is called Packageparser, and the path is Frameworks\base\core\java\android\content\pm\packageparser.java. When we need to get information about the APK package, we can use this class directly, the following code is an example function:
1 private PackageInfo Parsepackage (String archivefilepath, int flags) {
2
3 Packageparser packageparser = new Packageparser (Archivefilepath);
4 Displaymetrics metrics = new Displaymetrics ();
5 Metrics.settodefaults ();
6 final File SourceFile = new file (Archivefilepath);
7 Packageparser.package pkg = Packageparser.parsepackage (
8 SourceFile, Archivefilepath, metrics, 0);
9 if (pkg = = null) {
return null;
11}
12
Packageparser.collectcertificates (pkg, 0);
14
Return packageparser.generatepackageinfo (pkg, NULL, flags, 0, 0);
16}
Where parameter Archivefilepath specifies the path to the APK file; flags need to set the packagemanager.get_signatures bit to ensure that the certificate signature information is returned.
Specifically, how to obtain signature information via Packageparser is not detailed here, please refer to the public boolean collectcertificates in Packageparser (package pkg, int flags). and private certificate[] Loadcertificates (jarfile jarfile, Jarentry je, byte[] readbuffer) method. As for how to use hidden classes and methods in Android app development, see my article: How to use the Hide API in Android app development.
Immediately after that, we can visit the APK signature information via Packageinfo.signatures. It is also necessary to explain the correspondence between signature in Android and certificate in Java. Their relationship is as shown in the following code:
1 pkg.msignatures = new Signature[certs.length];
2 for (int i=0; i<n; i++) {
3 Pkg.msignatures[i] = new Signature (
4 certs[i].getencoded ());
5}
That is to say Signature = new Signature (certificate.getencoded ()); The certificate certificate contains additional basic information about the public key and the certificate. Different public keys, certificates must differ. We can obtain the public key information through the certificate Getpublickey method. So the comparison to the signature certificate is essentially a comparison of the public key information.
OK, after getting to the APK signing certificate, the comparison is left. This simple, functional function is as follows:
1 Private Boolean Issignaturessame (signature[] s1, signature[] s2) {
2 if (S1 = = null) {
3 return false;
4}
5 if (S2 = = null) {
6 return false;
7}
8 hashset<signature> Set1 = new hashset<signature> ();
9 for (Signature sig:s1) {
Ten Set1.add (SIG);
11}
hashset<signature> Set2 = new hashset<signature> ();
for (Signature sig:s2) {
Set2.add (SIG);
15}
Sure S2 contains all signatures in S1.
if (Set1.equals (Set2)) {
return true;
19}
return false;
21}
APK Signature Comparison Application scenario
After the above discussion, we must have understood the principle of signature comparison and my way of realization. So when is it appropriate to use signature comparisons to secure Android APK software?
Personally, there are three main types of scenarios:
1, the program self-test. When the program is running, it is self-signed. The comparison sample can be stored in the APK package and can also be stored in the cloud. The disadvantage is that when the program is cracked, the self-detection function can also be destroyed to invalidate it.
2, reliable third-party detection. A trusted third-party program is responsible for the APK's software security issues. Comparison samples are collected by third parties and placed in the cloud. This applies to software download markets such as antivirus security software or app market. The disadvantage is that network detection is required, and functionality cannot be implemented without the use of networks. (It is not possible to place large amounts of signature data locally on a mobile device.)
3, the system limited installation. This involves changing the Android system. Limit the APK to install only certain certificates. The software publisher needs to request a certificate from the system publishing. If you find a problem, you can track down which software publisher is responsible. Applicable to system providers or end product manufacturers. The disadvantage is too closed, not conducive to the openness of the system.
The above three kinds of scenes, although each have shortcomings, but the shortcomings are not insurmountable. For example, we can consider the function of the program self-detection using native method implementation and so on. Software security is a complex subject, often requires a combination of multiple technologies, in order to better protect the software from malicious destruction.
Resources
Android Source code
"Signature mechanism in Android"
Reprint Please specify the Source: http://www.blogjava.net/zh-weir/archive/2011/07/19/354663.html
Android signature mechanism