Android 系统签名密钥替换记录

前言

在 Android 项目的开发过程中,为了防止其他未经过允许的应用安装到本机中,可以通过自定义签名文件实现。系统原生自带默认的签名密钥,厂商可以创建自己的签名密钥来替换原生的密钥文件。应用通过厂商签名文件签名,安装时会对应用进行验签,验签通过后才允许安装到本机中。

文章中将会总结以下内容

系统签名文件相关内容

​ 介绍系统签名文件

​ 如何创建系统签名文件

​ 如何替换系统签名文件

​ 替换签名文件后的影响

应用如何使用签名文件

已签名的应用如何使用工具重新签名

正文

1 系统签名

Android 操作系统通过系统签名在两个地方使用加密签名:

  • 镜像中的 apk 应用文件必须经过签名。此情况有两种场景。

场景一:在系统更新应用时,必须使用与旧引用相同的密钥对其签名,才能存取旧应用的数据。无论是通过覆盖 apk 的方式更新应用,或者是使用安装在 /data 下的新版本应用来覆盖系统应用,都适用。

场景二:如果两个或多个应用想要共享同一个用户ID,方便共享数据等,必须使用相同的密钥对它们进行签名。

  • 必须使用符合系统预期的密钥对 OTA 更新包进行签名,否则在安装过程中,OTA 更新包将被拒绝。

总结,那么系统签名作用是应用签名和 OTA 升级包签名。

应用签名的好处:

应用来源验证: 应用签名允许Android系统验证应用的来源。每个应用都使用开发者的私钥进行签名,而应用的签名信息包含在应用的APK文件中。当用户尝试安装应用时,系统会检查应用的签名,以确保它与系统中已知的相匹配。
应用完整性验证: 应用签名有助于确保应用在传输过程中没有被篡改。如果应用在传输过程中被修改,其签名将失效,系统会拒绝安装或运行该应用。
权限声明: 应用签名也与应用的权限声明相关。Android系统使用应用签名来确保应用对敏感系统资源和API的访问受到控制。如果应用的签名与其声明的权限不匹配,系统会拒绝授予应用相应的权限。
防止重放攻击: 应用签名可以防止重放攻击,因为攻击者无法将已签名应用的部分替换为其他内容而不影响签名的有效性

1.1 系统签名文件介绍

系统签名文件路径位于 /build/target/product/security 下,路径下结构如下所示:

ubuntu:/build/target/product/security$ ls -l
total 52
-rw-r--r-- 1 uyanl362 domain users  656 Feb 20 11:06 Android.mk
-rw-r--r-- 1 uyanl362 domain users 1216 Feb 20 11:06 media.pk8
-rw-r--r-- 1 uyanl362 domain users 1675 Feb 20 11:06 media.x509.pem
-rw-r--r-- 1 uyanl362 domain users 1216 Feb 20 11:06 platform.pk8
-rw-r--r-- 1 uyanl362 domain users 1675 Feb 20 11:06 platform.x509.pem
-rw-r--r-- 1 uyanl362 domain users 3128 Feb 20 11:06 README
-rw-r--r-- 1 uyanl362 domain users 1218 Feb 20 11:06 shared.pk8
-rw-r--r-- 1 uyanl362 domain users 1675 Feb 20 11:06 shared.x509.pem
-rw-r--r-- 1 uyanl362 domain users 1217 Feb 20 11:06 testkey.pk8
-rw-r--r-- 1 uyanl362 domain users 1675 Feb 20 11:06 testkey.x509.pem
-rw-r--r-- 1 uyanl362 domain users  524 Feb 20 11:06 verity_key
-rw-r--r-- 1 uyanl362 domain users 1219 Feb 20 11:06 verity.pk8
-rw-r--r-- 1 uyanl362 domain users 1444 Feb 20 11:06 verity.x509.pem

上述结构中有四种常见的签名密钥,分别是 testkey、platform、shared、media。每个密钥用于签署不同类型的应用或组件,每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。私钥需要加以保密,并用于对 apk 的签名。

testkey:平台默认的 key。在编译中没有指定 LOCAL_CERTIFICATE 的,默认使用 testkey。

