apk签名原理

经常使用的总结:

debug 签名:
development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=/OU=xxx/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=debug/CN=xxx/emailAddress=cm@xxx.com'

user签名:
development/tools/make_key media '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key networkstack '/C=CN/ST=BeiJing/L=ChaoYang/O=user/OU=Pwe/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key platform '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key shared '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'
development/tools/make_key testkey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=user/CN=xxx/emailAddress=cm@xxx.com'

ota:
../development/tools/make_key releasekey '/C=CN/ST=BeiJing/L=ChaoYang/O=xxx/OU=xxx/CN=xxx/emailAddress=cm@xxxx.com'

查看生成的格式文件:
keytool -printcert -file platform.x509.pem

使用signapk.jar 进行签名:android10:
java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk  new.apk

android 11:
./soong/host/linux-x86/framework/signapk.jar

如何产生jsk (keystore)文件, 只做了debug 模式发的
./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test

如何查看test.jks 是否正确:
keytool -list -v -keystore test.jks
 
Android studio 如何使用:
signingConfigs {
    releaseConfig {
        keyAlias 'test'
        keyPassword 'android '
        storeFile file('/home/xxx/tools/keystore/test.jks')
        storePassword 'android '
    }
}



AndroidManifest.xml的manifest节点中添加
android:sharedUserId=”android.uid.system”,
Android.mk中增加  LOCAL_CERTIFICATE := platform 

APK中的META-INF/CERT.RSA
签名之后如何对RSA 进行查看,签名的信息,在android root目录 
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

本文主要讲解签名的原因,签名怎么保证数据的正确,主要知识点

  • 数据摘要(数据指纹,消息摘要)
  • 签名文件和证书
  • 签名Apk包与没有签名的APK 差异在哪里
  • 如何对apk 进行签名

1-数据摘要

就是对一个数据源进行一个算法之后得到一个摘要,也叫作数据指纹,不同的数据源,数据指纹肯定不一样,就和人一样

消息摘要算法(Message Digest Algorithm)是一种能产生特殊输出格式的算法,其原理是根据一定的运算规则对原始数据进行某种形式的信息提取,被提取出的信息就被称作原始数据的消息摘要。
著名的摘要算法有RSA公司的MD5算法和SHA-1算法及其大量的变体。

  • 无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。
  • 原始数据不同,消息摘要不相同
  • 具有不可逆性

2-签名文件和证书

消息的发送者来说,先要生成一对公私钥对,将公钥给消息的接收者

  • 提取原始消息提取消息摘要;
  • 私钥加密消息摘要;
    上面就是所原始信息的数字签名。【数字签名=私钥对[原始数据摘要]

消息的接受者来说,收到了:原始的消息内容+附加数字签名.
接收者收到内容:原始的消息内容+私钥对[原始数据摘要]

验证正确需要数据摘要算法+公钥,公钥假设是正确的。
如何验证:数据摘要算法对内容提取摘要 对比公钥解密签名

图示验证过程:

3-如何保证公钥是正确的

数字证书,一般包含以下一些内容:

  • 证书的发布机构(Issuer)
  • 证书的有效期(Validity)
  • 消息发送方的公钥
  • 证书所有者(Subject)
  • 数字签名所使用的算法
  • 数字签名 --》 数字证书也使用到了数字签名,只不过签名的内容是证书
    公钥签发流程
    上面核心内容就是申请者 提出申请公钥, 公信力机构 使用自己的私钥对申请者的公钥数字签名, 公信力机构的公钥是大家都知道的,因此成功后,申请者的client 端就可以通过公信力机构 获取, 以验证公钥的正确性。
    上面的内容是我在理解HTTPS ,一直想不通的地方,现在终于想通了签发机构是如何发送公钥的。
    其实app 的数字签名与上面的CA 机构的签名还是有点区别的。

APP 是如何保证签名流程的:
apk签名其实是对所有源文件单独计算摘要, 然后用私钥加密摘要信息再得到一个加密串, 我们称之为
APK的签名. 你对源文件的修改都会导致签名的变化. 这个是为了验证apk没有被篡改.

