问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

安卓签名校验机制解析

创作时间:
作者:
@小白创作中心

安卓签名校验机制解析

引用
1
来源
1.
https://joooook.github.io/2024/09/15/%E5%AE%89%E5%8D%93%E7%AD%BE%E5%90%8D%E6%A0%A1%E9%AA%8C%E6%9C%BA%E5%88%B6%E8%A7%A3%E6%9E%90/

安卓系统的签名校验机制经历了三代演进,从最初的V1方案到支持全文件签名的V2方案,再到为Android 9的APK密钥轮替功能设计的V3方案。本文将详细介绍这三代签名校验机制的工作原理,并介绍如何使用jarsigner和apksigner工具进行签名实践。

1. V1方案

V1签名后会在apk中增加META-INF文件夹,其中包含三个重要文件:

  • MANIFEST.MF:储存apk中每一个文件的摘要。
  • *.SF:包含MANIFEST.MF文件的摘要信息以及MANIFEST.MF文件当中每个条目在用摘要算法计算得到的摘要信息。
  • *.RSA:包含*.SF的签名及签名的公钥证书。

以小米万能遥控的包apk为例,META-INF文件夹中的MANIFEST.MF储存了文件名及其SHA256摘要的base64编码。*.SFMANIFEST.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 Block由以下几个部分组成:

偏移
字节数
描述
@0
8
这个Block的长度(本字段的长度不计算在内)
@8
n
一组ID-value
@-24
8
这个Block的长度(和第一个字段一样值)
@-16
16
魔数“APK Sig Block 42”

具体结构如下:

  • ID = 0x7109871a的键值对块就是保存V2签名信息的地方。开头示例如下:
  • 结尾处示例

美团团队通过自定义ID,可以用来生成渠道包。ID = 0x7109871a的键值对块中的Value储存的是v2签名信息。其中可以保存了一份或者多份APK签名信息(多个签名者)。Value的内容结果如下:

具体如下:

示例分析。红框部分为摘要,紫框部分为证书。

2.1 摘要计算过程

摘要计算只针对原始zip内容:

  • 拆分块chunk:将每个部分(即上面标注第1、3、4部分)拆分成多个大小为1MB大小的块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就是为了Android 9的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 -aliastest

5.2 jarsigner

签名命令:

jarsigner -keystore 密钥库名 xxx.apk 密钥别名

还有以下两个参数比较重要:

  • -digestalg:摘要算法
  • -sigalg:签名算法

5.3 apksigner

apksigner sign --ks demo1.keystore --ks-key-aliastest app-debug.apk

apksigner默认开启v1和v2签名,可以用以下参数关闭:

  • --v1-signing-enabled false
  • --v2-signing-enabled false
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号