platform:平台的核心应用 key。系统的核心应用使用此类签名。如果需要使用,需要配置 AndroidManifest.xml 的 manifest 节点中添加 android:sharedUserId=”android.uid.system”,
Android.mk中增加 LOCAL_CERTIFICATE := platform。

shared:平台需要共享的应用 key。签署 Android 平台上的共享系统库。如果需要使用,需要配置 AndroidManifest.xml 的 manifest 节点中增加 android:sharedUserId=”android.uid.shared”,
Android.mk 中增加 LOCAL_CERTIFICATE := shared。

media:平台的媒体相关应用 key。用于签署 Android 平台上的媒体库,媒体相关应用等。如果需要使用,需要配置 AndroidManifest.xml 的 manifest 节点中增加 android:sharedUserId=”android.media”,
Android.mk 中增加 LOCAL_CERTIFICATE := media。

路径下还有 verity 相关的三个文件,分别是 verity_key、verity.pk8、verity.x509.pem。

verity_key:公钥,在 dm verity 中用于验签系统分区。

verity.pk8:私钥,用于签名 boot 镜像和 system 镜像。

verity.x509.pem:包含公钥的证书。

1.2 制作系统签名文件

在系统签名文件路径下的 README 文件中,对于签名制作有相关描述,README 内容如下:

For detailed information on key types and image signing, please see:

https://source.android.com/devices/tech/ota/sign_builds.html

The test keys in this directory are used in development only and should
NEVER be used to sign packages in publicly released images (as that would
open a major security hole).

key generation
--------------

The following commands were used to generate the test key pairs:

  development/tools/make_key testkey  '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key platform '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key shared   '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
  development/tools/make_key media    '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'

signing using the openssl commandline (for boot/system images)
--------------------------------------------------------------

1. convert pk8 format key to pem format
   % openssl pkcs8 -inform DER -nocrypt -in testkey.pk8 -out testkey.pem

2. create a signature using the pem format key
   % openssl dgst -binary -sha1 -sign testkey.pem FILE > FILE.sig

extracting public keys for embedding
------------------------------------

dumpkey.jar is a Java tool that takes an x.509 certificate in PEM format as
input and prints a C structure to standard output:

    $ java -jar out/host/linux-x86/framework/dumpkey.jar build/target/product/security/testkey.x509.pem
    {64,0xc926ad21,{1795090719,2141396315,950055447,2581568430,4268923165,1920809988,546586521,3498997798,1776797858,3740060814,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,2563319927,323993566,28517732,609753416,1826472888,215237850,4261642700,4049082591,3228462402,774857746,154822455,2497198897,2758199418,3019015328,2794777644,87251430,2534927978,120774784,571297800,3695899472,2479925187,3811625450,3401832990,2394869647,3267246207,950095497,555058928,414729973,1136544882,3044590084,465547824,4058146728,2731796054,1689838846,3890756939,1048029507,895090649,247140249,178744550,3547885223,3165179243,109881576,3944604415,1044303212,3772373029,2985150306,3737520932,3599964420},{3437017481,3784475129,2800224972,3086222688,251333580,2131931323,512774938,325948880,2657486437,2102694287,3820568226,792812816,1026422502,2053275343,2800889200,3113586810,165549746,4273519969,4065247892,1902789247,772932719,3941848426,3652744109,216871947,3164400649,1942378755,3996765851,1055777370,964047799,629391717,2232744317,3910558992,191868569,2758883837,3682816752,2997714732,2702529250,3570700455,3776873832,3924067546,3555689545,2758825434,1323144535,61311905,1997411085,376844204,213777604,4077323584,9135381,1625809335,2804742137,2952293945,1117190829,4237312782,1825108855,3013147971,1111251351,2568837572,1684324211,2520978805,367251975,810756730,2353784344,1175080310}}

This is called by build/make/core/Makefile to incorporate the OTA signing keys
into the recovery image.

README 中描述系统签名文件是通过 development/tools/make_key 工具做出来的。如果需要自定义签名文件,我们需要使用这个工具制作,下面对参数进行描述:

development/tools/make_key 参数一[签名文件名] 参数二[签名属性]
参数一:签名文件名,我们可以使用原生的命名,testkey、platform、shared、media
参数二:属性
	C —> Country Name (2 letter code) #国家名称(2 个字母代码)
	ST —> State or Province Name (full name) #州或省名称(全名)
	L —> Locality Name (eg, city) #地区名称(例如,城市)
	O —> Organization Name (eg, company) #组织名称(例如,公司)
	OU —> Organizational Unit Name (eg, section) #组织单位名称(例如,部分)
	CN —> Common Name (eg, your name or your server’s hostname) #通用名称(例如,您的姓名或服务器的主机名)
	emailAddress —> Contact email address #联系电子邮件地址

1.3 替换系统签名文件

自定义签名文件替换到系统中,可以将自定义文件通过系统编译 mk 配置。例如,自定文件在 “/vendor/**/security/” 目录下,可以在系统的 /build/make/core/Makefile 文件或者自定义的平台项目 mk 文件中通过 PRODUCT_DEFAULT_DEV_CERTIFICATE 配置指定

ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))	
PRODUCT_DEFAULT_DEV_CERTIFICATE := \
       build/target/product/security/testkey
else
PRODUCT_DEFAULT_DEV_CERTIFICATE := \
       vendor/**/security/testkey
endif

上述可以判断下在 user 版本中使用新的 key,在 userdebug、eng 版本中使用原生 key 进行签名。

1.4 替换系统签名文件后的影响

1.4.1 查看 apk 签名信息

替换系统签名文件后,可以通过命令查看编译的 apk,判断签名是否应用。可以通过如下命令查看 apk 的签名信息

keytool -list -printcert -jarfile **.apk

1.4.2 升级包的签名

替换自定义签名时,如果涉及 testkey 的变更,那么对于 AB 升级场景,需要在制作升级包时指定原有 testkey 签名。在制作升级包时,如果不指定密钥路径的话,制作包过程中会默认使用 test_key 对包进行签名。那么如果修改了 testkey,制作升级包时会使用新的 test_key 进行签名,那么在刷写旧版本 test_key 的机器上使用新的 test_key 升级包时,会出现升级包校验错误(kDownloadMetadataSignatureMismatch 26)的异常。

升级场景
	机器版本:old testkey 版本
	升级包:new testkey 升级包
如果直接进行升级,那么会出现 kDownloadMetadataSignatureMismatch 26 的异常,此场景需要对升级包指定 旧testkey 文件签名

需要文件
	旧的签名文件:/build/target/product/security/testkey
	target 包:out/target/product/**/obj/PACKAGING/target_files_intermediates/mt2712_saic_ec32-target_files-eng.zip

命令:./build/tools/releasetoolsota_from_target_files.py -k /build/target/product/security/testkey out/target/product/**/obj/PACKAGING/target_files_intermediates/mt2712_saic_ec32-target_files-eng.zip ota_android_sign.zip

2 应用签名

2.1 应用使用签名文件签名

apk 应用新的签名文件有两种方式,第一种是通过系统端提供的 keystore 文件,在应用编译的时候,使用 keystore 文件签名;第二种是通过 signapk.jar 工具对已经编译好的应用进行重签名。

2.1.1 使用 keystore 文件签名

系统端在自定义签名文件后,需要生成 keystore 文件给外部 apk 开发签名使用。

这里以 platform 签名为例

//如果之前没有生成platform.pem文件,现在可以执行以下命令生成
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem

//生成platform.p12文件,设置对应的密码和alias名(app签名使用到)
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:密码 -name 名称

//生成platform.jks(app使用的签名文件),启动
keytool -importkeystore -deststorepass 密码 -destkeystore ./platform.keystore -srckeystore ./platform.p12 -srcstoretype PKCS12 -srcstorepass 密码

//剩下的就是将platform.jks拷贝到app工程目录下设置alias名和密码即可

2.1.2 使用 signapk.jar 重签名

对于已经编译好的 apk 文件,如果需要对 apk 进行重签名,需要使用 signapk 工具。

signapk 工具是 Android 的原生工具,代码在 /build/tools/signapk 路径下,编译 signapk.jar 在 /out/host/linux-x86/framework 路径下。

signapk.jar 的使用如下所示:

java -jar signapk.jar  platform.x509.pem platform.pk8 old.apk new.apk
  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值