{"record":{"id":"da0d7e421c548804","repo":"MuntashirAkon/AppManager","slug":"signing-info-verification-failed-ninstalled-certchecksumlist","errorCode":null,"errorMessage":"Signing info verification failed.\\nInstalled: ${certChecksumList}\\nBackup: ${Arrays.toString(certChecksums)}","messagePattern":"Signing info verification failed\\.\\\\nInstalled: (.+?)\\\\nBackup: (.+?)","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"critical","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":292,"sourceCode":"    private void restoreApkFiles() throws BackupException {\n        if (!mBackupFlags.backupApkFiles()) {\n            throw new BackupException(\"APK restore is requested but backup doesn't contain any source files.\");\n        }\n        Path[] backupSourceFiles = mBackupItem.getSourceFiles();\n        if (backupSourceFiles.length == 0) {\n            // No source backup found\n            throw new BackupException(\"Source restore is requested but there are no source files.\");\n        }\n        boolean isVerified = true;\n        if (mPackageInfo != null) {\n            // Check signature of the installed app\n            List<String> certChecksumList = Arrays.asList(PackageUtils.getSigningCertChecksums(mBackupInfo.checksumAlgo, mPackageInfo, false));\n            String[] certChecksums = BackupItems.Checksum.getCertChecksums(mChecksum);\n            for (String checksum : certChecksums) {\n                if (certChecksumList.contains(checksum)) continue;\n                isVerified = false;\n                if (!mRequestedFlags.skipSignatureCheck()) {\n                    throw new BackupException(\"Signing info verification failed.\" +\n                            \"\\nInstalled: \" + certChecksumList +\n                            \"\\nBackup: \" + Arrays.toString(certChecksums));\n                }\n            }\n        }\n        if (!mRequestedFlags.skipSignatureCheck()) {\n            String checksum;\n            for (Path file : backupSourceFiles) {\n                checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, file);\n                if (!checksum.equals(mChecksum.get(file.getName()))) {\n                    throw new BackupException(\"Source file verification failed.\" +\n                            \"\\nFile: \" + file +\n                            \"\\nFound: \" + checksum +\n                            \"\\nRequired: \" + mChecksum.get(file.getName()));\n                }\n            }\n        }\n        if (!isVerified) {","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L274-L310","documentation":"restoreApkFiles() compares the signing-certificate checksums of the currently installed app (PackageUtils.getSigningCertChecksums) with the certificate checksums recorded in the backup (BackupItems.Checksum.getCertChecksums). If a backup certificate checksum is not present among the installed certificates and signature check is not skipped, this BackupException is thrown — the backed-up APK was signed by a different key than the installed app.","triggerScenarios":"During restore, for some checksum in certChecksums, certChecksumList.contains(checksum) is false while mRequestedFlags.skipSignatureCheck() is false; message embeds installed vs backup cert checksum lists.","commonSituations":"The app was re-signed (e.g. repacked APK, Play Store vs sideloaded signature, debug vs release key); restoring a backup of a modified/forked APK over a store-installed app; the developer rotated signing keys.","solutions":["Uninstall the currently installed app, then restore the backup so the backed-up APK (with its original signature) is installed.","If the installed version is the one you want, install its APK instead of the backed-up one so signatures match.","Enable 'skip signature check' in the restore options only if you accept installing over a differently-signed app (data may be rejected by Android for signature mismatch on install).","Verify cert checksums: a mismatched checksum file from another backup can also trigger this; confirm the checksums file belongs to this backup."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Compare signatures before restoring:\nString[] installed = PackageUtils.getSigningCertChecksums(info.checksumAlgo, packageInfo, false);\nString[] backup = BackupItems.Checksum.getCertChecksums(checksums);\nboolean compatible = Arrays.stream(backup).allMatch(c -> Arrays.asList(installed).contains(c));\n// if !compatible: uninstall first, or skip signature check consciously","typeGuard":null,"tryCatchPattern":"try { restoreOp.runRestore(); } catch (BackupException e) {\n    if (e.getMessage().startsWith(\"Signing info verification failed\")) {\n        // parse Installed/Backup cert lists; offer uninstall-then-restore flow\n    }\n}","preventionTips":["Keep backups of the exact APK build you run (same signature) — avoid mixing store and sideloaded variants.","Uninstall before restoring when signatures differ.","Never skip signature checks when restoring backups from untrusted sources."],"tags":["android","signature","backup","security"],"backgroundTag":"signature-verification-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}