如何从包安装程序获取旁加载APK的签名



我正在尝试为设备构建自定义Android(基于AOSP 7.1)。我想获取要通过 USB 旁加载的应用程序的签名。系统上尚未安装这些应用程序。我的最终目标是像这样比较APK与平台签名的签名:https://gist.github.com/scottyab/b849701972d57cf9562e

我找到了很多指南,包括这个 - 如何获取APK签名签名?

并紧随李胜峰对接受答案的评论——"你需要将未安装的apk推送到你的程序可以获取apk的位置,比如SD_CARD,然后使用context.getPackageManager().getPackageAchiveInfo(NOT_INSTALL_APK_PATH,PackageManager.GET_SIGNATURES) .signatures[0]来获取它的哈希码。并比较它们">

我正在修改 AOSP (https://github.com/aosp-mirror/platform_packages_apps_packageinstaller/blob/master/src/com/android/packageinstaller/PackageInstallerActivity.java) 中的包安装程序应用程序。

我像这样修改了PackageInstallerActivity.javaprocessPackageUri函数(PackageManager.GET_SIGNATURES标志添加):

case SCHEME_FILE: {
File sourceFile = new File(packageUri.getPath());
PackageParser.Package parsed = PackageUtil.getPackageInfo(sourceFile);
// Check for parse errors
if (parsed == null) {
Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
showDialogInner(DLG_PACKAGE_ERROR);
setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
return false;
}
mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
PackageManager.GET_PERMISSIONS|PackageManager.GET_SIGNATURES, 0, 0, null,
new PackageUserState());
as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
} break;

签名验证功能

public boolean validateAppSignature() throws NameNotFoundException {
boolean sigMatch = false;
try {
for (Signature signature : mPkgInfo.signatures) {
// SHA1 the signature
String sha1 = getSHA1(signature.toByteArray());
// check if it matches hardcoded value
sigMatch = PLATFORM_SIGNATURE.equals(sha1);
if (sigMatch){
return sigMatch;  
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}

我希望获得APK签名的哈希值,但它抛出了此错误(来自adb logcat)W System.err: java.lang.NullPointerException: Attempt to get length of null array

可能来自尝试部分for (Signature signature : mPkgInfo.signatures).我怀疑PackageParser.generatePackageInfo部分是错误的,它没有返回任何签名。有人可以开导我吗?多谢。

附录:我发现PackageInstaller应用程序确实没有签名。我追踪了代码,并在src/com/android/packageinstaller/PackageUtil.java中找到了以下内容:

public static PackageParser.Package getPackageInfo(File sourceFile) {
final PackageParser parser = new PackageParser();
try {
return parser.parsePackage(sourceFile, 0);
} catch (PackageParserException e) {
return null;
}
}

parsePackage函数来自frameworks/base/core/java/android/content/pm/PackageParser.java,如下所示:

public Package parsePackage(File packageFile, int flags) throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
} else {
return parseMonolithicPackage(packageFile, flags);
}
}

它接受标志,但PackageUtil.java没有向它传递标志,我认为这就是我没有得到 apk 文件的任何签名的原因。我想如果我想要签名,我可能需要从PackageParser.java打电话给collectCertificates(Package, int)

我走在正确的轨道上吗?非常感谢您的意见。

由于@ChrisStratton的评论,我设法解决了这个问题。我需要从PackageInstallerActivity.java打电话给collectCertificates,如下所示:

case SCHEME_FILE: {
File sourceFile = new File(packageUri.getPath());
PackageParser.Package parsed = PackageUtil.getPackageInfoMod(sourceFile, PackageManager.GET_PERMISSIONS|PackageManager.GET_SIGNATURES);
// Check for parse errors
if (parsed == null) {
Log.w(TAG, "Parse error when parsing manifest. Discontinuing installation");
showDialogInner(DLG_PACKAGE_ERROR);
setPmResult(PackageManager.INSTALL_FAILED_INVALID_APK);
return false;
}
else {
try {
PackageParser.collectCertificates(parsed, PackageManager.GET_SIGNATURES);
} 
catch (Exception e) {
e.printStackTrace();
}
}
mPkgInfo = PackageParser.generatePackageInfo(parsed, null,
PackageManager.GET_PERMISSIONS|PackageManager.GET_SIGNATURES, 0, 0, null,
new PackageUserState());
as = PackageUtil.getAppSnippet(this, mPkgInfo.applicationInfo, sourceFile);
} break;

最新更新