This is not a question about how to sign an .apk file. I want to know what does signing actually means and how it is implemented.
Inside the .apk file there is META-INF folder and inside that there are two files.
First one is CERT.SF contains SHA1 hashes for various components and looks like this:
Name: res/layout/main.xml
SHA1-Digest: Cox/T8fN1X9Hv4VqjH9YKqc/MsM=
Name: AndroidManifest.xml
SHA1-Digest: wZ418H9Aix1LNch3ci7c+cHyuZc=
Name: resources.arsc
SHA1-Digest: P+uoRrpFyVW6P3Wf+4vuR2ZSuXY=
Name: classes.dex
SHA1-Digest: cN3zXtGii9zuTOkBqDTLymeMZQI=
There is also a file called CERT.RSA. I assume it is the public key to verify the signature.
My question is, where is the signature for the whole .apk file is stored? And what is actually signed? It could be either
.apk file used as a single binary object and this is signed
or CERT.SF is signed which contains individual hashes for different components
It would be also much better if you can point me to the documentation of the detailed signing and verification process.
Indeed this is not a specific Android question but a Java-in-general question however I post an answer anyway...
First of all: Only the XXX.SF file is signed; this means that all the files mentioned in the XXX.SF file are signed "indirectly" because XXX.SF contains their hashes. In fact all files not located in "Meta-Inf" should have hashes there! The whole .apk archive is not signed.
The XXX.SF file is more or less a copy of the MANIFEST.MF file. There is a line "SHA1-Digest-Manifest" which is the SHA-1 hash of "MANIFEST.MF" itself; the "SHA1-Digest" lines do not contain the hashes of the files but the hashes of the tree corresponding lines in the Manifest.MF file just like this:
SHA1("Name: filename"+CR+LF+"SHA1-Digest: "+SHA1(file_content)+CR+LF+CR+LF)
The file format of XXX.DSA/.RSA is the same as for an S/MIME email signature (for the content of XXX.SF) however the data is not base64 encoded and no header/trailer lines are used. "openssl smime -sign -outform DER" would create this format.
Multiple certificates can be used to sign a ZIP file. In this case multiple pairs of (XXX.SF/.RSA, YYY.SF/.RSA, ...) will exist.
This actually has nothing to do with Android. APK files are signed using jarsigner. Here is a link to the manpage.
Related
In Huawei App Gallery I have to update an existing aab application. Site redirects me to App signing page and there are steps that I have to follow in order to sign the app successfully. These are the steps provided:
Obtain the pepk.jar file from the Internet or another legitimate source.
Export and encrypt your private key and public key certificate into a ZIP file. Parameters in bold must be replaced as needed. Then, enter your data storage location and key password as prompted.
java -jar pepk.jar --keystore test.jks --alias test --output=output.zip --encryptionkey=<some_encryption_key> --include-cert
Upload the ZIP file containing the private key and public key certificate. (The ZIP file contains only certificate.pem and encryptedPrivateKey.)
Now I have 2 problems.
First one is, when I run the code in 2nd step in CMD. I get include-cert flag is not provided error. However when I write --include-cert=certificate.pem or --include-cert certificate.pem it says flag is unrecognized.
Second one is, I put certificate.pem and private key to folder and then turn it into ZIP. But when I click on submit it gives me Make sure the package contains only the certificate.pem and encryptedPrivateKey files error. Is not encryptedPrivateKey is the file that is exported by AndroidStudio when you generate an app bundle or Apk into the same location with .pepk extension?
I don't know what am I missing in order to sign my application. Any help would be appreciated, thanks in advance
If "No value provided for flag: include-cert" is displayed, the pepk.jar file is incorrect. You need to replace it with a correct one.
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-appsigning-faq-0000001052944432
I get include-cert flag is not provided error. However when I write --include-cert=certificate.pem or --include-cert certificate.pem it says flag is unrecognized.
It is recommended that you do not change the command and follow the commands in the document.
You could click here to try out.
And this is the App Signing Operation Guide video for reference.
I have the .aab that I'm planning to upload on play store for publish, and before publishing I'm trying a decompile to see which data may be exposed to user in a reverse engineering process.
In .aab_FILES/base/ I see the assets.pb and resources.pb protobuffs - can these files be open some in some way? Cause for the moment I haven't found any method to reveal their content.
I am actually looking to see where are values/strings.xml packed - cause they are missing from .aab_FILES/base/res/ location and I wanna make sure my maps API key (which resides in strings.xml) won't be exposed to users.
The resources.pb is a serialization of the strings data, so they can't be directly extracted to xml.
There are 2 ways to go around this:
Convert from aab to apk
Use bundletool to convert the aab to a universal apk and read the xmls from there:
java -jar bundletool-all-1.8.0.jar build-apks --mode=universal --bundle=~/test.aab --output=~/universal.apks
The universal.apks file can now be unzipped. It contains a universal.apk file, which the resources can be taken from like any apk. The easiest way to get readable xml files from the apk is by using apktool:
apktool d ~/unzipped_universal_apks/universal.apk -o ~/unzipped_universal
The folder ~/unzipped_universal now contains the decoded universal.apk and the xml resources should be decoded and readable inside it.
Read the protobuf values directly from the protobuf file
In order to read a protobuf file, you need its scheme (or proto file).
The proto files for an aab are in the aapt2 repository:
Resources.proto which depends on Configuration.proto.
These files can be compiled to workable code in a number of programming languages. I'll show it using python as described here.
First though, the Resources.proto should be modified to import Configuration.proto from the same folder location instead of the original (unless you create the whole necessary folder structure).
So, change:
import "frameworks/base/tools/aapt2/Configuration.proto";
To:
import "Configuration.proto";
Now, in the terminal, run:
protoc --python_out=~/proto_output Configuration.proto Resources.proto
Inside ~/proto_output there will now be 2 files: Configuration_pb2.py Resources_pb2.py.
These files contain the python code to access the protobuf structure for the resources.pb file, as well as the protobuf encoded AndroidManifest.xml.
In order to read the protobuf file run:
from google.protobuf.json_format import MessageToDict
from Resources_pb2 import ResourceTable
res_obj = ResourceTable()
res_pb_file_path = '~/unzipped_app_bundle/base/resources.pb'
with open(res_pb_file_path, 'rb') as f:
content = f.read()
res_obj.ParseFromString(content)
# converting the protobuf object to a nice dictionary representation
res_dict = MessageToDict(res_obj)
Try this given de-compile jar BundleDecompiler
de-compile option:
java -jar BundleDecompiler.jar decompile --in=input_app.aab --out=output_dir
I would like to share apk file to client. but through mail i don't think it's safe. Is there any other way to share apk file to others?
and what are the steps we have to follow while sharing apk file for safety purpose
You can upload your apk to Google Drive, right click file on Google Drive -> share this file to your client. Then after your client download successfully, you can delete this file from your Google Drive for safe. Hope it help you.
I'd go with encrypting the file:
Zip the file using a strong password (replace the {PASSWORD} argument with it)
tar cpvf app.tar app.apk
7z a -p {PASSWORD} -mx=9 -mhe -t7z app.7z app.tar
Use ECDH for the key (password) exchange (for example use RSA)
Send the file however you want
For decryption use:
7z x test.7z
I planned to change the package name through smali(reverse)
when I open up apktool.yml, I saw this
forced-package-id: '127'
I have tried to change it but it crash
why should i do?
Assuming your goal is to rename the package name of the apk, the package names used for the classes are irrelevant. The package name of the apk is mostly unrelated to the package names of any classes in the apk. And there's no reason you need to touch the package id.
I would recommend unpacking the apk with apktool, and then edit the apktool.yml, setting renameManifestPackage to the new package name. Then when you rebuild the apk with apktool, it should use aapt's --rename-manifest-package functionality to change the package name.
After that, just resign the new apk and you should be good to go.
apktool d app.apk
// change "renameManifestPackage: null" in app/apktool.yml
// to "renameManifestPackage: my.new.package"
apktool b app -o new_app.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/my.keystore new_app.apk mykeyname
And just to reiterate, you don't need to modify the package names of any classes.
To my knowledge there are no fast ways to change the package name.
You have to change the package="com.mycompany.myapp" in Manifest.xml and then manually replace all the package name occurrences in smali files (and folders). Finally edit apktool.yml replacing the old package name, with your new package name.
A full detailed tutorial can be found here: http://forum.xda-developers.com/showthread.php?t=2760965
I've tried different approaches but the most reliable for me has been the method described here:
https://forum.xda-developers.com/t/how-to-guide-mod-change-package-names-of-apks.2760965/
These are the steps:
Decode APK (using apktool)
Edit apktool.yml
Edit AndroidManifest.xml
Rename smali subfolders
Search & Replace *.smali (using Notepad++)
Build APK (using apktool)
Sign APK (using apksigner)
Tools needed:
Apktool - https://ibotpeaches.github.io/Apktool/
Notepad++ - https://notepad-plus-plus.org/downloads/
apksigner - https://developer.android.com/studio/command-line/apksigner
Download apktool and wrapper script to C:\apktool.
Let's assume you want to modify from/to as specified here:
From: XVipreSettings.apk (Package name: com.xvipre.settings)
To: ModdedApp.apk (Package name: com.modded.app)
1. Decode APK (using apktool)
apktool.bat d XVipreSettings.apk
2. Edit apktool.yml
apkFileName: XVipreSettings.apk
...
renameManifestPackage: null
is changed to:
apkFileName: ModdedApp.apk
...
renameManifestPackage: 'com.modded.app'
3. Edit AndroidManifest.xml
package="com.xvipre.settings"
is changed to:
package="com.modded.app"
4. Rename smali subfolders
move .\XVipreSettings\smali\com\xvipre\settings .\XVipreSettings\smali\com\xvipre\app
move .\XVipreSettings\smali\com\xvipre .\XVipreSettings\smali\com\modded
5. Search & Replace *.smali
Start Notepad++
Menu > Search > Find in Files... (Ctrl+Shift+F)
Find what : "Lcom/xvipre/settings"
Replace with : "Lcom/modded/app"
Filters : "*.smali"
Directory : "C:\apktool\XVipreSettings\smali\com"
Press Replace in Files (may take a few minutes)
6. Build APK
apktool.bat b XVipreSettings -o ModdedApp.apk
7. Sign APK
(I'm assuming 31.0.0 here yours may be different, also if you don't want to sign using debug certificate you need to modify this step accordingly)
%homedrive%%homepath%\AppData\Local\Android\Sdk\build-tools\31.0.0\apksigner.bat sign --ks %homedrive%%homepath%\.android\debug.keystore --ks-pass pass:android --key-pass pass:android C:\apktool\ModdedApp.apk
We need to enable our customers to update some components in Android application, like icon/logo, dictionary file etc.
I saw the .APK can be opened like a JAR with 7-zip, and hope files can be edited/replaced there. But it is need to update MANIFEST.MF file in it, containing a digest for each .APK component' like:
Manifest-Version: 1.0
Created-By: 1.0 (Android)
Name: res/raw/icon.png
SHA1-Digest: 6Un2G/VIkYfIGfMxruadIHtDABc=
Name: res/raw/logo.png
SHA1-Digest: zsIQqGWSu9w5m7gsl0jQoziy7JA=
...
How to update these digests?
The SHA1-digest entries are base64-encoded strings of digests computed using SHA1 algorithm. You'll also have to update Cert.rsa and Cert.sf though, the .rsa file contains the actual digital signature. You can start with http://java.sun.com/developer/Books/javaprogramming/JAR/sign/intro.html for more info.