{"record":{"id":"7348c849e202f5d0","repo":"beemdevelopment/Aegis","slug":"apk-signatures-did-not-match","errorCode":null,"errorMessage":"APK signatures did not match!","messagePattern":"APK signatures did not match!","errorType":"exception","errorClass":"CertificateException","httpStatus":null,"severity":"warning","filePath":"app/src/main/java/info/guardianproject/trustedintents/TrustedIntents.java","lineNumber":238,"sourceCode":"    public void checkTrustedSigner(PackageInfo packageInfo)\n            throws NameNotFoundException, CertificateException {\n        checkTrustedSigner(packageInfo.signatures);\n    }\n\n    public void checkTrustedSigner(Signature[] signatures)\n            throws NameNotFoundException, CertificateException {\n        if (signatures == null || signatures.length == 0)\n            throw new CertificateException(\"signatures cannot be null or empty!\");\n        for (int i = 0; i < signatures.length; i++)\n            if (signatures[i] == null || signatures[i].toByteArray().length == 0)\n                throw new CertificateException(\"Certificates cannot be null or empty!\");\n\n        // check whether the APK signer is trusted for all apps\n        for (ApkSignaturePin pin : pinList)\n            if (areSignaturesEqual(signatures, pin.getSignatures()))\n                return; // found a matching trusted APK signer\n\n        throw new CertificateException(\"APK signatures did not match!\");\n    }\n\n    public boolean areSignaturesEqual(Signature[] sigs0, Signature[] sigs1) {\n        // TODO where is Android's implementation of this that I can just call?\n        if (sigs0 == null || sigs1 == null)\n            return false;\n        if (sigs0.length == 0 || sigs1.length == 0)\n            return false;\n        if (sigs0.length != sigs1.length)\n            return false;\n        for (int i = 0; i < sigs0.length; i++)\n            if (!sigs0[i].equals(sigs1[i]))\n                return false;\n        return true;\n    }\n\n    public void startActivity(Context context, Intent intent) throws CertificateException {\n        if (!isIntentSane(intent))","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/beemdevelopment/Aegis/blob/d6f4e5925a97e4e91593f1542085eae03432a759/app/src/main/java/info/guardianproject/trustedintents/TrustedIntents.java#L220-L256","documentation":"After the null/empty guards, checkTrustedSigner compares the APK's signatures against every registered ApkSignaturePin in pinList using areSignaturesEqual. If none matches, it throws CertificateException('APK signatures did not match!'), meaning the intent sender's signing key is not one of the trusted/pinned keys — the app's identity cannot be verified as the intended, trusted sender.","triggerScenarios":"An app sends a trusted intent but was signed with a different key: a repackaged/cloned APK, a debug-signed build, a different app impersonating the package name, or the library's pin list not updated after the vendor rotated their signing certificate.","commonSituations":"Side-loaded or modded APK of the trusted app; switching between Play Store and third-party builds signed differently; upstream app migrates signing keys (new pin format/rotated key) while your pinned ApkSignaturePin is stale; malicious app spoofing package names.","solutions":["Verify the sender app's origin (install channel) — install the genuine, properly signed build from the official source","Update the trustedintents pin data (ApkSignaturePin certificate hashes) to match the vendor's current signing certificate if the vendor rotated keys","Check you pinned the right certificate (e.g. 'X509:' prefixed hex of the full cert); regenerate the pin from the trusted app's actual signature","Log and reject the intent — treat the exception as a security signal, do not add the unknown signature to the pin list"],"exampleFix":"// before\ntry {\n    trustedIntents.checkTrustedSigner(signatures);\n} catch (CertificateException e) {\n    Log.e(TAG, \"untrusted sender\", e); // APK signatures did not match!\n}\n// after\ntry {\n    trustedIntents.checkTrustedSigner(signatures);\n} catch (CertificateException e) {\n    Log.w(TAG, \"Rejected intent from untrusted signer for pkg \" + packageName, e);\n    Toast.show(context, \"Sender app is not the genuine version; install the official build\");\n    return; // do not process the intent\n}","handlingStrategy":"try-catch","validationCode":"byte[] expected = pin.getSignatures()[0].toByteArray();\nbyte[] actual = signatures[0].toByteArray();\nboolean pinned = java.util.Arrays.equals(expected, actual);\nif (!pinned) { rejectIntentWithUserGuidance(); }","typeGuard":"boolean isTrustedPackage(TrustedIntents ti, String pkg) {\n    try {\n        ti.checkTrustedSigner(pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES));\n        return true;\n    } catch (Exception e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    trustedIntents.checkTrustedSigner(signatures);\n} catch (CertificateException e) {\n    if (e.getMessage().contains(\"did not match\")) {\n        Log.w(TAG, \"untrusted APK signer; possible repackage\", e);\n        refuseToRespond();\n    }\n}","preventionTips":["Treat mismatch as a security signal; never auto-add unknown keys to pinList","Keep ApkSignaturePin data in sync with the trusted vendor's signing certificate rotation","Verify users install the genuine app from official channels","Log the sender package name on mismatch for incident triage"],"tags":["android","signatures","security","certificate-pinning"],"backgroundTag":"signature-verification-failed","analyzedSha":"d6f4e5925a97e4e91593f1542085eae03432a759","analyzedAt":"2026-09-08T00:46:31.111Z","contentChangedAt":"2026-09-08T00:46:31.111Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}