androiddevice-policy-manager

PackageManager.getPackageArchiveInfo with GET_SIGNING_CERTIFICATES returning null signing info


I am trying to get the signatures from an apk file prior to installing, however I am getting null signingInfo object. The PackageInfo is properly populated with all of the other data related to the package.

If I install the apk, then use getPackageInfo, the signingInfo will be populated. Not sure why its failing to obtain it from the apk itself.

Am I missing something on getting a signature from an apk file?

    // This call works after installing the apk, it is able to pull the signature without issues
    @Override
    public boolean isPackageSignatureValid(final String packageName)
    {
        try
        {
            android.content.pm.PackageManager pm = context.getPackageManager();
            PackageInfo packageInfo = pm.getPackageInfo(packageName, android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES);

            return validateSignature(packageInfo);
        }
        catch (android.content.pm.PackageManager.NameNotFoundException notFoundException)
        {
            return false;
        }
    }

    // Calling this on the apk file prior to install, signingInfo is always null
    @Override
    public boolean isApkSignatureValid(final String apkFilePath)
    {
        android.content.pm.PackageManager pm = context.getPackageManager();
        PackageInfo packageInfo = pm.getPackageArchiveInfo(apkFilePath, android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES);

        return validateSignature(packageInfo);
    }

    private boolean validateSignature(final PackageInfo packageInfo)
    {
        Signature[] signatures;

        if (packageInfo == null || packageInfo.signingInfo == null)
        {
            return false;
        }

        if (packageInfo.signingInfo.hasMultipleSigners())
        {
            signatures = packageInfo.signingInfo.getApkContentsSigners();
        }
        else
        {
            signatures = packageInfo.signingInfo.getSigningCertificateHistory();
        }

        ArrayList<Integer> packageHashes = new ArrayList<>();
        for (Signature sig : signatures)
        {
            // I know this is not the best way of doing this, please ignore for now as its not the main issue
            packageHashes.add(sig.hashCode());
        }

        return isHashValid(packageHashes);
    }

Solution

  • GET_SIGNING_CERTIFICATES flag is added starting from API level 28.

    Before that you can use GET_SIGNATURES.

    If getPackageArchiveInfo() still returns null in API 28+, you can back to the deprecated GET_SIGNATURES flag.

    Starting from API level Tiramisu, getPackageArchiveInfo() is deprecated, and this version can be used instead which accepts PackageManager.PackageInfoFlags flag set instead of PackageManager flags.