Android understand/generate/use/view signatures (V1-V4)

This article mainly provides a more detailed explanation of the android signature part, aiming to understand the overall usage system of signatures and the common usage of keytool and apksigner, focusing on practical significance.

1 Understanding of signature (V1 V2 V3 V4 signature)

In Android application signatures, V1 V2 V3 V4 signatures are different signature schemes. The specific descriptions are as follows:

  • V1 Signature (JAR Signature): The basic form of early Android app signing, based on the Java Signature (JAR Signature) specification. It signs your app’s entire APK file as a whole, including all of the app’s contents (including manifest files, resource files, code files, etc.). V1 signatures use MD5 and SHA1-based hashing algorithms, and RSA or DSA encryption algorithms.
  • V2 Signing (APK Signing Scheme v2+): A new signing scheme introduced in Android 7.0 (API level 24) and higher. It uses an incremental signing method that only signs parts of the APK content rather than the entire APK file. This incremental signing provides better signing efficiency and verification performance without compromising the integrity of the APK. V2 signatures use a SHA256-based hash algorithm and are signed using ECDSA (Elliptic Curve Digital Signature Algorithm). It also provides mechanisms for verification and integrity checking of APK files to ensure that the APK has not been tampered with during transfer and installation. V2 signatures are enhancements to V1 signatures, not mutually exclusive. On devices that support V2 signatures, the application will contain both V1 and V2 signature schemes to ensure compatibility and verification methods on various devices. V2 signature is an enhancement scheme introduced based on V1 signature, providing better efficiency and security.
  • V3 Signing (APK Signing Scheme v3+): A new signing scheme introduced in Android 9.0 (API level 28) and higher. It is a further enhancement to the V2 signature. V3 signatures use a more powerful signature algorithm (based on RSA or ECDSA) and longer key lengths to provide greater security. V3 signature is similar to V2 signature. It still uses incremental signature and only signs part of the APK content. V3 signatures are similar to V2 signatures in terms of verification and integrity checks, but they also provide some additional security features, such as integrity protection of the signature block and additional timestamps of the signature. It should be noted that V3 signature is optional, and the application can contain V1, V2 and V3 signature schemes at the same time. The introduction of V3 signatures further improves application security and verification mechanisms while ensuring compatibility with older Android devices. Developers can choose to use V3 signatures when building their applications to increase their application’s security level.
  • V4 Signing (APK Signing Scheme v4+): Introduced in Android 11.0 to support ADB incremental APK installation. v4 signatures are based on a Merkle hash tree calculated from all bytes of the APK. It follows the structure of the fs-verity hash tree exactly (e.g., zero-padding the salt, and zero-padding the last chunk.) Android 11 stores signatures in a separate [apk name].apk.idsig file. v4 signatures need to be supplemented by v2 or v3 signatures. When running the adb install –incremental command, adb requires the .apk.idsig file to exist next to the .apk. By default, it also attempts an incremental installation using the .idsig file; if this file is missing or invalid, the command falls back to a regular installation.

Application signature | The corresponding official document link is as follows:

  • Overview of signatures: android official documentation Overview
  • V2 signature: android official document V2 signature
  • V3 signature: android official document V3 signature
  • V4 signature: android official document V4 signature

These official documents make it easier to understand application signing.

2 Signature generation

2.1 Introduction to keytool tool

Signatures are mainly generated through Android Studio/keytool (common signatures) or Android Framework (mainly for system signatures). Keytool here is a tool in the Android Development Kit (Android SDK), used to generate and manage digital certificates, key pairs, and certificate requests. It is a command line tool used to perform key and certificate related operations such as creating key stores, generating key pairs, exporting certificates, etc.

Some common uses and features of Android Keytool are as follows:

  • Generate key pairs: Android Keytool can generate public and private key pairs, which can be used for operations such as encryption, decryption, and digital signatures.
  • Create a key store: Keytool can create a key store file (KeyStore), which is an encrypted container for storing keys and certificates. The key store can be a separate file or the operating system’s keystore.
  • Manage certificates: Use Keytool to manage digital certificates, including viewing certificate details, exporting certificates, importing certificates, etc. Certificates are commonly used to verify digital signatures and establish secure connections.
  • Generate certificate request: Keytool can generate a certificate request (Certificate Signing Request, CSR) to apply for a digital certificate from the certificate authority (Certificate Authority, CA). A CSR contains information about an entity (such as an application or website) so that the CA can verify and issue the appropriate certificate.
  • Import and export key pairs: Keytool allows exporting key pairs to files for use in other systems. It can also import other system-generated key pairs for use in Android applications.
  • Verify certificate chains: Keytool can verify certificate chains, which are hierarchies consisting of multiple certificates. It can verify the validity, integrity and legality of certificates.

