基于Flutter通过签名检测应用篡改:Play Store签名不一致求助
问题描述
本地分发的生产构建版本中,应用篡改检测代码运行正常,但上传至Play Store后获取到的应用签名与预期不一致。
使用的代码片段:
//get the current app signature public static String getCurrentAppSignature(Context context) throws PackageManager.NameNotFoundException, NoSuchAlgorithmException { PackageManager packageManager = context.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); // Get the first signature from the package info. Signature signature = packageInfo.signatures[0]; // Get the SHA-1 hash of the signature. byte[] sha1 = getSHA1(signature.toByteArray()); // Convert the SHA-1 hash to a string. String sha1String = convertToHexString(sha1); return sha1String; } //get the SHA1 hash private static byte[] getSHA1(byte[] data) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(data); return digest.digest(); } //convert to HexString private static String convertToHexString(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { sb.append(String.format("%02x", b)); } return sb.toString(); }
解决方案
核心原因
启用App Signing by Google Play后,Play Store会使用Google管理的分发密钥重新签名你的应用。本地构建时用的是你自己的上传密钥签名,而用户从Play Store下载的应用是分发密钥签名的,两者哈希值自然不同。
具体修复步骤
获取分发签名的SHA-1值
登录Google Play Console,进入你的应用 > 应用签名 > 复制"应用签名证书"下的SHA-1值,替换代码中用于校验的预期签名值。替换废弃API并兼容多版本
PackageManager.GET_SIGNATURES在Android 9(API 28)已被废弃,无法正确获取高版本系统的签名信息,需改用GET_SIGNING_CERTIFICATES,同时兼容低版本:public static String getCurrentAppSignature(Context context) throws PackageManager.NameNotFoundException, NoSuchAlgorithmException { PackageManager packageManager = context.getPackageManager(); String packageName = context.getPackageName(); int flags = PackageManager.GET_SIGNING_CERTIFICATES; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { flags = PackageManager.GET_SIGNATURES; } PackageInfo packageInfo = packageManager.getPackageInfo(packageName, flags); Signature[] signatures; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { SigningInfo signingInfo = packageInfo.signingInfo; // 处理多签名场景,优先取APK内容签名者 signatures = signingInfo.hasMultipleSigners() ? signingInfo.getApkContentsSigners() : signingInfo.getSigningCertificateHistory(); } else { signatures = packageInfo.signatures; } // 遍历所有签名,避免遗漏合法签名 for (Signature signature : signatures) { byte[] sha1 = getSHA1(signature.toByteArray()); String sha1String = convertToHexString(sha1); return sha1String; } return null; }多签名校验逻辑优化
如果应用存在多签名(比如同时配置了上传密钥和分发密钥),需修改校验逻辑:遍历所有获取到的签名,只要与预先存储的任意一个合法签名匹配,就判定为未篡改。签名值安全存储
不要将合法签名值直接硬编码在代码中,建议存储在加密的assets文件、安全存储服务或后端接口中,降低被逆向篡改的风险。
内容的提问来源于stack exchange,提问作者vishnu
相关产品推荐
相关产品推荐

