Android packaging, signing, and obfuscation

A few days ago, I had to pack an APK in my internship, and then it sent me a. Keystore file, and asked me to use this signature when packing. At that time, I was thinking ah, ORIGINALLY I only understood the difference between public key and key when learning computer network, and deepened my understanding after reviewing HTTPS, but in short, these are not my direct contact, they are all some theoretical knowledge and understanding, now encountered, I think why the Android package signature? Shouldn’t signatures exist in network traffic?

Originally, when I was learning Android, I made a music app, using the SDK of Ximalaya, which told you that you must use Obfuscated after the introduction. At that time, I first came into contact with obfuscated. Later decompiled some software, found some packages named A, B… That’s how confusion works.

These two knowledge points are to ensure the safety of our application, and are used in packaging, I summed up them together to learn.

At the end of the university, we learned the principles of compilation and c++. At that time, I thought these two courses might be of little use to our software students, because most of them chose Java. When I started to do the graduation project of Android live broadcasting, I feel like all the classes at school are connected

Android Packaging Process

The steps of the Android compilation process are as follows:

  1. AAPT: Android Asset Packaging Tool
  2. Process AIDL files and generate Java code (AIDL: Android Interface Definition Language)
  3. Compile the Source code file to generate the corresponding.class file
  4. The. Class file is converted to a dex file
  5. Combine dex files and compiled resource files into APK (APK-Builder)
  6. Use debug or publish keystore signature (Jarsigner)
  7. Apply optimizations to reduce memory consumption at runtime (Zipalign: Archive tools for it — > MMAP memory map — > Reduce memory consumption at runtime)

Ps:

  • If you are using apkSigner, you can only perform zipalign before signing the APK file. If you make further changes to APK after using apkSigner to sign the APK, the signature will be invalidated.
  • If you are using Jarsigner, you can only perform zipalign after signing the APK file.

Ps2:

  • The default dex file should be one, but the number of methods in each dex file should not exceed 65535. We just need to configure multiDexEnabled True under Glide

The signature

To the junior developers to us at ordinary times, after the birth of an application, is really a belongs to own app, debugging and running on their phones, general is sometimes even can’t do much model adaptation, for showing off wait for a reason, you may put your app packaged into apk, and then throw on a server, to generate a qr code, Post a friend moment (don’t ask me why I know, just ask me I have a friend). We don’t have any access to signatures at this point.

At that time, I thought that as long as I did not publish to various app stores, I did a search on the official documentation and found the following:

Android requires all APKs to be digitally signed with a certificate before they can be installed on the device or updated.

App-debug. apk is the apK that you build. The system should have signed us automatically, but what about the signed files? When I open the Android folder, I see debug.keystore. Yes, this is the default digital signature of this machine.

Android for the first time you run or debug project Studio, the IDE automatically in $HOME/Android/debug keystore created in debugging keystore and certificate, and set the keystore and key password.

It also tells us that it was created automatically when you first run and debug the IDE, which means that it doesn’t exist when you install the IDE, which means that the debug keystore and certificates generated by each machine should be different.

Let’s take a look at this:

Well, now that we’re done, it’s time to solve the original problem.

What’s the use of a signature?

The signature notes in the official text clearly tell us the function of signature.

There are three main points as follows:

  • Application upgrade: When an application update is installed, the system compares the certificates in the new version with those in the existing version. If the certificate matches, the system allows the update. If you use a different certificate to sign the new version, you must assign another package name to the application – in this case, the user installs the new version as a brand new application.
  • Application modularity: Android allows multiple APKs signed with the same certificate to run in the same process (if the application requests to do so) so that the system treats it as a single application. This way, you can deploy your application by module, and users can update each module independently.
  • Sharing code/data through permissions: Android provides signature-based permissions enforcement so that one application can provide functionality to another application that uses a specified certificate signature. By signing multiple APKs with the same certificate and using signature-based permission checking, your applications can share code and data in a secure manner.

In the actual application, I encountered this situation. The APK of this application has been installed on the current device, but the company asked me to develop it again. After I finished the development, I directly installed app-debug.apk on the device, and the error occurred. Solution 1: Uninstall the program and install it again, but this clears the cache of data. This reminds me of the Ark of Tomorrow, where every major version update uninstalls the original application, installs a new APK, and then re-logs in) (Solution 2: send the signature together to the app ape – we pack with the same signature)

This brings us to one of the most common uses of signatures: application upgrades. This is also one of the reasons why I want to know about signatures and write this blog.

Does signature guarantee the security of APK?

To answer this question, we need to know a few nouns:

Certificate A public key certificate (.der or.pem file, also known as a digital certificate or identity certificate) contains the public key in a public/private key pair, as well as some additional metadata (such as name and location) that identifies the owner of the corresponding private key.

When you sign your application, the signing tool appends the certificate to the application. The certificate associates the APK or App Bundle with you and your corresponding private key. This helps Android ensure that all future updates to your app are authentic and come from the original author. The key used to create this certificate is called the application signing key.

You can download your app signing key and upload the certificate to register your key with the API provider from the Play Administrator’s App Signing page. You can share the certificate with anyone. It does not contain your private key.

