package androidx.browser.trusted; import android.annotation.SuppressLint; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; public class PackageIdentityUtils { private static final String TAG = "PackageIdentity"; @RequiresApi(28) public static class Api28Implementation implements SignaturesCompat { @Override // androidx.browser.trusted.PackageIdentityUtils.SignaturesCompat @Nullable public List getFingerprintsForPackage(String str, PackageManager packageManager) throws PackageManager.NameNotFoundException { PackageInfo packageInfo = packageManager.getPackageInfo(str, 134217728); ArrayList arrayList = new ArrayList(); SigningInfo signingInfo = packageInfo.signingInfo; if (signingInfo.hasMultipleSigners()) { for (Signature signature : signingInfo.getApkContentsSigners()) { arrayList.add(PackageIdentityUtils.getCertificateSHA256Fingerprint(signature)); } } else { arrayList.add(PackageIdentityUtils.getCertificateSHA256Fingerprint(signingInfo.getSigningCertificateHistory()[0])); } return arrayList; } @Override // androidx.browser.trusted.PackageIdentityUtils.SignaturesCompat public boolean packageMatchesToken(String str, PackageManager packageManager, TokenContents tokenContents) throws PackageManager.NameNotFoundException, IOException { List fingerprintsForPackage; if (tokenContents.getPackageName().equals(str) && (fingerprintsForPackage = getFingerprintsForPackage(str, packageManager)) != null) { return fingerprintsForPackage.size() == 1 ? packageManager.hasSigningCertificate(str, tokenContents.getFingerprint(0), 1) : tokenContents.equals(TokenContents.create(str, fingerprintsForPackage)); } return false; } } public static class Pre28Implementation implements SignaturesCompat { @Override // androidx.browser.trusted.PackageIdentityUtils.SignaturesCompat @SuppressLint({"PackageManagerGetSignatures"}) @Nullable public List getFingerprintsForPackage(String str, PackageManager packageManager) throws PackageManager.NameNotFoundException { PackageInfo packageInfo = packageManager.getPackageInfo(str, 64); ArrayList arrayList = new ArrayList(packageInfo.signatures.length); for (Signature signature : packageInfo.signatures) { byte[] certificateSHA256Fingerprint = PackageIdentityUtils.getCertificateSHA256Fingerprint(signature); if (certificateSHA256Fingerprint == null) { return null; } arrayList.add(certificateSHA256Fingerprint); } return arrayList; } @Override // androidx.browser.trusted.PackageIdentityUtils.SignaturesCompat public boolean packageMatchesToken(String str, PackageManager packageManager, TokenContents tokenContents) throws IOException, PackageManager.NameNotFoundException { List fingerprintsForPackage; if (str.equals(tokenContents.getPackageName()) && (fingerprintsForPackage = getFingerprintsForPackage(str, packageManager)) != null) { return tokenContents.equals(TokenContents.create(str, fingerprintsForPackage)); } return false; } } public interface SignaturesCompat { @Nullable List getFingerprintsForPackage(String str, PackageManager packageManager) throws PackageManager.NameNotFoundException; boolean packageMatchesToken(String str, PackageManager packageManager, TokenContents tokenContents) throws IOException, PackageManager.NameNotFoundException; } private PackageIdentityUtils() { } @Nullable public static byte[] getCertificateSHA256Fingerprint(Signature signature) { try { return MessageDigest.getInstance("SHA256").digest(signature.toByteArray()); } catch (NoSuchAlgorithmException unused) { return null; } } @Nullable public static List getFingerprintsForPackage(String str, PackageManager packageManager) { try { return getImpl().getFingerprintsForPackage(str, packageManager); } catch (PackageManager.NameNotFoundException e) { Log.e("PackageIdentity", "Could not get fingerprint for package.", e); return null; } } private static SignaturesCompat getImpl() { return Build.VERSION.SDK_INT >= 28 ? new Api28Implementation() : new Pre28Implementation(); } public static boolean packageMatchesToken(String str, PackageManager packageManager, TokenContents tokenContents) { try { return getImpl().packageMatchesToken(str, packageManager, tokenContents); } catch (PackageManager.NameNotFoundException | IOException e) { Log.e("PackageIdentity", "Could not check if package matches token.", e); return false; } } }