2.2 Collection of common keytool commands

2.2.1 Generate key pair

$keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore keystore.jks
-genkeypair: command to generate a key pair.
-alias myalias: Specifies the alias myalias of the key pair.
-keyalg RSA: Specify the key algorithm as RSA algorithm.
-keysize 2048: Specifies the key length to be 2048 bits.
-validity 365 valid for 365 days, default 90 days
-keystore keystore.jks: Specifies the keystore file name keystore.jks. 

2.2.2 Export certificate

$keytool -exportcert -alias myalias -keystore keystore.jks -file certificate.crt
-exportcert: command to export certificate.
-alias myalias: Specifies the alias of the certificate to be exported.
-keystore keystore.jks: Specifies the keystore file name keystore.jks.
-file certificate.crt: Specifies the name of the exported certificate file certificate.crt. 

2.2.3 Import certificate

$keytool -importcert -alias myalias -file certificate.crt -keystore keystore.jks
-importcert: command to import certificates.
-alias myalias: Specifies the alias of the certificate to be imported.
-file certificate.crt: Specifies the certificate file name to be imported as certificate.crt.
-keystore keystore.jks: Specifies the keystore file name keystore.jks. 

2.2.4 List entries in the keystore

$keytool -list -keystore keystore.jks
-list: Command to list entries in the keystore.
-keystore keystore.jks: Specifies the keystore file name to be listed as keystore.jks. 

2.2.5 View certificate details

$keytool -printcert -file certificate.crt
-printcert: Command to view certificate details.
-file certificate.crt: Specify the certificate file name to be viewed as certificate.crt. 

2.2.6 View signing certificate details

Use the tool keytool to view the apk signature. The usage method is as follows:

$keytool -printcert -jarfile XXX.apk

If it is not signed or signed with a weak algorithm disabled by keytool, it will be displayed:

$keytool -printcert -jarfile XXX.apk
Not a signed jar file

If signed, it will be displayed:

$keytool -printcert -jarfile XXX.apk
Signed by #1:

Certificate #1:
Owner: CN=XXX, OU=XXX, O=XXX, L=xxx, ST=xxx, C=XXX
Posted by: CN=XXX, OU=XXX, O=XXX, L=xxx, ST=xxx, C=XXX
Serial number: 706e325f
Effective time: Fri Jun 04 13:59:30 CST 2021, Expiration time: Sun May 11 13:59:30 CST 2121
Certificate fingerprint:
     SHA1: 67:DC:CE:BD:3E:BB:67:AD:A4:CC:D6:65:B3:1C:2A:33:4F:B0:74:89
     SHA256: 92:93:EE:B8:A3:4B:57:3D:32:0E:F7:D2:52:80:4A:74:E0:BB:16:00:11:7E:6E:B4: 80:41:6B:FA:E4:6D:D5:EF
Signature algorithm name: SHA256withRSA
Principal public key algorithm: 2048-bit RSA key
Version: 3

Extension:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 54 0C 4B 25 7D 3D E1 2D 1E 1C 9F 93 BE 1D 39 08 T.K%.=.-......9.
0010: 14 8E 32 00 ..2.
]
]

Note: If you use a higher version of keytool here, the signatures of V1 and V2 may display “not a signed jar file”, but V3 will display normally.

3 Using tool signatures

3.1 Introduction to apksigner

apksigner is a command line tool provided in the Android SDK for digital signing of Android applications (APK). It is designed to ensure the integrity and security of APKs during publishing and installation.

Some of the main features and functions of apksigner are as follows:

  • Digital signature: apksigner uses the developer’s private key to digitally sign the APK. Digital signatures are a security mechanism used to verify the origin and integrity of APKs. Signed APKs prevent unauthorized modification and tampering, and provide a trust mechanism that enables users to verify the authenticity of the APK.
  • Supports multiple signature schemes: apksigner supports using different signature schemes to sign APKs, including old JAR signatures (JAR Signature Scheme v1) and modern APK signature schemes (APK Signature Scheme v2 +). The latter is the recommended signature scheme for Android 7.0 and higher, which provides better security and verification capabilities.
  • Verify signature: apksigner can verify the signature information of the signed APK, including signature scheme, certificate chain, certificate fingerprint, etc. This ensures that the APK has not been tampered with during release and transmission, and that the source of the APK can be verified.
  • Automatic optimization: apksigner can automatically optimize APK to reduce APK size and improve running performance. It can delete unused resources, compress files, optimize dex files, etc., thereby reducing the size of the APK.
  • Compatibility: apksigner is compatible with Android systems and consistent with Google Play Store requirements. apksigner is required when uploading an APK to the Google Play Store for publishing as Google Play requires the APK to be digitally signed.
  • Automated/Manual Build: Executed automatically as part of the build tool, or can be run manually to sign and verify an existing APK.

