签名的详细过程是怎样的

Table of Contents

apksigner 是 Android 官方提供的用于签名和验证 APK 文件的工具。它的核心原理基于数字签名技术,通过使用开发者的私钥对 APK 文件进行签名,确保 APK 的完整性和来源可信性。

1. 数字签名的基础

数字签名是一种基于非对称加密(公钥加密)的技术,主要包括以下步骤:

  1. 生成密钥对
    • 开发者生成一对密钥:私钥(用于签名)和公钥(用于验证)。
    • 私钥必须保密,而公钥可以公开。
  2. 签名
    • 使用私钥对数据的摘要(哈希值)进行加密,生成签名。
  3. 验证
    • 使用公钥解密签名,得到摘要,并与数据的实际摘要进行比对,验证数据的完整性和来源。

2. APK 签名的核心原理

apksigner 使用数字签名技术对 APK 文件进行签名,具体过程如下:

2.1 计算 APK 的摘要

  • 操作:对 APK 文件的内容计算哈希值(摘要)。
  • 算法:通常使用 SHA-256 等哈希算法。
  • 原因
    • 哈希值是对 APK 文件内容的唯一标识。
    • 即使 APK 文件内容发生微小变化,哈希值也会完全不同。

2.2 使用私钥加密摘要

  • 操作:使用开发者的私钥对 APK 的摘要进行加密,生成签名。
  • 算法:通常使用 RSA 或 ECDSA 等非对称加密算法。
  • 原因
    • 私钥加密的签名可以证明 APK 是由特定开发者发布的。
    • 只有拥有私钥的开发者才能生成有效的签名。

2.3 将签名嵌入 APK

  • 操作:将签名和开发者的公钥证书嵌入 APK 文件的特定位置。
  • 原因
    • 签名和公钥证书是验证 APK 完整性和来源的关键信息。
    • 用户设备可以使用公钥证书验证签名。

3. APK 签名的验证过程

当用户安装 APK 时,Android 系统会验证 APK 的签名,确保其完整性和来源可信。验证过程如下:

3.1 提取签名和公钥证书

  • 操作:从 APK 文件中提取签名和开发者的公钥证书。
  • 原因
    • 签名和公钥证书是验证的基础。

3.2 计算 APK 的摘要

  • 操作:对 APK 文件的内容重新计算哈希值(摘要)。
  • 原因
    • 用于与签名中的摘要进行比对。

3.3 使用公钥解密签名

  • 操作:使用开发者的公钥解密签名,得到原始的摘要。
  • 原因
    • 只有使用正确的公钥才能解密签名。

3.4 比对摘要

  • 操作:将解密后的摘要与重新计算的摘要进行比对。
  • 原因
    • 如果两者一致,说明 APK 文件未被篡改,且来源可信。
    • 如果不一致,说明 APK 文件可能被篡改或签名无效。

4. APK 签名方案(V1、V2、V3)

apksigner 支持多种签名方案,每种方案有不同的实现方式和安全性:

4.1 V1 签名(JAR 签名)

  • 原理
    • 基于 JAR 文件的签名机制。
    • 对 APK 中的每个文件单独签名,并将签名信息存储在META-INF目录中。
  • 优点
    • 兼容所有 Android 版本。
  • 缺点
    • 安全性较低,容易被篡改。

4.2 V2 签名(APK 签名方案 v2)

  • 原理
    • 对整个 APK 文件进行签名,而不是单独对每个文件签名。
    • 签名信息存储在 APK 文件的特定区块中。
  • 优点
    • 提供更高的安全性,防止篡改。
    • 支持更快的安装和验证。
  • 缺点
    • 仅支持 Android 7.0(API 24)及以上版本。

4.3 V3 签名(APK 签名方案 v3)

  • 原理
    • 在 V2 签名的基础上,增加了对密钥轮换的支持。
    • 允许开发者在更新应用时更换签名密钥。
  • 优点
    • 进一步增强安全性,支持密钥管理。
  • 缺点
    • 仅支持 Android 9.0(API 28)及以上版本。

5. apksigner 的使用示例

以下是使用 apksigner 签名和验证 APK 的示例:

5.1 签名 APK

apksigner sign --ks my-release-key.jks --out my-app-signed.apk my-app-unsigned.apk
  • --ks:指定密钥库文件。
  • --out:指定签名后的 APK 文件名。
  • my-app-unsigned.apk:未签名的 APK 文件。

5.2 验证签名

apksigner verify --verbose my-app-signed.apk
  • --verbose:显示详细的验证信息。

6. v2 签名后的签名信息和公钥是放在哪的

在 Android 的 V2 签名方案(APK Signature Scheme v2)中,签名信息和公钥证书被存储在 APK 文件的特定区块中,而不是像 V1 签名那样放在 META-INF 目录下。

6.1. V2 签名的存储位置

V2 签名信息存储在 APK 文件的 APK Signing Block 中。APK Signing Block 是一个独立的数据块,位于 ZIP 文件中央目录(Central Directory)文件内容(File Content) 之间。

一个典型的 APK 文件结构如下:

  1. 文件内容(File Content):包含 APK 的所有文件数据。
  2. APK Signing Block:存储 V2 签名信息。
  3. ZIP 中央目录(Central Directory):ZIP 文件的目录结构。
  4. ZIP 文件尾(End of Central Directory, EOCD):ZIP 文件的结束标记。

6.2. APK Signing Block 的结构

APK Signing Block 是一个自定义的数据块,其结构如下:

  • 块大小(Block Size):一个 8 字节的字段,表示 APK Signing Block 的总大小。
  • 键值对列表(Key-Value Pairs):APK Signing Block 包含多个键值对(ID-Value Pairs),每个键值对由一个 ID 和对应的值组成。V2 签名信息存储在 ID 为 0x7109871a 的键值对中。
  • 块尾(Block Footer):一个 16 字节的字段,包含 APK Signing Block 的魔数(Magic Number)和块大小。

6.3. V2 签名信息的内容

在 ID 为 0x7109871a 的键值对中,存储了以下信息:

  • 签名者信息(Signer Information)
    • 公钥证书:开发者的公钥证书(X.509 格式)。
    • 签名:对 APK 文件的签名。
    • 摘要:APK 文件的摘要(哈希值)。
    • 签名算法:使用的签名算法(如 SHA-256 with RSA)。
  • 签名块摘要(Signed Data Digest):对整个 APK 文件(不包括 APK Signing Block)的摘要。用于验证 APK 文件的完整性。
  • 签名块签名(Signed Data Signature):使用开发者的私钥对签名块摘要进行加密生成的签名。用于验证 APK 文件的来源。

6.4. V2 签名的验证过程

当 Android 系统安装或运行 APK 时,会验证 V2 签名的有效性,具体过程如下:

  • 提取 APK Signing Block:从 APK 文件中提取 APK Signing Block。
  • 解析签名信息:从 APK Signing Block 中提取 V2 签名信息(ID 为 0x7109871a 的键值对)。
  • 验证签名:使用开发者的公钥解密签名,得到摘要。重新计算 APK 文件的摘要,并与解密后的摘要进行比对。如果一致,说明 APK 文件未被篡改,且来源可信。

6.5. V2 签名的优势

  • 更高的安全性:V2 签名验证整个 APK 文件的完整性,防止篡改。
  • 更快的安装:V2 签名优化了安装时的验证过程。
  • 支持增量更新:V2 签名与 Android 的增量更新机制兼容。

明天再详细了解一下[[20250124-apk打包过程]]中提到的对齐优化