diff --git a/app/src/main/java/com/gh/common/util/PackageUtils.java b/app/src/main/java/com/gh/common/util/PackageUtils.java index deee31752a..298bd8f933 100644 --- a/app/src/main/java/com/gh/common/util/PackageUtils.java +++ b/app/src/main/java/com/gh/common/util/PackageUtils.java @@ -14,9 +14,6 @@ import android.os.Build; import android.os.Bundle; import android.text.TextUtils; -import androidx.annotation.Nullable; -import androidx.core.content.FileProvider; - import com.g00fy2.versioncompare.Version; import com.gh.common.constant.Constants; import com.gh.gamecenter.BuildConfig; @@ -33,11 +30,18 @@ import org.json.JSONObject; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.InputStream; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import androidx.annotation.Nullable; +import androidx.core.content.FileProvider; public class PackageUtils { @@ -178,7 +182,6 @@ public class PackageUtils { try { Signature sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0]; - // todo 目前测试的情况华为/小米/锤子均出现ANR // Fuck HUAWEI, 华为系统调用 getPackageArchiveInfo 获取魔羯 apk 的签名时会耗时超过5秒造成 ANR,没有找到解决方法 // 如果可以的话尽量避免调用 getPackageArchiveInfo 方法 Signature releaseSig = context.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_SIGNATURES).signatures[0]; @@ -189,6 +192,28 @@ public class PackageUtils { return false; } + // 从 APK 中获取公钥(只支持包含 V1 签名的 APK + private static String getApkSignatureFromFile(String apkFilePath) { + try { + ZipFile apkFile = new ZipFile(apkFilePath); + Enumeration entries = apkFile.entries(); + + while (entries.hasMoreElements()) { + ZipEntry entry = ((ZipEntry) entries.nextElement()); + String entryName = entry.getName(); + if (entryName.contains("CERT.RSA")) { + InputStream is = apkFile.getInputStream(entry); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate) cf.generateCertificates(is).toArray()[0]; + return cert.getPublicKey().toString(); + } + } + return ""; + } catch (Exception e) { + return ""; + } + } + /* * 解析签名 */ @@ -254,6 +279,13 @@ public class PackageUtils { return true; } + // 从 APK 文件里读取公钥,与已安装的公钥比较判断是否一样 + String signatureFromApk = getApkSignatureFromFile(path); + if (!TextUtils.isEmpty(signatureFromApk) + && signatureFromApk.equals(getApkSignatureByPackageName(context, packageName))) { + return true; + } + // 若已安装的应用的签名与即将要安装的签名一致也返回 true return compareSignatureBetweenInstalledAppWithApk(context, packageName, path); }