3.2 Common commands for signing

Use apksigner tool for V1 V2 V3 V4 signing. The apksigner.jar/apksigner tool is a command in the tool that comes with Android and is placed in the Sdk/build-tools/$version number/ directory.

The early version of apksigner is a jar package. The apksigner.jar file and xxx.jks are used to sign the application. The specific operations are as follows:

$java -jar apksigner.jar sign --ks xxx.jks --ks-key-alias xxx1 --ks-pass pass:xxx2 --key-pass pass:xxx3 --out [File generated after signing /out output parameters] [files requiring signature/in input parameters]

Later it was changed to apksigner executable file. The specific operations are as follows:

$apksigner sign --ks xxx.jks --ks-key-alias xxx1 --ks-pass pass:xxx2 --key-pass pass:xxx3 --out [File/out output parameters generated after signing] [File requiring signature/in input parameters]

3.3 Interpretation of key parameters of apksigner (sign and verify subcommands)

3.3.1 Detailed interpretation of sign parameters

If you need to re-sign/change the signature, just replace the jks file directly. The parameters involved here are described as follows:

--ks xxx.jks keystore name
--ks-key-alias xxx1 Key alias, if the keystore has a key pair, it can be omitted, otherwise it must be selected
--ks-pass pass:xxx2 Password to unlock the keystore file
--key-pass pass:xxx3 Password to unlock private key

For signed ones you can also set up a signed version solution as follows:

--v1-signing-enabled Whether to enable V1 signing, enabled by default
--v2-signing-enabled Whether to enable V2 signing, enabled by default
--v3-signing-enabled Whether to enable V3 signing, enabled by default
--v4-signing-enabled Whether to enable V4 signing, enabled by default

For other sign commands, you can use apksigner sign –help to view.

3.3.2 Detailed interpretation of verify parameter

Commonly used parameters are described as follows:

-v The value of output signature mode V1/V2/V3/V4 is not true/false
--print-certs Print signature details

The specific usage is as follows:

#The output here represents the V2 signature
$apksigner verify -v xxx1.apk
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): false
Number of signers: 1

#The output here represents the V1 + V2 + V3 signature
$apksigner verify -v xxx1.apk
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true
Verified using v3 scheme (APK Signature Scheme v3): true
Number of signers: 3

#Print the detailed information of cert here
apksigner verify --print-certs xxx.apk
Signer #1 certificate DN: CN=xxx1, OU=xxx2, O=xxx3, L=xxx, ST=xxx, C=xxx
Signer #1 certificate SHA-256 digest: 6793eeb8a34b573d320ef7d25208a474e0bb1600117e6e4b80416bfae46dd5fe
Signer #1 certificate SHA-1 digest: 24dc9cbd3ebb67ada4bdd665b31c2a994fb07444
Signer #1 certificate MD5 digest: 1252800c8673bd059951fcaf66a5b91c

#Use parameters -v and --print-certs at the same time to print more comprehensive information
$apksigner verify -v --print-certs xxx.apk
Verifies
Verified using v1 scheme (JAR signing): false
Verified using v2 scheme (APK Signature Scheme v2): false
Verified using v3 scheme (APK Signature Scheme v3): true
Number of signers: 1
Signer #1 certificate DN: CN=xxx1, OU=xxx2, O=xxx3, L=xxx4, ST=xxx5, C=xxx6
Signer #1 certificate SHA-256 digest: 6793eeb8a34b573d320ef7d25208a474e0bb1600117e6e4b80416bfae46dd5fe
Signer #1 certificate SHA-1 digest: 24dc9cbd3ebb67ada4bdd665b31c2a994fb07444
Signer #1 certificate MD5 digest: 1252800c8673bd059951fcaf66a5b91c
Signer #1 key algorithm: RSA
Signer #1 key size (bits): 2048
Signer #1 public key SHA-256 digest: 39e722630a16ebbc200a1cac68b2ac6689ae9f56bff911c229ef2a81f5c24b5c
Signer #1 public key SHA-1 digest: 5b9b6707d59e3aee0f844830cc3cc7074499fe2f
Signer #1 public key MD5 digest: 36cdbb8876ef2ffc59dcafeb59f26810

For other verify commands, you can use apksigner verify –help to view.