一、简述
首先,我们先了解一下签名的类型有哪些?
Android标准签名key文件位于源码/build/target/product/security
目录下,四组默认签名供Android.mk在编译APK使用。主要有4个key:
- testkey:普通签名APK,默认情况下使用。
- platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。
- shared:该APK需要和home/contacts进程共享数据。
- media:该APK是media/download系统中的一环。
应用程序的Android.mk中有一个LOCAL_CERTIFICATE字段,由它指定哪个key签名,未指定的默认用testkey.
build/target/product/security
目录下查看:
mo@ubuntu:~/AOSP/android6.0/build/target/product/security$ ls
Android.mk platform.x509.pem testkey.pk8 verity.x509.pem
media.pk8 README testkey.x509.pem
media.x509.pem shared.pk8 verity_key
platform.pk8 shared.x509.pem verity.pk8
.pk8代表私钥,.x509.pem公钥,它们都是成对出现;
testkey是作为android编译的时候默认的签名key,如果系统中的apk的Android.mk中没有设置LOCAL_CERTIFICATE的值,就默认使用testkey。
而如果设置成:
LOCAL_CERTIFICATE := platform
就代表使用platform来签名,这样的话这个apk就拥有了和system相同的签名,因为系统级别的签名也是使用的platform来签名,此时使用android:sharedUserId="android.uid.system"
才有用!
二、自定义签名
1.key生成签名
在/build/target/product/security
目录下有个README,里面说明了怎么制作这些key以及使用
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/core/Makefile to incorporate the OTA signing keys
into the recovery image.
从README可知,key是通过development/tools
目录下的make_key脚本生成的,脚本需要传入两个参数。其中第一个参数是key的名字,我们可以不修改,使用aosp默认的4个key的名字;第二个参数即是具体的一些属性,此为key真正的关键(我们需要修改的部分),下面对第二个参数的一些具体属性做出分析解释:
C —> Country Name (2 letter code)
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
另外在是用make_key生成key的过程中会提示输入password,一般是不输入,直接enter的。
2.删除已存在的key
进入到/build/target/product/security
目录执行如下命令:
rm ./*.p*
删除全部已存在的key,然后重新生成新的key。
3.生成key
返回到AOSP的根目录,使用make_key脚本去生成4个签名key。
testkey
./development/tools/make_key build/target/product/security/testkey '/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
platform
./development/tools/make_key build/target/product/security/platform '/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
media
./development/tools/make_key build/target/product/security/media '/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
shared
./development/tools/make_key build/target/product/security/shared '/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
我们可以自定义key_create.sh
脚本生成秘钥放到aosp根目录下,脚本代码如下:
subject='/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
for x in releasekey platform shared media;
do
./development/tools/make_key build/target/product/security/$x "$subject";
done
4.验证key
在生成4个key后,再使用OpenSSL的工具来验证一下生成的key是否正常。
进入到/build/target/product/security
目录,执行如下命令:
openssl x509 -noout -subject -issuer -in media.x509.pem
输出:
subject= /C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com
issuer= /C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com
另外3个key的验证类似media,就不再多做介绍。
5.修改系统默认签名key
在上面提到如果apk中的编译选项LOCAL_CERTIFICATE没有设置的话,就会使用默认的testkey作为签名key,我们可以修改成自己想要的key,按照上面的步骤制作一个releasekey,
a.修改android配置在/build/core/config.mk
中定义变量:
DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
TO
DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/releasekey
b.修改android配置在/build/core/Makefile.mk
中定义变量:
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_VERSION_TAGS += release-keys
这样的话默认的所有签名将会使用releasekey
。
c.修改system/sepolicy/private/keys.conf 和 system/sepolicy/prebuilts/api/{apilevel}/private/keys.conf
[@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
验证打包编译好的系统使用的签名
编译完成之后也可以在build.prop
中查看到变量:
adb root //获取root权限
adb remount
adb shell
cd system
cat build.prop
会看到一行ro.build.tags=release-keys
6.生成 generate_verity_key
make generate_verity_key
(mmm system/extras/verity/)
首先,先生成veritykey签名
development/tools/make_key veritykey '/C=CN/ST=ShenZhen/L=ShenZhen/O=momxmo/OU=mo/CN=www.momxmo.com/emailAddress=test@126.com'
然后执行
out/host/linux-x86/bin/generate_verity_key -convert veritykey.x509.pem verity_key
拷贝veritykey.pk8
,veritykey.x509.pem
,verity_key.pub
至 build/target/product/security/
目录,将其重命名:verity.pk8, verity.x509.pem,verity_key
,并替换相应的 key。
根据以上步骤把生成的相应的key替换系统中build/target/product/security/
目录下的key后重新编译系统,即可使用自己生成的系统签名key
三、系统key文件生成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名和密码即可
最终的platform.keystore即为我们所要的keystore