如何从PackageInstaller获取侧载APK的签名

时间:2019-03-28 05:14:55

标签: android certificate apk digital-signature android-source

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

我发现了很多指南,包括本指南- How to get APK signing signature?

,然后按照李圣峰对已接受的答案的评论-“您需要将未安装的apk推送到您可以编程获取apk的位置,例如SD_CARD,然后使用context.getPackageManager().getPackageAchiveInfo(NOT_INSTALL_APK_PATH,PackageManager.GET_SIGNATURES) .signatures[0]来获取其hashCode。并进行比较”

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

我这样修改了processPackageUri的{​​{1}}函数(添加了PackageInstallerActivity.java标志):

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;

我希望获取APK签名的哈希值,但会引发此错误,(来自adb logcat) 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; }

可能来自尝试部分W System.err: java.lang.NullPointerException: Attempt to get length of null array。我怀疑for (Signature signature : mPkgInfo.signatures)部分是错误的,并且没有返回任何签名。有人可以启发我吗?非常感谢。

附录:我发现PackageInstaller应用程序确实没有签名。我跟踪了代码,并在PackageParser.generatePackageInfo中找到了以下内容:

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); } } 没有传递任何标志,我认为这就是我没有获得apk文件任何签名的原因。我想如果需要签名,可能需要从PackageUtil.java致电collectCertificates(Package, int)

我走对了吗?非常感谢您的投入。

1 个答案:

答案 0 :(得分:0)

由于@ChrisStratton的评论,我设法解决了这个问题。我需要从collectCertificates致电PackageInstallerActivity.java,就像这样:

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;