Android 17(API 级别 37)引入了 APK 签名方案 v3.2,这是一种混合签名方案,旨在支持 Android 生态系统向后量子密码学 (PQC) 过渡。
随着行业大规模部署 PQC 算法,v3.2 方案提供了纵深防御。它要求您使用经典算法(如 RSA 或 ECDSA)和 PQC 算法为 APK 签名。这种混合方法使用经典密码学来保护您的 APK,同时防御量子计算机的威胁。
用途和详细信息
v3.2 方案作为一种与行业标准一致的过渡机制运行。借助这种混合方法,您可以获得 PQC 的量子抗性优势,同时继续依赖经典签名算法的成熟安全性。一旦新标准化的 PQC 算法大规模建立运营成熟度,您就可以从这种混合配置过渡到单个 PQC 签名密钥。v3.2 签名方案的平台支持从 Android 17 开始。较低的 Android 版本会跳过 v3.2 分块,并使用之前的方案进行签名验证。
为了在此过渡期间保持安全性并防止降级攻击,v3.2 方案强制执行以下行为:
- 新密钥材料: 过渡到混合分块需要生成新的经典密钥和 PQC 密钥。 请勿在混合配置和非混合配置之间重复使用密钥材料。
- 隐式轮替: 平台将混合分块视为隐式密钥轮替。平台会将新的经典密钥附加到应用的现有签名谱系中作为倒数第二个密钥,并将新的 PQC 密钥视为应用的当前签名身份。
- 共享谱系: 为了成功执行隐式轮替,混合分块中的新经典密钥和新 PQC 密钥必须共享相同的签名祖先。您必须为两个新的混合签名者复制应用的现有签名历史记录(无论是单个原始密钥还是之前轮替的密钥的谱系)。平台使用此共享谱系来验证将应用过渡到混合方案的实体是否是应用当前签名身份的合法所有者。
- PQC 单个签名者限制: 在 PQC 的初始发布期间,Android 明确将 PQC 算法的使用限制为 v3.2 混合分块。平台不会使用之前的签名方案(例如 v2、v3.0 或 v3.1)验证单个签名者 PQC 配置。
- 过渡返回: 从 v3.2 混合分块过渡回单个签名者分块(无论是经典签名者还是 PQC 签名者,如果未来版本支持)时,平台会验证混合分块中的经典密钥和 PQC 密钥是否都存在于新的签名谱系中,并证明新的单个签名者。
过渡的最佳实践
为了保持与较低 Android 版本的兼容性,并在过渡到 PQC 签名期间提供安全的升级路径,APK 必须继续包含由单个经典密钥签名的标准 v3.0 或 v3.1 签名分块。由于只有 Android 17(API 级别 37)及更高版本支持 v3.2 混合方案,因此此要求允许运行较低版本的设备验证和安装应用。
经典回退配置
为了在 PQC 过渡期间提供运营安全网,请实现经典回退配置。
- 现有应用: 应用当前已建立的签名密钥 K0 是此回退的自然基础。
- 新应用: 生成基准经典签名密钥 K0 以及新的混合密钥 C_K1 和 PQC_K1,以建立初始身份。
在这两种情况下,APK 都必须包含由经典密钥 K0 签名的标准 v3.0 或 v3.1 签名分块,以及由新混合密钥 C_K1 和 PQC_K1 签名的 v3.2 混合分块。
在 v3.2 方案的初始部署期间,混合分块的签名谱系应向 K0 授予 ROLLBACK 功能。如果出现部署问题,此功能可让应用回退到经典签名,而不会中断用户更新。一旦有足够的运行时数据确认混合部署稳定,我们建议在后续更新中移除 ROLLBACK 功能,以全面保护您的新密钥。
长期配置要求
只要您的应用以仅支持混合方案的平台版本为目标,您就必须保持此混合签名配置。即使平台版本支持单个签名者 PQC 密钥,您也必须使用这两个密钥为以需要 v3.2 混合分块的版本为目标的任何 APK 签名。
APK 签名方案 v3.2 分块
APK 签名分块将 v3.2 签名分块与任何 v2、v3.0 和 v3.1 签名分块一起存储。
v3.2 分块结构与 v3.0 类似,但使用新的分块 ID 0x70e1c89f 来表示它是混合分块。有效的 v3.2 分块必须包含正好两个签名者。
支持的算法
v3.2 方案最初支持以下 PQC 签名算法:
- ML-DSA-65
- ML-DSA-87
这些算法与标准经典签名算法(例如 v3.0 和 v3.1 中支持的算法)配对,以形成混合分块。
格式
APK 签名分块将 APK 签名方案 v3.2 分块存储在 ID 0x70e1c89f 下。
v3.2 分块的格式与 v3.0 相同,但签名者元素的顶级序列必须包含正好两个以相同 SDK 版本为目标的条目:
- 带长度前缀的签名者的(带长度前缀)序列:
- 带长度前缀的签名者(经典)
- 带长度前缀的签名者 (PQC)
每个签名者都使用标准 v3 格式:
- 带长度前缀的签名数据:
- 带长度前缀的摘要的(带长度前缀)序列:
- 签名算法 ID(4 字节)
- 摘要(带长度前缀)
- 证书的(带长度前缀)序列:
- 带长度前缀的 X.509 证书(ASN.1 DER 形式)
- minSDK (uint32)
- maxSDK (uint32)
- 带长度前缀的其他属性的(带长度前缀)序列:
- ID (uint32)
- 值(可变长度:其他属性的长度 - 4 字节)
- minSDK (uint32)
- maxSDK (uint32)
- 带长度前缀的签名的(带长度前缀)序列:
- 签名算法 ID(4 字节)
- 带长度前缀的签名数据签名
- 带长度前缀的公钥(
SubjectPublicKeyInfo,ASN.1 DER 形式)
验证
在 Android 17(API 级别 37)及更高版本中,为了验证 v3.2 签名,平台会验证传统签名者和 PQC 签名者,确认它们的兼容性,并检查隐式轮替沿袭。在 Android 16(API 级别 36)及更低版本的平台版本中,平台不会处理此混合签名分块,而是使用之前的方案。
整个过程如下:
- 找到 APK 签名方案 v3.2 分块 (ID 0x70e1c89f)。
- 验证该分块是否包含正好两个 签名者。如果少于或多于两个,验证将失败。
- 验证一个签名者是否使用经典签名算法,另一个签名者是否使用 PQC 签名算法。如果两者都是经典签名算法或两者都是 PQC 签名算法,验证将失败。
- 验证两个签名者是否以完全相同的 SDK 范围(
minSdkVersion和maxSdkVersion)为目标。 - 对于两个签名者中的每一个,执行标准 v3 验证:
- 从签名中选择安全系数最高的受支持签名算法 ID。
- 使用公钥针对签名数据验证签名中的相应签名。
- 验证签名数据中的
minSdkVersion和maxSdkVersion是否与未签名的minSdkVersion和maxSdkVersion匹配。 - 解析证书并验证第一个证书是否与公钥匹配。
- 解析其他属性以提取轮替证明结构。
- 验证签名历史记录(proof-of-rotation):
- 检查两个签名者是否具有相同的先前签名历史记录。
- 谱系长度必须匹配,并且所有证书和功能标志(直到当前签名者)都必须相同。
- 如果历史记录匹配,请合并谱系:将经典签名者的证书视为 PQC 签名者的证书的前身,并将 PQC 签名者指定为当前终端节点。
- 验证内容摘要:
- 为两个签名者迭代摘要映射。
- 验证对于任何匹配的摘要算法,经典签名者和 PQC 签名者之间计算出的摘要值是否相同。
- 使用经过验证的签名者中的匹配摘要来验证 APK 内容的完整性(类似于 v2 和 v3)。
- 如果应用已安装,请验证软件包更新谱系:
- 从单个签名者更新:如果安装的应用使用单个经典密钥签名,则该密钥必须存在于新混合分块的签名谱系中,作为混合签名者的前身。
- 从混合签名者更新以继续混合:如果安装的应用使用 v3.2 混合分块签名,则之前的经典密钥和 PQC 密钥都必须保留在更新 APK 的 v3.2 分块中作为当前活跃签名者,或者两者都必须存在于证明新轮替的混合密钥的新签名谱系中。
- 从混合签名者过渡:如果安装的应用使用 v3.2 混合分块签名,并且更新 APK 过渡回单个签名者(PQC 或经典),则之前的两个混合签名者都必须存在于更新 APK 的签名谱系中,并证明新的单个签名密钥。
- 无效的更新路径:如果开发者尝试仅使用其中一个混合密钥作为单个签名者来更新混合签名的应用,而没有进行适当的轮替,则更新将失败。两个密钥都必须明确参与任何过渡,以防止降级攻击。
- 如果任何步骤失败,验证将失败。
剥离保护措施
为了防止降级攻击到较低的签名方案,v3.2 方案包含类似于之前方案迭代的剥离保护属性。
签名工具会将两个特定的混合剥离保护属性写入 v3.0 和 v3.1 签名分块的其他属性中。这些属性定义了 v3.2 混合分块必须存在并经过验证的确切 SDK 版本边界:
- 最低 SDK 版本属性 (ID
0xbf940529): 此 属性的值决定了混合签名分块支持的最低 SDK 版本。 - 最高 SDK 版本属性
(ID
0x9f06b79c): 此属性的值决定了 混合签名分块支持的最高 SDK 版本。当较高的平台版本不需要混合签名时,您可以使用此属性过渡到单个签名者配置。
如果平台因分块缺失或其 SDK 范围不适用于设备而跳过 v3.2 验证,则平台会针对存在的下一个分块验证 APK。如果较早的分块包含这些剥离保护属性,则平台会应用以下检查:
- 存在性和范围验证: 如果 v3.0 或 v3.1
签名分块包含最低 SDK 属性(ID
0xbf940529,值 X)或最高 SDK 属性(ID0x9f06b79c,值 Y),平台要求 v3.2 混合分块存在于 APK 中。平台会读取混合分块,以验证其目标 SDK 范围是否与这些属性指定的边界匹配。如果 v3.2 分块缺失,或者其内部最低和 最高 SDK 目标值不等于 X 和 Y,平台 将拒绝安装。 - 在范围内强制执行: 如果设备的 SDK 版本属于 这些属性指定的有效范围(当您提供 最高属性时,大于或 等于 X,且小于或等于 Y),平台会严格要求使用 v3.2 混合分块进行 签名验证。如果平台在此目标 SDK 范围内的设备上验证 v3.0 或 v3.1 分块,平台将拒绝安装,因为 v3.2 分块被恶意绕过或剥离。
通过强制执行这些边界,平台可以确定 APK 何时必须包含 v3.2 分块。如果分块已被剥离,平台将拒绝安装以防止降级攻击。
验证您的实现
如需测试 v3.2 签名方案的实现,请运行位于 cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ 中的 HybridSignatureVerificationTest.java CTS 测试。
这些测试涵盖了一系列全面的场景,包括成功安装、从仅经典版本更新、使用 ROLLBACK 功能进行回滚过渡,以及验证剥离攻击缓解措施。