APK签名

0 背景

通过对 Apk 进行签名,开发者可以证明对 Apk 的所有权和控制权,可用于安装和更新其应用。而在 Android 设备上的安装 Apk ,如果是一个没有被签名的 Apk,则会被拒绝安装。

在安装 Apk 的时候,软件包管理器也会验证 Apk 是否已经被正确签名,并且通过签名证书和数据摘要验证是否合法没有被篡改。只有确认安全无篡改的情况下,才允许安装在设备上。

简单来说,APK 的签名主要作用有两个:

证明 APK 的所有者。
允许 Android 市场和设备校验 APK 的正确性。


Android 目前支持以下四种应用签名方案:

v1 方案:基于 JAR 签名。
v2 方案:APK 签名方案 v2(在 Android 7.0 中引入)
v3 方案:APK 签名方案 v3(在 Android 9 中引入)
v4 方案:APK 签名方案 v4(在 Android 11 中引入)


v1 到 v2 是颠覆性的,为了解决 JAR 签名方案的安全性问题,而到了 v3 方案,其实结构上并没有太大的调整,可以理解为 v2 签名方案的升级版,有一些资料也把它称之为 v2+ 方案。‘

1. v1 方案

V1 签名的机制主要就在 META-INF 目录下的三个文件,MANIFEST.MF,CERT.SF,CERT.RSA,他们都是 V1 签名的产物。

在 V1 签名方案中,并不会保护 APK 内的所有文件,会存在一些例外部分,即便被修改也不会导致签名失效。

例如:ZIP 元数据。同时,v1 方案对 APK 内部被保护的原始文件,是单独进行计算数据摘要的,所以在验证时,需要先解压再验证,导致安装时会花费更多的时间,消耗更多的内存。例如 v1 方案中签渠道的方式就是利用了此特性,将渠道信息写入 META-INF 文件中,这不会破坏 v1 签名。

为了解决这些问题,Android 7.0 中引入了 APK 签名方案 v2。

1.1 V1 方案的缺点

  • 不安全
  • 速度慢

1.2 V1 方案的原理

首先我们找一个已经签名的apk文件,修改后缀名为zip,然后解压。可以看到里面有一个META-INF文件夹,里面就是签名验证的文件。有三个文件MANIFEST.MF、CERT.SF、CERT.RSA分别保存着不同的签名信息。

1.2.1 MANIFEST.MF文件

1. Manifest-Version
 用来定义manifest文件的版本,例如:Manifest-Version: 1.0
2. Created-By
 声明该文件的生成者,一般该属性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.5.1
3.Name
 声明了apk中所有的文件。
4.SHA-256-Digest
 对apk中所有文件中对应name的文件的校验码。文件内容发生改变时校验码也随之发生改变,防止文件被修改。

1.2.2 CERT.SF文件

除了保存APK所有文件的名称和校验码之外,还保存了MANIFEST.MF文件的校验码。

1.2.3 CERT.RSA文件

签名的时候需要给一个证书,证书里面有公钥和私钥。

RSA文件的内容就是:使用私钥计算CERT.SF文件的数字签名 + 包含公钥的证书。

所以v1的签名过程为:

CERT.RSA文件 —》保护CERT.SF文件 —》保护MANIFEST.MF文件 —》保护apk所有的文件

v1签名:保护的是apk中已存在的文件不被修改。

1.3 如何进行V1 签名

这里我只列出,如何用命令行去签名。

2. v2 方案

2.1 v2 方案原理

v2 签名是一种全文件签名方案,该方案能够发现对 APK 的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证。

使用 APK 签名方案 v2 进行签名时,会在 APK 文件中插入一个 APK 签名分块,该分块位于「ZIP 中央目录」部分之前并紧邻该部分。在「APK 签名分块」内,v2 签名和签名者身份信息会存储在 APK 签名方案 v2 分块 中。

上图是签名前后,APK 文件结构的对比。可以看到在 v2 已签名的 APK 中,包含了 4 个部分:

  1. ZIP 条目的内容
  2. APK 签名分块(APK Signing Block)
  3. ZIP 中央目录
  4. ZIP 中央目录结尾

在验证期间,v2+ 方案会将 APK 文件视为 blob,并对整个文件进行签名检查。对 APK 进行的任何修改(包括对 ZIP 元数据进行的修改)都会使 APK 签名作废。这种形式的 APK 验证不仅速度要快得多,而且能够发现更多种未经授权的修改。

新的签名格式向后兼容,因此,使用这种新格式签名的 APK 可在更低版本的 Android 设备上进行安装(会直接忽略添加到 APK 的额外数据),但前提是这些 APK 还带有 v1 签名。

 

从安全的角度 v2 会比 v1 更安全,v2 签名是验证整个打包后的 APK 文件,所以对其 APK 文件做“任何”改动都会破坏签名。注意这里的任何是带引号的,V2签名的签名块其实是一个 K-V 的结构,可以向其中插入一些简单的数据而不破坏 v2 签名,这就是 v2 方案下,多渠道的方案思路。

