Android APK 签名信息查看及系统签名处理

16,511 阅读5分钟

前言

在日常的 Android 应用开发过程中,我们常常会涉及到应用签名相关的问题。例如地图、语音识别等第三方 SDK 会对 APK 签名进行一些检验的操作;在系统应用开发中,没有系统签名系统相关的权限就无法调用相关 API ,因此我们要懂得如何查看 APK 签名信息,如何为 APK 进行签名、如何获取系统签名。该文章主要包含以下内容:

  • 签名文件信息查看
  • APK 签名信息查看
  • APK 签名/重新签名、获取系统签名的方式
  • 编译过程添加系统签名信息

查看签名密钥信息

  • keystore/jks 格式密钥库。keytool 为 JDK 里的一个命令行工具,正常情况下安装好 JDK 并配置好环境变量就可以直接调用

     keytool -list -v -storepass 密钥库密码 -keystore  密钥库文件路径
    

    以查看默认的 debug.keystore 签名信息为例,通常打包 debug 类型的 APK 默认采用该文件的签名信息进行签名。windows 中的位置位于 C:\Users\用户名\.android\debug.keystore , *unix 系统位置 ~/.android/debug.keystore

    使用 win+r 输入 powershell 进入命令行操作界面

    PS C:\Users\jacknic>cd  .\.android\
    PS C:\Users\jacknic\.android> keytool -list -v -storepass android -keystore .\debug.keystore
    密钥库类型: jks
    密钥库提供方: SUN
    
    您的密钥库包含 1 个条目
    
    别名: androiddebugkey
    创建日期: 2020-6-28
    条目类型: PrivateKeyEntry
    证书链长度: 1
    证书[1]:
    所有者: EMAILADDRESS=android@android.com...
    发布者: EMAILADDRESS=android@android.com...
    序列号: b3998086d056cffa
    有效期为 Wed Apr 16 06:40:50 CST 2008Sun Sep 02 06:40:50 CST 2035
    证书指纹:
             MD5:  8D:DB:34:2F:2D:A5:40:84:02:D7:...
             SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7...
             SHA256: C8:A2:E9:BC:CF:59:7C:2F:B6:DC:66:BE:E2:93:FC:13:...
    ...
    
  • 查看pem证书信息 (platform.pk8,platform.x509.pem)

    C:\Users\jacknic>keytool.exe  -printcert -v -file platform.x509.pem
    所有者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
    发布者: EMAILADDRESS=android@android.com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
    序列号: b3998086d056cffa
    有效期为 Wed Apr 16 06:40:50 CST 2008 至 Sun Sep 02 06:40:50 CST 2035
    证书指纹:
             MD5:  8D:DB:34:2F:2D:A5:40:84:02:D7:56:8A:F2:1E:29:F9
             SHA1: 27:19:6E:38:6B:87:5E:76:AD:F7:00:E7:EA:84:E4:C6:EE:E3:3D:FA
             SHA256: C8:A2:E9:BC:CF:59:7C:2F:B6:DC:66:BE:E2:93:FC:13:F2:FC:47:EC:77:BC:6B:2B:0D:52:C1:1F:51:19:2A:B8
    签名算法名称: MD5withRSA (弱)
    主体公共密钥算法: 2048 位 RSA 密钥
    版本: 3
    
    扩展:
    
    #1: ObjectId: 2.5.29.35 Criticality=false
    ...
    
  • 查看 APK 文件签名信息

    使用 keytool 工具

    keytool -list -printcert -jarfile D:\path\app.apk
    

    只有 v1 版本的签名 APK 可能要解压出 META-INF/CERT.RSA 然后查看签名信息

    keytool -printcert -file CERT.RSA
    

    使用 Jadx 工具

    Jadx 是一个非常强大的 Java & Android 反编译器,用来查看 APK 文件的各种信息也很方便。使用 Jadx 打开 APK 文件后在侧边栏中选中 APK signatureCertificate/证书选项即可查看 APK 的签名信息。

  • 查看编译签名配置信息

    通常的应用开发都是使用 Gradle 构建的,可以通过命令行执行相应的 task 查看打包签名信息。打开命令行窗口,并切换到 android 项目所在目录。执行以下命令:

    Windows 执行 .\gradlew.bat signingReport

    PS D:\dev\android\personal\android-actions-demo> .\gradlew.bat signingReport
    > Task :app:signingReport
    Variant: releaseUnitTest
    Config: release
    Store: D:\dev\android\personal\android-actions-demo\keystore.jks
    Alias: key
    ----------
    Variant: release
    Config: release
    Store: D:\dev\android\personal\android-actions-demo\keystore.jks
    Alias: key
    ----------
    Variant: debugUnitTest
    Config: debug
    Store: C:\Users\jacknic\.android\debug.keystore
    Alias: AndroidDebugKey
    MD5: 8D:DB:34:2F:2D:A5:40:84...
    SHA1: 27:19:6E:38:6B:87:5E:76:AD:...
    SHA-256: C8:A2:E9:BC:CF:59:7C:2F:B6:DC...
    Valid until: 203592日 星期日
    ...
    

    *unix 执行 ./gradlew signingReport 注意可执行权限问题,

    /d/dev/android/personal/android-actions-demo (master)
    $ ./gradlew signingReport
    > Task :app:signingReport
    Variant: debugUnitTest
    Config: debug
    ...
    
  • Android Studio 中查看应用签名信息

    在已打开的项目中在窗口的右上方点击 Gradle -> Tasks -> android -> signingReport ,在窗口底部 Run 选项卡中即可看到输出的签名信息。

APK 签名操作

  • 对 APK 进行签名/重新签名

    我们可以使用 apksigner 工具进行 APK 的签名/重新签名操作。apksigner 工具在 Android SDK 文件夹的 build-tools/x.x.x/apksigner.bat 。在 studio 中可以通过快捷键 ctrl+alt+shift+s 打开项目结构(Project Structure)窗口,选择 SDK Location 查看 Android SDK 所在位置。

    密钥库签名 可通过参数指定密钥库密码

    apksigner sign --ks release.jks app.apk
    

    例如:

    PS C:\Users\jacknic> D:\soft\Android\sdk\build-tools\29.0.3\apksigner.bat sign --ks D:\dev\android\personal\android-actions-demo\keystore.jks C:\Users\jacknic\Desktop\app.apk
    Keystore password for signer #1: 输入密钥库密码
    

    证书与私钥签名

    apksigner sign --key key.pk8 --cert cert.x509.pem app-name.apk
    

    例如:

    PS C:\Users\jacknic\Desktop\apksigner> java -jar .\apksigner.jar sign --key .\platform.pk8 --cert .\platform.x509.pem  --out signed-app.apk  C:\Users\jacknic\Desktop\aaaa.apk
    

    常用参数说明

    参数名说明
    --ks Java 的密钥库文件
    --ks-pass 包含签名者私钥和证书的密钥库的密码,不指定默认手动输入
    --key 包含签名者私钥的文件的名称
    --cert 包含签名者证书链的文件的名称。此文件必须使用 X.509 PEM 或 DER 格式。
    --ks-key-alias 如果与签名者关联的密钥库包含多个密钥,则必须指定此选项
    --out 您将要保存已签名 APK 的位置。

    详细命令使用与参数说明查看 apksigner 官方文档

进行系统签名

  • 获取系统签名

    在编译系统的时候,系统相关的证书与私钥已存在了,在日常的开发中系统的编译,应该是由相关的系统工程师管理的。具体位置可参考 AOSP/LineageOS 项目build/target/security中的相关文件。可在下面的连接进行查看,AOSP 的签名就是 Android Studio 自带模拟器(非 Google APIs 镜像)的系统签名。

    github.com/LineageOS/a…

    主要是私钥 platform.pk8 和证书 platform.x509.pem ,根据 证书与私钥签名 签名方式我们可以对相应的 APK 进行签名,使得 App 拥有系统签名。

  • 另一种方式,在编译 Android 系统源码的时候,编译过程中会自动为某些指定 APK 进行重新签名操作,使其拥有系统签名。

keystore/jks 密钥库生成

有了证书与私钥,为了安全和方便开发,我们可以生成密钥库。使用命令行或 keytool-importkeypair 工具生成密钥库,该工具只能在 shell 中执行,如果是*unix系统打开命令行终端即可,如果是 windows 但安装了 Git ,可以使用其内置的 bash 执行。 打开 git bash ,windows下通常可以在文件目录中 点击右键 -> Git Bash Here 打开命令行,并执行下面的命令

  1. 命令行生成
# 需在shell里执行,依赖OpenSSL,在这里修改文件路径及密码等信息 
keystore="platform.jks"
pk8="platform.pk8"
cert="platform.x509.pem"
alias="platform"
passphrase="123456"
key="key"
p12="p12"

# Convert PK8 to PEM KEY
openssl pkcs8 -inform DER -nocrypt -in "${pk8}" -out "${key}"

# Bundle CERT and KEY
openssl pkcs12 -export -in "${cert}" -inkey "${key}" -out "${p12}" -password pass:"${passphrase}" -name "${alias}"

# Print cert
echo -n "Importing \"${alias}\" with "
openssl x509 -noout -fingerprint -in "${cert}"

# Import P12 in Keystore
keytool -importkeystore \
-deststorepass "${passphrase}" -destkeystore "${keystore}" -deststoretype PKCS12 \
-srckeystore "${p12}" -srcstoretype PKCS12 -srcstorepass "${passphrase}"

# keytool -importkeystore -srckeystore demo.jks -destkeystore demo.jks -deststoretype pkcs12

  1. 使用 keytool-importkeypair 生成
./keytool-importkeypair.sh -k ./debug_app.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias androiddebugkey

执行该命令之后,在目录下就生成名为 debug_app.keystore 的密钥库。

Gradle 编译过程中进行系统签名

  • 指定 release 类型签名信息

    android{
     ...
        signingConfigs {
            release {
                // debug_app.keystore 文件位于工程根目录即与 app 目录同级
                storeFile rootProject.file('debug_app.keystore')
                keyAlias 'androiddebugkey'
                keyPassword 'android'
                storePassword 'android'
            }
        }
        buildTypes {
            release {
                minifyEnabled true
                shrinkResources true
                signingConfig signingConfigs.release
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        ...
    }
    
  • 指定 debug 类型签名信息

    通常 debug 类型的 APK 是采用默认的签名信息是 用户目录下\.android\debug.keystore ,我们使用 Android Studio 直接运行和安装的 APK 也是附带这个签名信息。通过修改 debug 签名配置,我们在 Studio 直接运行的 App 也能具有系统签名

    android {
    
        defaultConfig {
        ...
           // 主要配置
            signingConfig signingConfigs.debug
        }
    
        signingConfigs {
            debug {
                keyAlias "androiddebugkey"
                keyPassword "android"
                storePassword "android"
                storeFile rootProject.file('debug_app.keystore')
            }
        }
        buildTypes {
    	...
            debug {
                signingConfig signingConfigs.debug
            }
        }
    }
    

总结

在日常的应用开发中,了解 Gradle 和 APK 的构建流程并对相关子流程进行配置,可以简化一些开发流程提高效率。

APK构建流程

思维拓展

参考资料