Each application must use the same certificate for its entire life cycle so that users can install a new version as an application update. For a detailed understanding of the benefits of having all applications use the same certificate for their entire life cycle, see the signing considerations above.

A certificate fingerprint is a short, unique representation of a certificate, and API providers typically require both the certificate fingerprint and the package name to register applications using their services. You can find the MD5, SHA-1, and SHA-256 fingerprints of the uploaded certificate and application signature certificate on the Application Signature page of the Play Manager. You can also download the original certificate (.der) from the same page to calculate additional fingerprints.

Here are the different types of keys and keystores you should know about:

  • Application signing key: The key used to sign the APK installed on the user device. As part of the Android security update model, the application signing key remains constant throughout the life of the application. The application signing key is a private key and must be kept secret. However, you can share certificates generated using the application signing key with others.

  • Upload Key: The key used to sign the App Bundle or APK before uploading it for the Google Play App Signing plan. You must keep the upload key confidential. However, you can share certificates generated using the upload key with others. You can generate an upload key in one of the following ways:

    • If you want Google to generate an application signing key for you when you opt in to the program, the key you use to sign your application for publication will be specified as the upload key.
    • If you provide An application signing key to Google when you add a new or existing application to the program, you can generate a new upload key during or after the opt-in process to improve security.
    • If you do not generate a new upload key, continue to use your application signing key as the upload key to sign each version.
    • Tip: To keep your key secure, make sure that the application signing key is different from the upload key.
  • Java keystore (.jks or.keystore) : A binary file used as a store for certificates and private keys.

  • Play Encrypt Private Key (PEPK) tool: Use this tool to export the Private Key from the Java Key store and Encrypt the Private Key for transmission to Google Play. When providing the application signing key for Use by Google, select the export and upload key option from Java Keystore, and follow the instructions to download and use this tool. Alternatively, you can choose the Export and upload keys (without using Java keystores) option to download, view, and use the open source PEPK tools.

(The above is an overview of the knowledge of applying signatures in the official text – quotes from keys, certificates, and keystores)

Android signature does not prevent the APK package from being modified, but the modified re-signature cannot be the same as the original signature (unless you have a private key). So if your software is still decompiled, but somebody else decompiled it and packaged it, it’s a different application. (For example, when we used to play small nokia games, some of them were Chinese versions, and then we would not replace the original program. I remember playing an online game called “Ancient 2” and playing a double-open version. Now I know the original app was cracked and repackaged.)

To sum up: the signature mechanism is actually a verification mechanism for the integrity of APK package and uniqueness of the publishing agency. Apk is a simple, but limited, defense for software. We can increase the security by doing a signature comparison while the program is running, but if it’s cracked, having the program skip that part of the signature comparison undermines this basic defense.

The debug.keystore contains the signature algorithm name: SHA1withRSA. It can be concluded that the APK is signed by private key using SHA1-RSA algorithm.

Sha-1 is a cryptographic hash function that is still in widespread use, although it is no longer secure. It turns an input of arbitrary length into an output of fixed length through a hash algorithm.

RSA is an asymmetric encryption algorithm. Use the private key to encrypt the output information of SHA-1 using the RSA algorithm.

Only the public key can be used to decrypt RSA encrypted information during installation. Once decrypted, it is compared with the sha-1 output, and if it matches, it indicates that the content has not been abnormally modified.

confusion

Obfuscation handling: Shorten the names of classes and members to reduce the size of DEX files.

The purpose of obfuscation is to reduce the size of an application by shortening the names of its classes, methods, and fields.

While obfuscation does not remove code from your application, it can significantly reduce the size of your application if your application’s DEX file indexes many classes, methods, and fields. However, because obfuscating renames different parts of the code, additional tools are needed to perform certain tasks, such as checking the stack trace.

In addition, if your code depends on the predictable naming of applied methods and classes (for example, when using reflection), you should treat the corresponding signatures as entry points and specify retention rules for them.

The purpose of obfuscation is to reduce the size of the application, but obfuscation is often said to protect the code because it reduces the readability of the code and takes time to decode after decompilation. This may not be one of the purposes of confusion, but people have used it to discover its additional value.

Confusion is irreversible, in the process of confusion, some information that does not affect the normal operation will be permanently lost, the loss of these information makes the program more difficult to understand.

I once thought a certain function of an app had a particularly good effect, and after decomcompiling it, I found that confusion was really useful, probably because I read a novel with only a few names, except for the protagonist, and no one else could match the number. I often went back to find out who this person was. (If it was an English name, I wouldn’t be able to remember it and would probably not look for it, in which case I would need a piece of paper to write down the relationship between the names and put it in a book, which might be called “confusion”.)

conclusion

At last! No software on the market is 100% secure, but their encryption is complex and can change over time, and cracking it can be a cost issue.

And finally! Decomcompiling software on your PC is familiar (apktool + dex2jar + JD-gui)

On the phone, I quite like a software called “Development Assistant” (it seems to be made by some didi boss). It can see the application layout, screen color, encryption software used in the app, etc. The functionality is better than “MT Manager” in my opinion.

In Android Studio we can use build -> Analyze APK… To analyze APK, and then to further optimize the size of our APK.