Skip to content

Android 编译使用哪个key签名?

一看Android.mk

在我们内置某个apk的时候都会带有Android.mk,这里面就写明了该APK使用的是什么签名,如:

C
LOCAL_CERTIFICATE := platform

表明使用的是platform签名

C
LOCAL_CERTIFICATE := PRESIGNED

表明使用的是apk原本的签名,记住这里的PRESIGNED需要大写

二看产品自定义秘钥

大部分公司在自定义自己的秘钥的时候,都会做出如下修改

  1. 在产品的mk中指定PRODUCT_DEFAULT_DEV_CERTIFICATE,如:

device/amlogic/产品名/产品名.mk:

C
# android sign key
PRODUCT_DEFAULT_DEV_CERTIFICATE := vendor/xxxx/android-certs/releasekey

# Here is a customization of which key signature to use
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),vendor/xxxx/android-certs/releasekey)
BUILD_KEYS := release-keys
endif
  1. 一旦指定了PRODUCT_DEFAULT_DEV_CERTIFICATE就不会再使用默认的testkey

build/core/config.mk文件:

C
# The default key if not set as LOCAL_CERTIFICATE
ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
  DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
else
  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/make/target/product/security/testkey
endif
.KATI_READONLY := DEFAULT_SYSTEM_DEV_CERTIFICATE

可以看到在没有定义PRODUCT_DEFAULT_DEV_CERTIFICATE的情况下默认使用的是testkey,但是如果我们定义了,就会改换路径为你自定义的路径。

三看编译模式

system/sepolicy/prebuilts/api/30.0/private/keys.conf

C
[@PLATFORM]
ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/platform.x509.pem

[@MEDIA]
ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/media.x509.pem

[@NETWORK_STACK]
ALL : $MAINLINE_SEPOLICY_DEV_CERTIFICATES/networkstack.x509.pem

[@SHARED]
ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/shared.x509.pem

# Example of ALL TARGET_BUILD_VARIANTS
[@RELEASE]
ENG       : $DEFAULT_SYSTEM_DEV_CERTIFICATE/releasekey.x509.pem
USER      : $DEFAULT_SYSTEM_DEV_CERTIFICATE/releasekey.x509.pem
USERDEBUG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/releasekey.x509.pem

不同的编译模式使用了不同的默认密钥

这里很奇怪,DEFAULT_SYSTEM_DEV_CERTIFICATE到底是直接选定了密钥文件还是只是文件存储路径。

总结:

  1. 内置apk,签名要看mk文件中的LOCAL_CERTIFICATE,指定是谁就是谁
  2. 如果没有指定LOCAL_CERTIFICATE,使用的是产品自定义的秘钥以及编译模式
  3. 如果产品没有指定自定义秘钥,那么就是testkey

keystore签名

其实这部分我不是很明白,我这边的需求客户那边的一个apk没有足够的权限,我需要对其使用platform签名以提权。

使用.pem和.pk8的签名

使用.pem和.pk8的签名文件签名的过程很简单,我之前的【生成签名文件release key,通过Android源码对apk进行签名】文章的最后一句就是

C
java -Djava.library.path="prebuilts/sdk/tools/linux/lib64" -jar ./prebuilts/sdk/tools/lib/signapk.jar ./build/make/target/product/security/platform.x509.pem ./build/make/target/product/security/platform.pk8 app.apk app_signed.apk

使用keystore签名

但是使用keystore签名遇到一些麻烦,先是报错,我将apk改成zip然后删掉一个文件夹之后解决。然后签名成功但是安装的时候又爆了一个错,捣鼓半天发现需要v2签名。不能用“jarsigner”

C
adb install signed-anydesk_v4.apk
Performing Streamed Install
adb: failed to install signed-anydesk_v4.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Scanning Failed.: No signature found in package of version 2 or newer for package com.anydesk.anydeskandroid]

错误信息表明在 APK 中找不到版本为 2 或更新的包的签名。

  • v1 方案:基于 JAR 签名,采用的签名工具为 jarsigner
  • v2 方案:APK 签名方案 v2,在 Android 7.0 引入,采用的签名工具为 apksigner
  • v3 方案:APK 签名方案v3,在 Android 9.0 引入,采用的签名工具为 apksigner

我最后换一个命令才终于完成

C
// --ks [签名证书路径]
// --ks-key-alias [别名]
// --ks-pass pass:[KeyStore密码]
//  --key-pass pass:[签署者的密码]
//  --out [output.apk] [input.apk]

java -jar apksigner.jar sign --ks android.keystore --ks-key-alias cmccsdk --ks-pass pass:123456 --key-pass pass:123456 --out output.apk input.apk

完成签名后,可以用以下命令查看APK采用的签名方案。

C
// 验证APK采用的是V1、V2 还是V3签名
apksigner verify -v test.apk

权限-signature 签名权限

签名权限描述:

只有当应用A 与 定义权限的应用B 或 OS 使用相同的证书签名时,系统才会向应用授予签名权限。

img

  1. 应用A 和 应用B 具有相同的证书签名 :两个LOCAL_CERTIFICATE := PRESIGNED 具有相同证书签名应用。

如果应用B先安装的,而且已经申请过权限,(A和B有相同的证书签名)则系统会在不通知用户或征得用户明确许可的情况下,给A应用自动授予这些signature权限。

  1. 应用A 和 系统签名应用

使用platform或者testkey等其他签名

除了签名权限之外还有普通权限,特殊权限,运行时权限,这里推荐

Android 权限(一):权限大全

上次更新于: