平台
Android 7.1 + RK3288
环境
当前的签名文件如下:
build/target/product/security/ -rw-rw-r-- 1 anson anson 260 6月 19 2018 Android.mk -rw-rw-r-- 1 anson anson 1675 6月 19 2018 media.pem -rw-rw-r-- 1 anson anson 1217 6月 19 2018 media.pk8 -rw-rw-r-- 1 anson anson 1440 6月 19 2018 media.x509.pem -rw-rw-r-- 1 anson anson 1675 6月 19 2018 platform.pem -rw-rw-r-- 1 anson anson 1216 6月 19 2018 platform.pk8 -rw-rw-r-- 1 anson anson 1440 6月 19 2018 platform.x509.pem -rw-rw-r-- 1 anson anson 3123 6月 19 2018 README -rw-rw-r-- 1 anson anson 1679 6月 19 2018 shared.pem -rw-rw-r-- 1 anson anson 1218 6月 19 2018 shared.pk8 -rw-rw-r-- 1 anson anson 1440 6月 19 2018 shared.x509.pem -rw-rw-r-- 1 anson anson 1675 6月 19 2018 testkey.pem -rw-rw-r-- 1 anson anson 1216 6月 19 2018 testkey.pk8 -rw-rw-r-- 1 anson anson 1440 6月 19 2018 testkey.x509.pem -rw-rw-r-- 1 anson anson 524 6月 19 2018 verity_key -rw-rw-r-- 1 anson anson 1219 6月 19 2018 verity.pk8 -rw-rw-r-- 1 anson anson 1444 6月 19 2018 verity.x509.pem
对应的几个密钥的用途:
testkey # 普通APK,默认情况下使用 platform # 该APK完成一些系统的核心功能,这种方式编译出来的APK所在进程的UID为system shared # 该APK是media/download系统中的一环 media # 该APK是media/download系统中的一环
build/core/main.mk include $(BUILD_SYSTEM)/config.mk
build/core/config.mk include $(BUILD_SYSTEM)/envsetup.mk DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
testkey 不仅会影响应用的签名, 同时还有打包的固件OTA升级包等.
实现
最简单的方案, 替换掉 build/target/product/security 相关的密钥文件
自定义密钥名, 同时修改Makefile 和 相应的.MK文件
build/core/config.mk: 中DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/mykey
build/core/Makefile: ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/mykey)
关于apk签名,可通过修改Android.mk中的声明修改签名:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := Provision LOCAL_CERTIFICATE := mykey ## 也可定义绝对路径: #LOCAL_CERTIFICATE := build/target/product/security/mykey/mykey LOCAL_PRIVILEGED_MODULE := true LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE)
确认build/target/product/security/mykey相关文件存在, 否则会出现:
ninja: error: 'build/target/product/security/mykey.pk8', needed by 'out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk', missing and no known rule to make it
build/core/package_internal.mk
# Pick a key to sign the package with. If this package hasn't specified # an explicit certificate, use the default. # Secure release builds will have their packages signed after the fact, # so it's ok for these private keys to be in the clear. ifeq ($(LOCAL_CERTIFICATE),) LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE) endif ifeq ($(LOCAL_CERTIFICATE),EXTERNAL) # The special value "EXTERNAL" means that we will sign it with the # default devkey, apply predexopt, but then expect the final .apk # (after dexopting) to be signed by an outside tool. LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE) PACKAGES.$(LOCAL_PACKAGE_NAME).EXTERNAL_KEY := 1 endif # If this is not an absolute certificate, assign it to a generic one. ifeq ($(dir $(strip $(LOCAL_CERTIFICATE))),./) LOCAL_CERTIFICATE := $(dir $(DEFAULT_SYSTEM_DEV_CERTIFICATE))$(LOCAL_CERTIFICATE) endif private_key := $(LOCAL_CERTIFICATE).pk8 certificate := $(LOCAL_CERTIFICATE).x509.pem
从生成的中间ninja->out/build-rk3288-mmm-packages_apps_Provision_Android.mk.ninja
description = target Package: Provision (out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk) command = /bin/bash -c "(touch out/target/product/rk3288/obj/APPS/Provision_intermediates/zipdummy ) && ((cd out/target/product/rk3288/obj/APPS/Provision_intermediates/ && jar cf package.apk zipdummy) ) && (zip -qd out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk zipdummy ) && (rm out/target/product/rk3288/obj/APPS/Provision_intermediates/zipdummy ) && (out/host/linux-x86/bin/aapt package -u -z --pseudo-localize -c zh_CN,en_US,cs_CZ,da_DK,de_AT,de_CH,de_DE,de_LI,el_GR,en_AU,en_CA,en_GB,en_NZ,en_SG,eo_EU,es_ES,fr_CA,fr_CH,fr_BE,fr_FR,it_CH,it_IT,ja_JP,ko_KR,nb_NO,nl_BE,nl_NL,pl_PL,pt_PT,ru_RU,sv_SE,tr_TR,zh_CN,zh_HK,zh_TW,am_ET,hi_IN,en_US,en_AU,en_IN,fr_FR,it_IT,es_ES,et_EE,de_DE,nl_NL,cs_CZ,pl_PL,ja_JP,zh_TW,zh_CN,zh_HK,ru_RU,ko_KR,nb_NO,es_US,da_DK,el_GR,tr_TR,pt_PT,pt_BR,sv_SE,bg_BG,ca_ES,en_GB,fi_FI,hi_IN,hr_HR,hu_HU,in_ID,iw_IL,lt_LT,lv_LV,ro_RO,sk_SK,sl_SI,sr_RS,uk_UA,vi_VN,tl_PH,ar_EG,fa_IR,th_TH,sw_TZ,ms_MY,af_ZA,zu_ZA,am_ET,en_XA,ar_XB,fr_CA,km_KH,lo_LA,ne_NP,si_LK,mn_MN,hy_AM,az_AZ,ka_GE,my_MM,mr_IN,ml_IN,is_IS,mk_MK,ky_KG,eu_ES,gl_ES,bn_BD,ta_IN,kn_IN,te_IN,uz_UZ,ur_PK,kk_KZ,sq_AL,gu_IN,pa_IN,be_BY,bs_BA -M packages/apps/Provision/AndroidManifest.xml -I out/target/common/obj/APPS/framework-res_intermediates/package-export.apk --min-sdk-version 25 --target-sdk-version 25 --product tablet --version-code 25 --version-name 7.1.2 --skip-symbols-without-default-localization -F out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk ) && (find out/target/common/obj/APPS/Provision_intermediates/ -maxdepth 1 -name \"classes*.dex\" | sort | xargs zip -qjX out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk ) && (if [ -d out/target/common/obj/APPS/Provision_intermediates/jack-rsc ] ; then find out/target/common/obj/APPS/Provision_intermediates/jack-rsc -type f | sort | sed -e \"s?^out/target/common/obj/APPS/Provision_intermediates/jack-rsc/? -C \\\"out/target/common/obj/APPS/Provision_intermediates/jack-rsc\\\" \\\"?\" -e \"s/\$$/\\\"/\" > out/target/product/rk3288/obj/APPS/Provision_intermediates/jack_res_jar_flags; if [ -s out/target/product/rk3288/obj/APPS/Provision_intermediates/jack_res_jar_flags ] ; then jar uf out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk @out/target/product/rk3288/obj/APPS/Provision_intermediates/jack_res_jar_flags; fi; fi ) && (mv out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk.unsigned ) && (java -Djava.library.path=out/host/linux-x86/lib64 -jar out/host/linux-x86/framework/signapk.jar --min-sdk-version \ $$((out/host/linux-x86/bin/aapt dump badging out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk.unsigned 2>&1 | grep '^sdkVersion' || echo \"sdkVersion:'0'\") | cut -d\"'\" -f2 | sed -e s/^.*[^0-9].*\$$/25/) build/target/product/security/mykey.x509.pem build/target/product/security/mykey.pk8 out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk.unsigned out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk.signed ) && (mv out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk.signed out/target/product/rk3288/obj/APPS/Provision_intermediates/package.apk )"
可以看出, 编译系统会去找build/target/product/security/mykey.x509.pem, build/target/product/security/mykey.pk8
扩展
android系统release签名
Android OTA releasekey 替换
Android系统build阶段签名机制
Manually generating keys 创建密钥
方法1:
development/tools/make_key testkey '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
方法2:
# generate RSA key openssl genrsa -3 -out temp.pem 2048 Generating RSA private key, 2048 bit long modulus ....+++ .....................+++ e is 3 (0x3) # create a certificate with the public part of the key openssl req -new -x509 -key temp.pem -out releasekey.x509.pem -days 10000 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com' # create a PKCS#8-formatted version of the private key openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt # securely delete the temp.pem file shred --remove temp.pem
Android签名生成和互转
打印编译时的环境变量:
build/core/dumpvar.mk print_build_config_vars := \ PLATFORM_VERSION_CODENAME \ PLATFORM_VERSION \ TARGET_PRODUCT \ TARGET_BUILD_VARIANT \ TARGET_BUILD_TYPE \ TARGET_BUILD_APPS \ TARGET_ARCH \ TARGET_ARCH_VARIANT \ TARGET_CPU_VARIANT \ TARGET_2ND_ARCH \ TARGET_2ND_ARCH_VARIANT \ TARGET_2ND_CPU_VARIANT \ HOST_ARCH \ HOST_2ND_ARCH \ HOST_OS \ HOST_OS_EXTRA \ HOST_CROSS_OS \ HOST_CROSS_ARCH \ HOST_CROSS_2ND_ARCH \ HOST_BUILD_TYPE \ BUILD_ID \ OUT_DIR ifneq ($(filter report_config,$(DUMP_MANY_VARS)),) # Construct the shell commands that print the config banner. report_config_sh := echo '============================================'; report_config_sh += $(foreach v,$(print_build_config_vars),echo '$v=$($(v))';) report_config_sh += echo '============================================'; endif
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=7.1.2 TARGET_PRODUCT=rk3288 TARGET_BUILD_VARIANT=userdebug TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon TARGET_CPU_VARIANT=cortex-a15 TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_2ND_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=Linux-4.15.0-64-generic-x86_64-with-Ubuntu-16.04-xenial HOST_CROSS_OS=windows HOST_CROSS_ARCH=x86 HOST_CROSS_2ND_ARCH=x86_64 HOST_BUILD_TYPE=release BUILD_ID=NHG47K OUT_DIR=out BUILD_SYSTEM=build/core ============================================
build/core/Makefile
# The "test-keys" tag marks builds signed with the old test keys, # which are available in the SDK. "dev-keys" marks builds signed with # non-default dev keys (usually private keys from a vendor directory). # Both of these tags will be removed and replaced with "release-keys" # when the target-files is signed in a post-build step. ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey) BUILD_KEYS := test-keys else BUILD_KEYS := dev-keys endif ifeq ($(TARGET_BUILD_VARIANT),user) BUILD_KEYS := release-keys endif
判断编译所使用的密钥, 并会显示设置 > 关于设备 > 版本号末尾, 如:XXX-userdebug 7.1.2 NHG47K eng.XXX.20191125.144140 test-keys