117 lines
5.4 KiB
Java
117 lines
5.4 KiB
Java
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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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<byte[]> 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;
|
|
}
|
|
}
|
|
}
|