Android APK安装时的签名校验原理
Android APK安装时的签名校验原理主要是通过验证APK文件的签名信息来确保APK文件的完整性和来源的可信性。具体过程如下:
-
签名生成:开发者使用Android SDK提供的工具生成一个密钥库文件(.keystore),其中包含一个或多个数字证书。然后,使用这些工具将APK文件与数字证书进行关联,生成一个签名文件(如.RSA文件)。
-
签名打包:签名文件与APK文件一起打包成最终的APK文件,供用户下载和安装。
-
安装时校验:当用户尝试安装APK文件时,Android系统会执行以下校验步骤:
- 提取签名信息:从APK文件中提取出签名文件(如.RSA文件)和证书信息。
- 计算摘要:使用与签名时相同的哈希算法(如SHA-256)对APK文件的内容进行哈希计算,得到一个新的摘要。
- 验证签名:使用证书中的公钥对签名文件中的签名进行解密,得到原始的摘要。然后,将这个解密得到的摘要与刚刚计算出的新摘要进行比较。
- 检查证书链:验证证书链的有效性,确保证书是由受信任的证书颁发机构(CA)签发的,或者证书链中的某个证书已经预置在Android系统中。
-
结果判断:如果签名信息一致且证书链有效,Android系统会认为APK文件是完整且来自可信的开发者,允许用户安装和运行该APK文件。如果签名信息不一致或证书链无效,Android系统会提示用户安装失败或存在潜在风险。
V1到V4签名的异同和特点
签名版本 | 引入时间 | 签名方式 | 安全性 | 兼容性 | 特点 |
---|---|---|---|---|---|
V1 (JAR签名) | 早期Android版本 | 基于Java签名框架 | 较低 | 广泛 | - 将整个APK文件作为一个整体进行签名。 - 使用MD5和SHA1哈希算法,以及RSA或DSA加密算法。 - 适用于所有Android系统版本,但安全性较低。 |
V2 (APK Signature Scheme v2) | Android 7.0 (API 24) | 增量签名 | 较高 | Android 7.0及以上 | - 只对APK内容的部分进行签名,提高签名效率和验证性能。 - 使用SHA256哈希算法和ECDSA签名算法。 - 提供对APK文件进行验证和完整性检查的机制。 - 与V1签名共存,确保兼容性。 |
V3 (APK Signature Scheme v3) | Android 9.0 (API 28) | 进一步增强V2签名 | 更高 | Android 9.0及以上 | - 采用更强大的签名算法和更长的密钥长度。 - 仍然采用增量签名方式。 - 提供签名块的完整性保护和签名的附加时间戳。 - 可选使用,应用可同时包含V1、V2和V3签名。 |
V3.1 (APK Signature Scheme v3+) | Android 13 | V3签名的改进版本 | 更高 | Android 13及以上 | - 解决V3签名在轮替方面的一些已知问题。 - 支持SDK版本定位功能,允许轮替定位到平台的更高版本。 - 使用在Android 12或更低版本中无法识别的分块ID。 |
V4 (APK Signature Scheme v4+) | Android 11.0 | 支持ADB增量APK安装 | 特定场景 | Android 11及以上 | - 基于Merkle哈希树计算APK的所有字节。 - 完全遵循fs-verity哈希树的结构。 - 签名存储在单独的.apk.idsig文件中,不包含在APK文件中。 - 需要V2或V3签名作为补充,用于ADB增量安装。 |
总结
Android APK签名是确保APK文件的完整性和来源可信的重要机制。签名过程使用开发者的私钥对APK进行签名,而用户设备上的系统会使用开发者的公钥来验证签名的有效性。结合这篇文章的内容,我们可以从原理和源码层面(特别是PackageManagerService
,简称PMS)来详细说明APK签名的过程。
APK签名原理
-
签名的目的:
- 完整性:确保APK在传输或存储过程中未被篡改。
- 来源可信:确保APK来自特定的开发者,且未被第三方冒充。
- 防止篡改:如果APK被修改,签名会失效,系统会拒绝安装或运行。
-
签名过程:
- 开发者使用私钥对APK的摘要(如SHA-256)进行加密,生成签名。
- 签名和开发者的公钥证书会被打包到APK的
META-INF
目录中。 - 安装时,系统会使用公钥验证签名的有效性,并检查APK的完整性。
-
签名验证流程:
- 系统提取APK中的签名文件和公钥证书。
- 使用公钥解密签名,得到APK的摘要。
- 重新计算APK的摘要,并与解密后的摘要对比,验证是否一致。
结合PMS源码分析签名验证
PackageManagerService
(PMS)是Android系统中负责APK安装、卸载和管理的核心服务。签名验证的逻辑主要在PMS中实现。以下是源码中的关键点:
1. 签名验证入口
在PMS中,APK的签名验证主要在PackageParser
和PackageManagerService
中完成。以下是关键方法:
// frameworks/base/core/java/android/content/pm/PackageParser.java
public class PackageParser {
public static class Package {
// APK的签名信息
public Signature[] signatures;
}
// 解析APK并验证签名
public Package parsePackage(File packageFile, int flags) {
// 解析APK文件
Package pkg = parsePackage(packageFile, flags);
// 验证签名
verifySignatures(pkg);
return pkg;
}
private void verifySignatures(Package pkg) {
// 获取APK的签名信息
Signature[] signatures = pkg.signatures;
if (signatures == null || signatures.length == 0) {
throw new PackageManagerException("APK has no signatures");
}
// 验证签名的有效性
for (Signature signature : signatures) {
if (!signature.verify()) {
throw new PackageManagerException("Signature verification failed");
}
}
}
}
2. PMS中的安装流程
在PMS中,APK的安装流程会调用PackageParser
来解析APK并验证签名:
// frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub {
public void installPackage(String packageName, int flags) {
// 解析APK
PackageParser.Package pkg = mPackageParser.parsePackage(packageFile, flags);
// 验证签名
verifySignatures(pkg);
// 继续安装流程
installPackageTracedLI(pkg);
}
private void verifySignatures(PackageParser.Package pkg) {
// 获取APK的签名信息
Signature[] signatures = pkg.mSignatures;
if (signatures == null || signatures.length == 0) {
throw new PackageManagerException("APK has no signatures");
}
// 验证签名的有效性
for (Signature signature : signatures) {
if (!signature.verify()) {
throw new PackageManagerException("Signature verification failed");
}
}
}
}
3. 签名验证的核心逻辑
签名的验证逻辑主要在Signature
类中实现:
// frameworks/base/core/java/android/content/pm/Signature.java
public class Signature {
private final byte[] mSignature;
public Signature(byte[] signature) {
this.mSignature = signature;
}
// 验证签名的有效性
public boolean verify() {
// 使用公钥解密签名
PublicKey publicKey = getPublicKey();
try {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(mSignature);
return signature.verify(mSignature);
} catch (Exception e) {
return false;
}
}
private PublicKey getPublicKey() {
// 从证书中提取公钥
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(mSignature));
return cert.getPublicKey();
}
}
APK签名验证的完整流程
-
解析APK:
- PMS通过
PackageParser
解析APK文件,提取签名信息。
- PMS通过
-
验证签名:
- 使用开发者的公钥解密签名,得到APK的摘要。
- 重新计算APK的摘要,并与解密后的摘要对比。
-
安装APK:
- 如果签名验证通过,PMS会继续安装流程;否则,抛出异常并拒绝安装。
总结
- APK签名是Android安全机制的核心部分,确保APK的完整性和来源可信。
- PMS是Android系统中负责APK安装和管理的核心服务,签名验证的逻辑主要在PMS和
PackageParser
中实现。 - 通过源码分析,我们可以看到PMS如何解析APK、提取签名信息,并使用公钥验证签名的有效性。
通过结合源码和原理,我们可以更深入地理解Android APK签名的工作机制。