2.2 缺点

无法解决签名过期更换签名的问题

2.3 签名分块的格式

最值得注意的是里面的两个模块:键值对 和 magic(魔数)

键值对: 该分块包含多个“ID-值”对,所采用的封装方式有助于更轻松地在 APK 中找到该分块。APK 的 v2 签名会存储为一个“ID-值”对,其中 ID 为 0x7109871a。
magic(魔数): 用于标记文件格式

2.4 v2 签名包含的内容

为了保护 APK 内容,APK 包含以下 4 个部分:

  1. ZIP 条目的内容(从偏移量 0 处开始一直到“APK 签名分块”的起始位置)
  2. APK 签名分块
  3. ZIP 中央目录
  4. ZIP 中央目录结尾

APK 签名方案 v2 负责保护第 1、3、4 部分的完整性,以及第 2 部分包含的“APK 签名方案 v2 分块”中的 signed data 分块(也就是ID为:0x7109871a的数据)的完整性。

2.5 解析v2 签名块

怎么判断使用的是V2签名?如何定位签名块?签名块从第几个字节开始?

EOCD格式(第四部分):如下图所示 

 通过这个数据可以确定第三部分的位置

找到位置之后,在往前面读取16个字节(magic)。如果这16个字节匹配那就使用的是V2签名。

然后根据size of block来读取第二部分即可。

2.6 如何进行V2 签名

 

3. v3 方案

3.1 v3方案原理

v2 方案解决了安全问题以及安装时验证的效率问题,但是它并没有解决换签名问题。v3 APK 签名分块的格式与 v2 相同。APK 的 v3 签名会存储为一个“ID-值”对,其中 ID 为 0xf05368c0。

Android 9.0 中引入了新的签名方式,它的格式大体和 v2 类似,在 v2 插入的签名块(Apk Signature Block v2)中,又添加了一个新快(Attr块)。

在这个新块中,会记录我们之前的签名信息以及新的签名信息,以密钥转轮的方案,来做签名的替换和升级。这意味着,只要旧签名证书在手,我们就可以通过它在新的 APK 文件中,更改签名。

 

V3 签名新增的新块(attr)存储了所有的签名信息,由更小的 Level 块,以链表的形式存储。

其中每个节点都包含用于为之前版本的应用签名的签名证书,最旧的签名证书对应根节点,系统会让每个节点中的证书为列表中下一个证书签名,从而为每个新密钥提供证据来证明它应该像旧密钥一样可信。

这个过程有点类似 CA 证书的证明过程,已安装的 App 的旧签名,确保覆盖安装的 APK 的新签名正确,将信任传递下去。

3.2 如何进行v3 方案签名

 

4. v4 方案

4.1 v4 方案阐述

在传统的应用安装方案中,开发者通过 ADB(Android Debug Bridge)以有线或无线的方式与终端用户连接,或者用户从软件商店直接下载,然而该方案需要用户等待完整的安装包传输结束后才能启动安装,在这期间产生了不良的用户体验。

增量安装技术是一种流式的安装方案:一旦安装包的核心文件传输完成便可启动应用。流式安装意味着允许优先传输核心数据以启动应用,并在后台流式传输剩余数据。

在Android 11中,Google在内核中实现了增量文件系统用于对增量安装的支持。(详见https://source.android.com/devices/architecture/kernel/incfs)

这使得 Android os 可以通过 ADB 流式传输 APK。同时,Android 11 为了适应增量安装,添加了新的 v4签名方案。

此方案不改变前代签名方案而是创建一种新的签名:基于 APK 所有字节数据计算出 Merkle 哈希树,并将Merkle 树的根哈希、盐值作为签名数据进行包完整性验证。新的签名数据保存在 .idsig 文件中并且在进行增量安装前必须为APK创建对应的 v4 签名文件。

官网:v4签名

4.2 如何进行v4签名

 

总结

v1 签名实际上就是 JAR 签名的方案,它不会保护 APK 内的所有问题,存在安全和效率问题
v2 签名是一种全文件签名方案,增加了 APK 签名块(APK Signing Block),但仍无法解决更换签名的问题
v3 签名是 v2 的升级版,也被称为 v2+。在 V2 插入的签名块(Apk Signature Block V2)中,又添加了一个新快(Attr 块),它使用链表存储了所有的签名信息,验证时就像 CA 证书的证明过程。
v4 签名是为了 增量安装 技术而产生的一种新的签名方案。

参考链接

https://blog.csdn.net/weixin_46569059/article/details/120307144

https://blog.csdn.net/indeedes/article/details/124242326

posted @ 2023-04-26 10:40  皓然123  阅读(411)  评论(0)    收藏  举报