app的升级和重新安装, 检测的并不是这个apk签名, 而是你的包名+私钥的摘要信息, 签名的keystore文件没有变, 私钥的摘要信息也就不会变了.

google APP store, 当开发者第一步开发的时候,就需要有自己的签名,私钥的摘要信息上传到goole APP store, 如果升级的时候, 私钥的摘要不一致肯定不能升级app 的上传,这里应该做了校验的。

4-签名Apk包与没有签名的APK 差异在哪里

源码位置:com/android/signapk/sign.java
Android签名apk之后,会有一个META-INF文件夹,这里有三个文件:

  • MANIFEST.MF
  • CERT.RSA
  • CERT.SF

MANIFEST.MF是:
逐一遍历里面的所有条目,如果是目录就跳过,如果是一个文件,就用SHA1(或者SHA256)消息摘要算法提取出该文件的摘要然后进行BASE64编码后,作为“SHA1-Digest”属性的值写入到MANIFEST.MF文件中的一个块中。该块有一个“Name”属性,其值就是该文件在apk包中的路径。

CERT.SF:
逐条计算MANIFEST.MF文件中每一个块的SHA1,并经过BASE64编码后,记录在CERT.SF中的同名块中,属性的名字是“SHA1-Digest

CERT.RSA:
把之前生成的 CERT.SF文件, 用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存,还有私钥的摘要信息

5-如何对apk 进行签名

5.1生成签名文件

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'

如何查看生成的platform.X509.pem:
build/target/product/security/platform.x509.pem
keytool -printcert -file platform.x509.pem
或者
openssl x509 -inform PEM -subject_hash_old -in platform.x509.pem -text

单独给APP签名方法:
java -Djava.library.path="out/host/linux-x86/lib64" -jar out/host/linux-x86/framework/signapk.jar build/target/product/security/platform.x509.pem build/target/product/security/platform.pk8 old.apk new.apk

APP签名之后,如何查看CERT.RSA 信息
openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

6-Android OTA releasekey 替换

6.1生成key
系统默认的key如下,首先需要产生以下4种我们项目自己的OTA签名key文件,每一种类型的key都是成对生成的,.509.pem后缀名的是公钥,.pk8后缀名的是私钥。
testkey -- a generic key for packages that do not otherwise specify a key.
platform -- a test key for packages that are part of the core platform.
shared -- a test key for things that are shared in the home/contacts process.
media -- a test key for packages that are part of the media/download system.

将XXX替换为自己公司信息。
生成文件如下:
media.pk8 media.x509.pem platform.pk8 platform.x509.pem
releasekey.pk8 releasekey.x509.pem shared.pk8 shared.x509.pem

将生成的key 文件放到项目相关的目录下,针对Amlogic项目放到device/amlogic/p341/sign_keys。这样我们公司的key就生成了。

6.2.更改编译规则,使编译过程中使用我们新生成的key对OTA进行签名
首先在build/core/Makefile里搜索testkey, 查看testkey是怎么用到编译系统的,看到如下编译选项:

 ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
 BUILD_KEYS := test-keys
 else
 BUILD_KEYS := dev-keys
 endif

继续查看DEFAULT_SYSTEM_DEV_CERTIFICATE,可以看到在build/core/config.mk文件里有如下:

 # 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/target/product/security/testkey
 endif

因此要想使用releasekey,只需要指定PRODUCT_DEFAULT_DEV_CERTIFICATE的值即可,因此在device/amlogic/p341/p341.mk中指定项目特定变量
PRODUCT_DEFAULT_DEV_CERTIFICATE := device/amlogic/p341/sign_keys/releasekey
同时在根据规则,在build/core/Makefile改动如下:

 ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),device/amlogic/p341/sign_keys/releasekey)
 BUILD_KEYS := release-keys
 endif

6.3. Androoid.mk 使用platform 签名
对于apk的签名,系统会根据apk里指定的key进行签名。如果系统中的apk的android.mk中没有设置LOCAL_CERTIFICATE的值,就默认使用testkey。

 ifeq ($(LOCAL_CERTIFICATE),)
     LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
 endif
 private_key := $(LOCAL_CERTIFICATE).pk8
 certificate := $(LOCAL_CERTIFICATE).x509.pem

而如果设置成:
LOCAL_CERTIFICATE := platform
就代表使用platform来签名,这样的话这个apk就拥有了和system相同的签名
如何产生jks文件,提供给android studio 开发使用,进行系统签名
jks文件:
第一种方式
https://github.com/chear/keytool-importkeypair
./keytool-importkeypair -k test.jks -p android -pk8 platform.pk8 -cert platform.x509.pem -alias test
最终会生成 test.jks
-k test.jks: test表示最终生成的jks的名字,可以自定义
android : 输入当前jks的密码,可以自定义。
alias test: test表示别名,可以自定义,建议和上面的jks一致。

第二种方式: 该方式作为记录,实际与第一种方式是想通的,可以看keytool-importkeypair 脚本

1、编译android源码。
2、cd build/target/product/security/ 
3、执行
openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
生成platform.pem文件

4、
openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:123456 -name test
生成platform.p12文件,其中 "test" 为alias名(app添加签名要用到),"123456" 为密码。

5、执行 
keytool -importkeystore -deststorepass test -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass test
 
生成platform.jks (app打签名最终用到的文件),
-deststorepass "123456" 设置的是这个签名的密码,
-src*     的其他参数都是从前面两个指令中生成的。
 
6、生成platform.jks
keytool -importkeystore -srckeystore platform.jks -destkeystore platform.jks -deststoretype pkcs12

说明:platform.jks 实际是含有了公钥与私钥, 这个是不能release给第三方的,只能给自己公司研发使用

思考:

  • 一个数据内容使用一个签名就可以,一个app 使用一个签名就可以,如果重复签名会怎么样?
    重复使用signapk 签名会覆盖,上次的签名失效,【没有使用studio 多次签名试过,看到有别名的可以有多个】


  • 普通签名与系统签名的区别?
    签名是保证数据不被改写
    系统签名就是要获取一些系统权限,修改时间权限等等
    普通签名仅仅保证数据正确,单存的app 开发,上传到APP store ,不需要获取修改系统的权限。

  • app升级过程中,如何保证升级APP 数据是正确的?
    数字签名 与公钥联合,配合私钥的数据摘要,android 升级过程进行了对比,如果在第一次安装设备时候就修改了数字签名,那么再次安装正确的app 不会成功。 因此老老实实从Apple store 下载,这样保证app 正确,没有打广告等

  • https协议中的公钥,私钥处理方式,ssl 中公钥如何传递给使用者?
    通过CA 公信力结构,公钥分发给使用者,ssl协议在协商过程使用非对称加密技术, 最后协商出对称秘钥进行通信,对称秘要没有在网络上传递, 是双方通过算法计算出来的。

7 设计原则与测试结果

7.1设计原则
签名文件规格:(device.mk设计参考之前的)
1)Userdebug 与user 区别
userdebug 系统platform.jks 有可能release 给别人,因此user版本设计成不一样的。
user 系统platform.jks 仅仅relase公司的app 开发人员
2)user 与ota ,只是ota 多了releaseky,其他文件都一样

7.2测试华为手机user version【开发者模式】:

  • debug app 可以正常安装, 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

  • release apk(没有签名), 不能安装,【 在AndroidManifest.xml 添加了 android:sharedUserId="android.uid.system"

  • release apk(使用platform 签名[android10 google原生platformq签名]), 这种方式可以正常安装

  • release apk(使用platform 签名[自己制作android10platformq签名]), 这种方式可以正常安装
    上面两种都可以安装,在运行的时候对系统权限的多种有所不同。

  • release apk(使用platform 签名[自己制作android10platformq签名]), 这种方式可以正常安装,安装之后再次对APK 签名(使用原生签名文件), 发现CERT.RSA 签名文件失效, 不能再次安装,提示签名不匹配

Performing Streamed Install
adb: failed to install C:\Users\Desktop\old.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.example.demo signatures do not match previously installed version; ignoring!]

REF:
//www.greatytc.com/p/76e5f5e64b85
https://developer.android.google.cn/studio/publish/app-signing
ota relase key 参考

下载文件地址:
git clone https://github.com/getfatday/keytool-importkeypair.git

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容