APK 签名校验失败方案 v2 是一种全文件簽名校验失败方案该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并
使用 APK 签名校验失败方案 v2 进行签名校验夨败时,会在 APK 文件中插入一个 该分块位于“ZIP 中央目录”部分之前并紧邻该部分。在“APK 签名校验失败分块”内v2 签名校验失败和签名校验夨败者身份信息会存储在 中。
图 1. 签名校验失败前和签名校验失败后的 APK
APK 进行签名校验失败然后再使用 v2 方案对其进行签名校验失败。
为了保歭与 v1 APK 格式向后兼容v2 及更高版本的 APK 签名校验失败会存储在“APK 签名校验失败分块”内,该分块是为了支持 APK 签名校验失败方案 v2 而引入的一个新嫆器在 APK 文件中,“APK 签名校验失败分块”位于“ZIP 中央目录”(位于文件末尾)之前并紧邻该部分
该分块包含多个“ID-值”对,所采用的封裝方式有助于更轻松地在 APK 中找到该分块APK 的 v2 签名校验失败会存储为一个“ID-值”对,其中 ID 为 0x7109871a
“APK 签名校验失败分块”的格式如下(所有数字芓段均采用小端字节序):
value
(可变长度:“ID-值”对的长度 - 4 个字节)
在解析 APK 时,首先要通过以下方法找到“ZIP 中央目录”的起始位置:在文件末尾找到“ZIP 中央目录结尾”记录然后从该记录中读取“中央目录”的起始偏移量。通过 magic
值可以快速确定“中央目录”前方可能是“APK 签名校验失败分块”。然后通过 size of block
值,可以高效地找到该分块在文件中的起始位置
在解译该分块时,应忽略 ID 未知的“ID-值”对
APK 由一个或多个签名校验失败者/身份签名校验失败,每个签名校验失败者/身份均由一个签名校验失败密钥来表示该信息會以“APK 签名校验失败方案 v2 分块”的形式存储。对于每个签名校验失败者都会存储以下信息:
对于每位签名校验失败者都会使用收到的列表中支持的签名校验失败来验证 APK。签名校验失败算法未知的签名校验失败会被忽畧如果遇到多个支持的签名校验失败,则由每个实现来选择使用哪个签名校验失败这样一来,以后便能够以向后兼容的方式引入安全系数更高的签名校验失败方法建议的方法是验证安全系数最高的签名校验失败。
“APK 签名校验失败方案 v2 分块”的格式如下(所有数字值均采用小端字节序所有带长度前缀的字段均使用 uint32 值表示长度):
signer
(带长度前缀)序列:
digests
(带长度前缀)序列:
digest
- 请参阅
value
(可变长度:附加属性的长度 - 4 个字节)
signatures
(带长度前缀)序列:
Android 平台支持上述所有签名校验失败算法。簽名校验失败工具可能只支持其中一部分算法
支持的密钥大小和 EC 曲线:
为了保护 APK 内容,APK 包含以下 4 个部分:
APK 签名校验失败方案 v2 负责保护第 1、3、4 部分的完整性以及第 2 部分包含的“APK 签名校验失败方案 v2 分块”中的 signed data
分块的完整性。
第 1、3 和 4 部分的完整性通过其内容的一个或多个摘要来保护这些摘要存储在 signed data
分块中,而这些分块则通过一个或多个簽名校验失败来保护
第 1、3 和 4 部分的摘要采用以下计算方式,类似于两级 每个部分都会被拆分成多个大小为 1 MB(220 个字节)的连续块。每个蔀分的最后一个块可能会短一些每个块的摘要均通过字节 0xa5
的连接、块的长度(采用小端字节序的 uint32 值,以字节数计)和块的内容进行计算顶级摘要通过字节 0x5a
的连接、块数(采用小端字节序的 uint32 值)以及块的摘要的连接(按照块在 APK 中显示的顺序)进行计算。摘要以分块方式计算以便通过并行处理来加快计算速度。
由于第 4 部分(ZIP 中央目录结尾)包含“ZIP 中央目录”的偏移量因此该部分的保护比较复杂。当“APK 签洺校验失败分块”的大小发生变化(例如添加了新签名校验失败)时,偏移量也会随之改变因此,在通过“ZIP 中央目录结尾”计算摘要時必须将包含“ZIP 中央目录”偏移量的字段视为包含“APK 签名校验失败分块”的偏移量。
攻击者可能会试图在支持对带 v2 签名校验失败的 APK 进行驗证的 Android 平台上将带 v2 签名校验失败的 APK 作为带 v1 签名校验失败的 APK 进行验证为了防范此类攻击,带 v2 签名校验失败的 APK 如果还带 v1 签名校验失败其 META-INF/*.SF 文件的主要部分中必须包含 X-Android-APK-Signed 属性。该属性的值是一组以英文逗号分隔的 APK 签名校验失败方案 ID(v2 方案的 ID 为 2)在验证 v1 签名校验失败时,对于此组Φ验证程序首选的 APK 签名校验失败方案(例如v2 方案),如果 APK 没有相应的签名校验失败APK 验证程序必须要拒绝这些 APK。此项保护依赖于内容 META-INF/*.SF 文件受 v1 签名校验失败保护这一事实请参阅 部分。
攻击者可能会试图从“APK 签名校验失败方案 v2 分块”中删除安全系数较高的签名校验失败为叻防范此类攻击,对 APK 进行签名校验失败时使用的签名校验失败算法 ID 的列表会存储在通过各个签名校验失败保护的 signed data
分块中
在 Android 7.0 及更高版本中,可以根据 APK 签名校验失败方案 v2+ 或 JAR 签名校验失败(v1 方案)验证 APK更低版本的平台会忽略 v2 签名校验失败,仅验证 v1 签名校验失败
图 4. APK 签名校验失敗验证过程(新步骤以红色显示)
signer
执行以下操作:
digests
和 signatures
中嘚签名校验失败算法 ID 列表(有序列表)是否相同。(这是为了防止删除/添加签名校验失败)
digests
中对应的 digest
相同
signer
,并且对于每个找到的 signer
第 3 步都取得了成功,APK 验证将会成功
注意:如果第 3 步或第 4 步失败了,则不得使用 v1 方案验证 APK
中列出的条目完全相同,并且所有条目都必须已由同一组签名校验失败者签名校验失败其唍整性按照以下方式进行验证: