安卓签名校验机制
目录
- 1 V1方案
- 1.1 V1方案的安全性
- 2 V2方案
- 2.1 摘要计算过程
- 2.2 防回滚绕过
- 3 V3方案
- 4 V4方案
- 5 签名实践
- 5.1 keytool生成密钥库
- 5.2 jarsigner
- 5.3 apksigner
- 6 引用
安卓的签名校验机制共有三代。
9.0以上的系统会判断apk是否使用到V3版本的签名,如果有,那么按照V3版本签名校验方式进行校验校验成功直接安装,校验失败拒绝安装;如果apk不是使用V3签名,判断是不是使用V2,如果没有使用V2那么再判断是不是使用V1的签名。
1 V1方案
v1签名后会增加META-INF
文件夹,其中会有如下三个文件:
MANIFEST.MF
:储存apk中每一个文件的摘要。*.SF
:MANIFEST.MF
文件的摘要信息以及MANIFEST.MF
文件当中每个条目在用摘要算法计算得到的摘要信息。*.RSA
:包含*.SF
的签名及签名的公钥证书
以小米万能遥控的包apk
为例
META-INF
文件夹
MANIFEST.MF
储存了文件名及其SHA256
摘要的base64
编码
*.SF
比MANIFEST.MF
多了MANIFEST.MF
的摘要,并且对MANIFEST.MF
中的每个模块都进行了摘要。
如何区别一个模块,查看文件的十六进制,一个模块是以0D0A0D0A
结尾的,其实就是两次换行。
取AndroidManifest.xml
模块来验证
*.RSA
是PKCS#7格式
的数据经过ASN.1 DER规则编码
之后的二进制文件
使用以下命令行读取
openssl pkcs7 -inform DER -in <*.RSA文件路径> -text -noout -print_certs
1.1 V1方案的安全性
APK 包的完整性校验不够强。如果我们在 APK 签名后,对 APK 包中没有涉及到原始文件的数据块做改变,那么这层校验机制就会失效。
2 V2方案
APK 签名方案 v2 是一种全文件签名方案,该方案能够发现对 APK 受保护部分进行的所有更改
APK Signing Bolck 由这几个部分组成:
偏移 | 字节数 | 描述 |
---|---|---|
@0 | 8 | 这个 Block 的长度(本字段的长度不计算在内) |
@8 | n | 一组 ID-value |
@-24 | 8 | 这个 Bolck 的长度(和第一个字段一样值) |
@-16 | 16 | 魔数 "APK Sig Block 42" |
具体结构如下
ID = 0x7109871a
的键值对块就是保存V2签名信息的地方。开头示例如下
结尾处示例
美团团队通过自定义ID,可以用来生成渠道包https://tech.meituan.com/2017/01/13/android-apk-v2-signature-scheme.html
ID = 0x7109871a
的键值对块中的Value
储存的是v2
签名信息。
其中可以保存了一份或者多份APK签名信息(多个签名者)。
Value
的内容结果如下
具体如下
示例分析。红框部分为摘要,紫框部分为证书。
2.1 摘要计算过程
摘要计算只针对原始zip
内容
-
拆分块chunk
将每个部分(即上面标注第1、3、4部分)拆分成多个大小为 1 MB大小的块chunk,最后一个块chunk可能小于1MB。之所以分块,是为了可以通过并行计算摘要以加快计算速度
-
计算块chunk摘要
0xa5 + chunk长度(字节数) + chunk内容
拼接起来用对应的摘要算法进行计算出每一块的摘要值; -
计算整体摘要
0x5a + chunk数 + chunk摘要
(按块在 APK 中的顺序)拼接起来用对应的摘要算法进行计算出整体的摘要值
2.2 防回滚绕过
为了防止攻击者删除apk
中的v2
方案从而绕过,带 v2
签名的 APK
如果还带 V1
签名,其 META-INF/*.SF
文件的主要部分中必须包含 X-Android-APK-Signed
属性。
3 V3方案
APK 的 v3 签名存储为 ID 值对,ID 为 0xf05368c0。v3 方案的设计与v2 方案非常相似。它具有相同的通用格式,添加了有关支持的SDK版本和proof-of-rotation结构的信息。
简单来说APK v3就是为了Andorid9的APK 密钥轮替功能而出现的,就是在v2的基础上增加两个数据块来存储APK 密钥轮替(更新签名密钥)所需要的一些信息,所以可以看成是v2的升级。具体结构见官网说明即可。
4 V4方案
APK v4是为了ADB 增量 APK 安装出现的
增量更新是基于 BSDiff 这个差量更新算法,基于两个 apk 字节码的差异,在服务端生成 patch 包,然后客户端通过同样的算法,把已安装的 apk 与 patch 包结合生成更新后的apk进行安装,以此减小 app 版本升级时的下载时间,提高更新效率。
签名方式和v2v3有所不同。
5 签名实践
以下介绍jarsigner
和apksigner
签名工具的使用。
jarsigner
是JDK
提供的针对jar
包签名的通用工具,位置在JDK/bin/jarsigner
apksigner
是Google官方提供的针对Android apk签名及验证的专用工具,位置在Android SDK/build-tools/SDK版本/apksigner
但这两种工具的签名都要使用到密钥库文件,所以顺便介绍密钥库生成。
5.1 keytool生成密钥库
使用keytool
生成密钥库
keytool -genkey -keyalg RSA -keystore (指定密钥库文件名) demo.keystore
填写信息即可生成,
这个条目名字也是要用到的
或者我们可以指定条目名字
keytool -genkey -keyalg RSA -keystore demo1.keystore -alias test
5.2 jarsigner
签名命令
jarsigner -keystore 密钥库名 xxx.apk 密钥别名
还有以下两个参数比较重要
-digestalg
摘要算法-sigalg
签名算法
5.3 apksigner
apksigner sign --ks demo1.keystore --ks-key-alias test app-debug.apk
apksigner
默认开启v1
和v2
签名,可以用以下参数关闭。
--v1-signing-enabled
false
--v2-signing-enabled
false
6 引用
Android V2签名与校验原理分析-CSDN
签名校验机制.md-Github
AndroidV1,V2,V3签名原理详解-腾讯云开发者社区-腾讯云
Android apk之v1、v2、v3签名-知乎
Android V2签名与校验原理分析_v2 方案校验不通过-CSDN博客
Android中APK签名工具之jarsigner和apksigner详解-CSDN博客