How to update digests in Android MANIFEST.MF? - android

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.

Related

Where does Android store the platform, shared, media and release keys in the final Android OS image

Does anyone have any idea where the public keys used for signing (platform, shared, media and release key ) stored in the final generated Android OS image?
The 'Signing Builds for Release' ( https://source.android.com/devices/tech/ota/sign_builds ) page provides information on how Android OS images are signed.
The standard Android build uses four keys, all of which reside in build/target/product/security:
testkey: Generic default key for packages that do not otherwise specify a key. Used for development builds
releasekey: Generic default key for packages that do not otherwise specify a key.Used for release builds
platform: Test key for packages that are part of the core platform.
shared: test key for things that are shared in the home/contacts process.
media: Test key for packages that are part of the media/download system.
The public keys (releasekey.x509.pem, platform.x509.pem, shared.x509.pem, media.x509.pem) associated with the above private keys need to be included as part of the Android image.
These are provided as part of the build process and generally stored in build/target/product/security on the host used to build the Android OS image
However, what is not provided is where the public keys used for signing are located in the generated OS image.
For example when dm-verity is used, the RSA-2048 key in libmincrypt-compatible format is stored in the /boot partition at /verity_key.
They are not stored directly, but are stored as part of signed apk which are already part of system image. PackageManager parses them and store them in
/data/system/packages.xml.
In that xml you see tags like:
public-key identifier
Which contains public key of all apks.
In case you already have some apk which is also on device, you can unzip it.
// To get public key from apk
openssl pkcs7 -inform DER -print_certs -out cert.pem -in CERT.RSA
openssl x509 -in cert.pem -pubkey -noout
This will be same as one of public keys stored in packages.xml
Apart from this in device at /etc/security/mac_permissions.xml there are signatures which tell that app with certain signature below to certain SE context.
You can read its details at
http://androidxref.com/7.1.1_r6/xref/system/sepolicy/README
OTA certificates are stored at /etc/security/otacerts.zip which is used by recovery system.

Can you force jarsigner to us forwards slashes

I have an android APK file, which I need to unzip, replace one file, re-sign using jarsigner and then zipalign to a valid apk.
The app installs without errors, but when run it cannot find the first thing it looks for in the /assets/ folder. The required file is definitely in the apk, in the right place etc.
"An error has occurred in sub:main_activity_create(Jave line:375) java.io.FileNotFoundException:control.bal"
The differences I can see is that the original Manifest.MF file has forward slashes, but when I run jarsigner on the server it creates a new manifest.mf with backward slashes. Is there a way of making jarsigner use forward slashes?
Code is C# .NET running on an Azure server.
Orignal Manifest.MF format
Manifest-Version: 1.0
Created-By: 1.8.0_112 (Oracle Corporation)
Name: assets/longblackbar.png
SHA1-Digest: 1Fq7U1Y/dLAVflFmTzLcC0tvKu4=
Re-signed Manifest.MF format
Manifest-Version: 1.0
Created-By: 1.7.0_51 (Oracle Corporation)
Name: assets\longblackbar.png
SHA1-Digest: vaky9S8cGhJIvh7a4LmmtWOpqAg=
Turns out the answer is that the C# ZipFileExtensions method is the cause of the problem, creating backslashes. If I replace that with running 7za.exe as a process then forward slashes are used, and thereafter everything works fine.

Changing the package name

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

android ant build: debug and release targets

According to the 'help' target documentation:
debug: builds the applications and
signs it with a debug key
release; builds the application: the
generated APK file must be signed
before it is published
Here is what I found, which is a bit different than what I expected:
debug: ignores keystore definitions in build.properties whether you specify them or not. Which kesystore file is it using? The same as Eclipse: the default debug.keystore file in your Documents and Settings?
It creates two files:
-debug-unaligned.apk (signed, unaligned)
-debug.apk (signed, aligned)
release: 'help' says it doesn't sign it. It creates these files:
-unsigned.apk (unsigned, unaligned)
The next two are only if you have the values specified in build.properties:
-unaligned.apk (signed, unaligned)
-release.apk (signed, aligned)
Any helpful comments / verifications will be greatly appreciated.
Which kesystore file is it using? The same as Eclipse: the default debug.keystore file in your Documents and Settings?
Yes.
As far as the release target goes, you will get behaviour like this:
If you have lines like:
key.store=c:/users/me/my-release-key.keystore
key.alias=release_alias
key.store.password=myStorePassword
key.alias.password=myAliasPassword
in your build.properties, it will automatically build and sign your apk with no prompting for anything.
If you comment out the last two lines, then it will prompt you for the passwords, then complete a signed build if the passwords are OK.
If you don't have any of the above lines, then it will just build you an unsigned apk with no prompting for anything and end with:
-release-nosign:
[echo] No key.store and key.alias properties found in build.properties.
[echo] Please sign C:\dev\projects\AntBuilds\MyProject\bin\MyProject-unsigned.apk manually
[echo] and run zipalign from the Android SDK tools.
.
This answer works for me, I am using ant to auto-compile android app, it prompts and need password, I wrote one file named password, and using the command ---ant release < passwd,
However, it also prompts that I need input password.
Using the tips here
key.store=c:/users/me/my-release-key.keystore
key.alias=release_alias
key.store.password=myStorePassword
key.alias.password=myAliasPassword
I solved this problem.

How does an .apk files get signed

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.

Categories

Resources