This error means the system verified a code signature and found a mismatch: the signed hash no longer matches the file’s actual contents. The code was modified after signing, or the signature from the original publisher was replaced with a different one. Both produce the same detection result.
The error has two fundamentally different causes depending on who is seeing it. If you’re a developer seeing it during testing or in your build pipeline, a post-sign modification in your build process is almost certainly responsible. If you’re a user seeing it about a download, the file was genuinely modified after the publisher signed it. This guide covers both, across the platforms where this error appears.
What the System Is Actually Detecting
Code signing works by computing a cryptographic hash of the file’s contents at signing time and embedding the signature. Verification re-computes the hash and checks whether it matches the signed value. A tamper error means these two hashes are different.
Three events produce this mismatch:
- The file was modified after signing: any change to any byte of the signed content, including seemingly harmless ones like a version string update or a configuration file embedded in a package, breaks the signature.
- The original signature was replaced: the file was re-signed with a different certificate. This is the ‘repackaging’ case: someone stripped the original signature and applied their own. The file’s content may be identical or may have been modified.
- The signature data itself is corrupt: rare, but a partial download, storage error, or intentional attack on the signature metadata can corrupt the embedded signature without changing the file content, causing verification to fail.
Step 1: Identify Your Platform and Context
| Platform | What produces this error | Where to read |
| Windows | signtool verify fails; file modified after signing; antivirus patching; post-sign build step | Section A |
| Android | Google Play Protect warning; APK re-signed with different key; Play App Signing mismatch | Section B |
| macOS | codesign verification fails; nested components modified after bundle signing | Section C |
| Java | JAR manifest digest mismatch; class files modified after jarsigner ran | Section D |
Section A: Windows Authenticode
On Windows, this error manifests as signtool verify reporting ‘The digital signature of the object did not verify’ or similar, or as Windows refusing to run a file because the Authenticode signature is broken.
Verify the signature and identify the failure
| # Check whether the signature is broken and where:
signtool verify /pa /v YourApp.exe
# Expected output for a valid signature: # Successfully verified: YourApp.exe
# Expected output when tampered: # SignTool Error: The digital signature of the object did not verify. # Number of errors: 1
# Cross-check: compute the file hash and compare to what you signed: > Get-FileHash YourApp.exe -Algorithm SHA256 # Compare to the hash you computed at build time before signing. # If they differ, the file changed after signing. |
Cause A1: A build step runs after the signing step
This is the most common developer-side cause. The pipeline signs the executable, then a subsequent step modifies it: a version stamper updates a resource in the PE file, a packer compresses the binary, a post-build script appends data, or a bundler re-packages the signed DLL into a container. Any of these breaks the signature.
The fix is architectural: signing must be the absolute last step applied to the distributed binary. Every build transformation, resource embedding, version stamping, and packaging operation must complete before the signing step runs.
- Audit your build pipeline and identify every step that touches output files after the signing step
- Move the signing step to the end of the pipeline, after all other transformations
- If you must sign before packaging (for example, an MSI that contains pre-signed DLLs), sign each inner component, then package, then sign the outer package as a separate signing operation
Cause A2: Antivirus software modifying signed files
Some antivirus products inject code or modify PE files to add monitoring hooks. This is intentional from the AV’s perspective but breaks Authenticode signatures. If signed files verify correctly immediately after signing but fail verification on endpoints with specific AV products, the AV is the culprit.
This is a compatibility problem between the AV vendor and your software. Report it to the AV vendor. In the short term, AV exclusions for the affected files may be necessary. This problem is more common with older or more aggressive AV products.
Cause A3: File was genuinely tampered with or repackaged
If the file verifies correctly in your possession but fails on a download from a third-party site, the third-party site distributed a modified version. This is a distribution integrity problem. The correct response is to report the third-party distribution, publish the SHA-256 hash of the legitimate binary on your official site, and encourage users to download only from official sources.
A Windows executable that fails Authenticode signature verification should never be run. The verification failure means either the file was modified (potentially with malicious intent) or the signature data is corrupt. There is no safe way to run a tampered binary.
Section B: Android APK Signature Verification
Android requires APKs to be signed, and it verifies the signature at install time and through Google Play Protect at runtime. The tamper error appears when the APK’s signature doesn’t match expectations, which happens in several distinct scenarios.
Understanding Android signing schemes
Android supports four signature schemes (v1 through v4), applied progressively from older to newer Android versions. The signature scheme covering the full APK package (not just individual files within it) is v2 and later. v2 and v3 sign the entire APK binary, meaning any modification to the APK after signing, including adding files, changing resources, or reordering entries, breaks the signature. v1 (JAR signing) only signs individual file entries and is more tolerant of re-packaging, which is why attackers who want to re-package signed APKs without detection prefer targets that only use v1 signing.
Cause B1: APK was re-signed with a different key
The most common cause from a user-facing perspective. Someone downloaded the official APK, modified it (injected adware, changed analytics IDs, removed license checks), stripped the original signature, and re-signed it with their own certificate. Google Play Protect detects that the signature doesn’t match the publisher key on record.
For developers: if users report this about your app downloaded from unofficial sources, the app has been cracked and redistributed. There is no fix on the developer side beyond discouraging sideloading and reporting the infringing distribution.
Cause B2: Play App Signing key vs upload key confusion
Google Play App Signing stores a separate distribution key from the upload key. When a developer enrolls in Play App Signing, Google re-signs the APK with the distribution key before delivering it to devices. The device sees Google’s distribution key, not the developer’s upload key. If a developer verifies their APK locally with apksigner using the upload key, it verifies correctly. If a user verifies the APK downloaded from a device using the upload key, it appears to have a different signature, which can be misinterpreted as tampering.
| # Verify an APK signature and see which certificates are present:
apksigner verify –verbose –print-certs app-release.apk # Output shows the certificate fingerprints for each signature scheme. # Compare the fingerprint to your upload key (local verification) vs # the distribution key (on-device or Play-distributed APK). |
Cause B3: Post-build APK modification
Same pattern as Windows: a build step after signing modifies the APK. Common examples include post-processing tools that add files to the APK ZIP container, obfuscation tools applied after signing, or CI scripts that modify the APK manifest. The fix is identical: sign last, after all modifications are complete.
| # Verify APK signature integrity after signing:
apksigner verify –verbose app-release.apk # ‘Verified’ indicates all present signature schemes pass. # If this passes in your build environment but fails on device, # check whether any tool modifies the APK after this verification step. |
Section C: macOS Code Signature Verification
macOS uses codesign for binary and bundle signing. The ‘code modified after the fact’ error is the macOS equivalent of the Windows tamper detection, and it appears during app launch when Gatekeeper or the runtime verification system detects a mismatch.
Verify the macOS signature and identify the problem
| # Verify a macOS app bundle signature:
codesign -v –verbose=4 YourApp.app
# Expected output for a valid signature: # YourApp.app: valid on disk # YourApp.app: satisfies its Designated Requirement
# If tampered, output includes: # YourApp.app: code or signature modified # YourApp.app: failed to satisfy its Designated Requirement
# Check which specific component failed: codesign -v –verbose=4 YourApp.app 2>&1 | grep -i ‘error\|modified\|invalid’ |
Cause C1: Nested components signed in the wrong order
A macOS app bundle contains multiple components: the main executable, frameworks, plugins, helper tools, and resources. Each executable component must be individually signed before the outer bundle is signed. If the outer bundle is signed before an inner component, or if an inner component is modified after the outer bundle is signed, verification fails.
The correct order: sign every nested framework, plugin, and helper tool first, working from the innermost components outward, then sign the outer .app bundle last. Re-signing the outer bundle after any inner component changes is required.
Cause C2: Post-sign modification by packaging tools
Some packaging tools (DMG creators, installer builders) modify the .app bundle after it has been signed: they might add a Sparkle update framework, change Info.plist values, or modify entitlements. Each of these breaks the signature. The fix: apply all modifications to the bundle before signing. If a packaging tool requires modifying the bundle, work with the tool’s documentation to understand its expected signing workflow.
Electron apps are particularly prone to this: electron-builder can run post-processing hooks that modify the asar archive or add files after signing. Ensure the afterPack hook (if used) runs before the signing hook, and that signing is the final operation electron-builder performs on each target platform.
Section D: Java Signed JARs
Java’s JAR signing (jarsigner) adds a signature manifest that contains cryptographic digests of every file in the JAR. If any file inside the JAR is modified after jarsigner runs, the manifest digest no longer matches the actual file, and the JVM or Java Web Start reports a tamper error.
Verify a JAR signature
| # Verify a signed JAR:
jarsigner -verify -verbose -certs app.jar
# Expected output for a valid signature: # jar verified.
# If tampered: # jarsigner: java.lang.SecurityException: invalid SHA-256 signature file digest for [filename] # jar is unsigned. (signatures missing or not parsable)
# Check which specific file caused the failure: jarsigner -verify -verbose -certs app.jar 2>&1 | grep -i ‘invalid\|tampered’ |
Cause D1: Class files modified by a bytecode tool after signing
Bytecode manipulation tools (ProGuard, R8, AspectJ weavers, instrumentation agents) must be applied before signing. If they run on already-signed JARs, the resulting class files no longer match the signed digests. Build the obfuscated or instrumented JAR first, then sign the result.
Cause D2: Manifest files modified after signing
MANIFEST.MF and other files in META-INF are part of the signed content. Tools that modify these after signing (some Maven plugins, build tools that update version information) break the signature. Ensure all manifest modifications occur in the pre-signing build phase.
The Root Cause of Most Developer-Side Tamper Errors: Signing Too Early
Across all platforms, the vast majority of developer-side tamper detection errors trace back to the same architectural mistake: the signing step is placed too early in the build pipeline.
The principle is absolute: sign the exact artifact that users will receive. If the artifact is modified after signing, even by your own build pipeline, the signature is broken. This is not a bug in the signing tooling; it is the entire point of code signing.
Build pipelines that have signing work correctly tend to share one structural characteristic: signing is a gate, not a step. The signed artifact is immediately transferred to distribution storage. Nothing touches it between the signing operation and the moment it reaches the user. Any pipeline that has steps between signing and distribution is a pipeline where this error can appear.
| Pipeline mistake | Symptom | Fix |
| Version stamper runs after signing | Windows signtool verify fails | Move version stamping before the signing step |
| electron-builder post-processes after signing | macOS codesign verification fails at launch | Ensure all afterPack hooks complete before the signing hook |
| ProGuard/R8 runs on already-signed JAR | jarsigner verify reports invalid digest | Apply bytecode transformation before jarsigner, not after |
| APK packaging tool reorders ZIP entries post-sign | apksigner verify fails on v2/v3 scheme | Complete all APK modifications before apksigner runs |
| MSI adds a pre-signed DLL and re-signs the MSI incorrectly | Inner component signature breaks | Sign each DLL, build the MSI, then sign the MSI as a separate operation |
Frequently Asked Questions
Can I re-sign a file after it was modified to fix this error?
Yes, and that is almost always the correct fix when the modification was legitimate and intentional. Re-sign the final artifact after all build steps complete, using the same certificate. The new signature covers the current state of the file. The only situation where re-signing is not the fix is when the modification was made by an attacker or unauthorized party, in which case the file should be discarded and rebuilt from trusted sources.
A file I signed yesterday now fails verification today. Nothing changed. Why?
Three possibilities. First, the certificate expired and no timestamp was applied: without a timestamp, the signature becomes invalid after certificate expiry. Always use the /tr flag (Windows), –timestamp (macOS codesign), or -tsa (jarsigner) to embed an RFC 3161 timestamp. Second, the certificate was revoked: check the certificate’s revocation status. Third, the file was actually modified between signing and now: check the file’s current hash against what it was at signing time. Unexplained hash changes on files at rest warrant investigation for unauthorized modification.
My app is unmodified and verified correctly, but users are seeing tamper warnings from Google Play Protect. What is happening?
If the app verifies correctly from your official distribution channel, users seeing Play Protect warnings are likely running a version downloaded from an unofficial source. Play Protect compares the installed APK’s signing certificate against the certificate on record for that package name from the Play Store. An APK with the same package name but a different signing certificate triggers the warning. This indicates the user installed a re-signed (and likely modified) version. Directing users to download exclusively from the official Play Store listing is the response. Consider filing DMCA or abuse reports against unofficial distribution sites hosting modified versions.

Gloria Bradford is a renowned expert in the field of encryption, widely recognized for her pioneering work in safeguarding digital information and communication. With a career spanning over two decades, she has played a pivotal role in shaping the landscape of cybersecurity and data protection.
Throughout her illustrious career, Gloria has occupied key roles in both private industry and government agencies. Her expertise has been instrumental in developing state-of-the-art encryption and code signing technologies that have fortified digital fortresses against the relentless tide of cyber threats.