{"record":{"id":"0d96df3c476f15af","repo":"Tencent/tinker","slug":"get-public-key-md5-is-null","errorCode":null,"errorMessage":"get public key md5 is null","messagePattern":"get public key md5 is null","errorType":"exception","errorClass":"TinkerRuntimeException","httpStatus":null,"severity":"critical","filePath":"tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareSecurityCheck.java","lineNumber":170,"sourceCode":"                    }\n                } catch (Exception e) {\n                    ShareTinkerLog.e(TAG, path.getAbsolutePath(), e);\n                }\n            }\n        }\n        return false;\n    }\n\n    @SuppressLint(\"PackageManagerGetSignatures\")\n    private void init(Context context) {\n        ByteArrayInputStream stream = null;\n        try {\n            PackageManager pm = context.getPackageManager();\n            String packageName = context.getPackageName();\n            PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);\n            mPublicKeyMd5 = SharePatchFileUtil.getMD5(packageInfo.signatures[0].toByteArray());\n            if (mPublicKeyMd5 == null) {\n                throw new TinkerRuntimeException(\"get public key md5 is null\");\n            }\n        } catch (Exception e) {\n            throw new TinkerRuntimeException(\"ShareSecurityCheck init public key fail\", e);\n        } finally {\n            SharePatchFileUtil.closeQuietly(stream);\n        }\n    }\n}\n","sourceCodeStart":152,"sourceCodeEnd":179,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareSecurityCheck.java#L152-L179","documentation":"ShareSecurityCheck.init computes the MD5 of the host app's first APK signature block (PackageInfo.signatures[0]) via SharePatchFileUtil.getMD5. getMD5 returns null when the digest cannot be produced; here that null is treated as fatal and TinkerRuntimeException('get public key md5 is null') is thrown. Without the public-key md5, tinker cannot validate that patches are signed by the same key as the app.","triggerScenarios":"getMD5 failing on the signature bytes (stream/digest IO failure, though rare); packageInfo.signatures being empty on exotic ROMs so [0] is not the issue here but getMD5 receives data it cannot digest; device-level crypto provider issues.","commonSituations":"Devices with broken MessageDigest/MemoryFile behavior; apps installed via unusual channels (enterprise stores, some work-profile containers) where PackageManager returns atypical signature data; extremely rare vendor crypto bugs.","solutions":["Reinstall the app normally (from Play/adb) so PackageManager returns standard signature data, then retry loading the patch.","If reproducible on one device/ROM only, treat tinker as unsupported there: gate patch loading behind a device blacklist or capability check.","Compute the expected md5 with the same code (SharePatchFileUtil.getMD5 on signatures[0].toByteArray()) in a debug build to see whether null is deterministic on that device.","Upgrade tinker — newer builds use GET_SIGNING_CERTIFICATES paths on modern Android instead of the legacy GET_SIGNATURES flow."],"exampleFix":"// before\nmPublicKeyMd5 = SharePatchFileUtil.getMD5(packageInfo.signatures[0].toByteArray());\nif (mPublicKeyMd5 == null) throw new TinkerRuntimeException(\"get public key md5 is null\");\n\n// after\nbyte[] sig = packageInfo.signatures[0].toByteArray();\nmPublicKeyMd5 = SharePatchFileUtil.getMD5(sig);\nif (mPublicKeyMd5 == null) {\n    MessageDigest md = null;\n    try { md = MessageDigest.getInstance(\"MD5\"); } catch (NoSuchAlgorithmException ignored) { }\n    mPublicKeyMd5 = (md == null) ? null : toHex(md.digest(sig));\n}","handlingStrategy":"fallback","validationCode":"Signature[] sigs = context.getPackageManager()\n        .getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES).signatures;\nif (sigs == null || sigs.length == 0 || SharePatchFileUtil.getMD5(sigs[0].toByteArray()) == null) {\n    // signature identity unavailable: disable patch loading on this device\n}","typeGuard":null,"tryCatchPattern":"catch TinkerRuntimeException 'get public key md5 is null' -> disable tinker for the session and report the device model","preventionTips":["Probe signature-md5 availability at app startup before enabling patch loading.","Blacklist devices/ROMs where the signature digest is unavailable.","Keep tinker current for modern GET_SIGNING_CERTIFICATES handling."],"tags":["signature","security-check","package-manager"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}