Android P v3签名新特性

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {

PackageParser pp = new PackageParser();

pp.setSeparateProcesses(mSeparateProcesses);

pp.setDisplayMetrics(mMetrics);

pp.setCallback(mPackageParserCallback);

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “parsePackage”);

final PackageParser.Package pkg;

try {

pkg = pp.parsePackage(tmpPackageFile, parseFlags);

DexMetadataHelper.validatePackageDexMetadata(pkg);

} catch (PackageParserException e) {

res.setError(“Failed parse during installPackageLI”, e);

return;

} finally {

Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

}

try {

// either use what we’ve been given or parse directly from the APK

if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) {

pkg.setSigningDetails(args.signingDetails);

} else {

PackageParser.collectCertificates(pkg, false /* skipVerify */);

}

} catch (PackageParserException e) {

res.setError(“Failed collect during installPackageLI”, e);

return;

}

}

  • 首先实例化一个PackageParser的对象pp,利用这个对象的parsePackage()方法,返回一个位于PackageParser类中的内部类Package的实例对象pkg,其中包含着要安装的应用的一些信息

  • 利用PackageParser的一个静态方法collectCertificates(pkg,false)收集证书,这里就是验签的入口了

PackageParser.collectCertificates()

frameworks/base/core/java/android/content/pm/PackageParser.java

public static void collectCertificates(Package pkg, boolean skipVerify)

throws PackageParserException {

collectCertificatesInternal(pkg, skipVerify);

final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;

for (int i = 0; i < childCount; i++) {

Package childPkg = pkg.childPackages.get(i);

childPkg.mSigningDetails = pkg.mSigningDetails;

}

}

private static void collectCertificatesInternal(Package pkg, boolean skipVerify)

throws PackageParserException {

pkg.mSigningDetails = SigningDetails.UNKNOWN;

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “collectCertificates”);

try {

collectCertificates(pkg, new File(pkg.baseCodePath), skipVerify);

if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {

for (int i = 0; i < pkg.splitCodePaths.length; i++) {

collectCertificates(pkg, new File(pkg.splitCodePaths[i]), skipVerify);

}

}

} finally {

Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

}

}

private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify)

throws PackageParserException {

final String apkPath = apkFile.getAbsolutePath();

int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR;

if (pkg.applicationInfo.isStaticSharedLibrary()) {

// must use v2 signing scheme

minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;

}

SigningDetails verified;

if (skipVerify) {

// systemDir APKs are already trusted, save time by not verifying

verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(

apkPath, minSignatureScheme);

} else {

verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);

}

// Verify that entries are signed consistently with the first pkg

// we encountered. Note that for splits, certificates may have

// already been populated during an earlier parse of a base APK.

if (pkg.mSigningDetails == SigningDetails.UNKNOWN) {

pkg.mSigningDetails = verified;

} else {

if (!Signature.areExactMatch(pkg.mSigningDetails.signatures, verified.signatures)) {

throw new PackageParserException(

INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,

apkPath + " has mismatched certificates");

}

}

}

  • collectCertificates重载到三个参数的方法,因为跳过检查的参数为false,最终调用ApkSignatureVerifier类中的verify方法
ApkSignatureVerifier.verify()

frameworks/base/core/java/android/util/apk/ApkSignatureVerifier.java

public static PackageParser.SigningDetails verify(String apkPath,

@SignatureSchemeVersion int minSignatureSchemeVersion)

throws PackageParserException {

if (minSignatureSchemeVersion > SignatureSchemeVersion.SIGNING_BLOCK_V3) {

// V3 and before are older than the requested minimum signing version

throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,

"No signature found in package of version " + minSignatureSchemeVersion

  • " or newer for package " + apkPath);

}

// first try v3

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “verifyV3”);

try {

ApkSignatureSchemeV3Verifier.VerifiedSigner vSigner =

ApkSignatureSchemeV3Verifier.verify(apkPath);

Certificate[][] signerCerts = new Certificate[][] { vSigner.certs };

Signature[] signerSigs = convertToSignatures(signerCerts);

Signature[] pastSignerSigs = null;

int[] pastSignerSigsFlags = null;

if (vSigner.por != null) {

// populate proof-of-rotation information

pastSignerSigs = new Signature[vSigner.por.certs.size()];

pastSignerSigsFlags = new int[vSigner.por.flagsList.size()];

for (int i = 0; i < pastSignerSigs.length; i++) {

pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded());

pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i);

}

}

return new PackageParser.SigningDetails(

signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3,

pastSignerSigs, pastSignerSigsFlags);

  • 这里会首先尝试v3的签名方案,然后v2v1依次尝试,这里只给出v3的部分,最终返回一个PackageParser类中的内部类SigningDetails的对象

  • 检查v3版本签名调用ApkSignatureSchemeV3Verifier类中的verify()方法

ApkSignatureSchemeV3Verifier.verify()

frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java

private static final int APK_SIGNATURE_SCHEME_V3_BLOCK_ID = 0xf05368c0;

public static VerifiedSigner verify(String apkFile)

throws SignatureNotFoundException, SecurityException, IOException {

return verify(apkFile, true);

}

/**

  • Returns the certificates associated with each signer for the given APK without verification.

  • This method is dangerous and should not be used, unless the caller is absolutely certain the

  • APK is trusted. Specifically, verification is only done for the APK Signature Scheme v3

  • Block while gathering signer information. The APK contents are not verified.

  • @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v3.

  • @throws IOException if an I/O error occurs while reading the APK file.

*/

public static VerifiedSigner plsCertsNoVerifyOnlyCerts(String apkFile)

throws SignatureNotFoundException, SecurityException, IOException {

return verify(apkFile, false);

}

private static VerifiedSigner verify(String apkFile, boolean verifyIntegrity)

throws SignatureNotFoundException, SecurityException, IOException {

try (RandomAccessFile apk = new RandomAccessFile(apkFile, “r”)) {

return verify(apk, verifyI

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值