Evaluate repackaging and re-signing detection by two tests: can the running app tell its genuine signing identity from any other, and do your own builds keep passing when keys, profiles or stores change? Otukan checks the signing certificate, package contents and installation source on Android and iOS while your app runs. It recognises copies that were unpacked, modified and signed again, applies your response before sensitive flows open and sends the observed certificate to your backend. Your signing keys stay with your team; Otukan only needs to know which certificates are genuine. Detection makes copies visible and costly; your server keeps the final decision.
How re-signing detection fits with other integrity checks is covered on application integrity.
Who holds signing authority
A re-signed copy is only recognisable if you are clear about who signs the genuine one. Signing authority is split differently on each platform.
Android
Every APK or app bundle is signed before it installs. With Play App Signing, your team keeps the upload key and Google holds the app signing key used for installs from Google Play. Builds distributed outside Google Play carry whichever key your team signs them with. Anyone can sign an APK with a key of their own, which is exactly what makes re-signed copies easy to produce.
iOS
Apps are signed with a distribution certificate from your Apple Developer account, and each build carries a provisioning profile and entitlements that tie it to your team. Re-signing a copy needs a different developer identity and a profile of its own, so the copy’s team and entitlements differ from yours. Builds installed from the App Store carry Apple’s distribution signature over your build, so your team identifier and entitlements are what identify the genuine release.
| Artefact | Who owns it | Android | iOS | What Otukan compares |
|---|---|---|---|---|
| Signing key | Your team, or Google for Play installs | Upload key and app signing key | Distribution certificate private key | Never held by Otukan |
| Certificate | Public, derived from the key | Signing certificate in the package | Signing identity and team | Against the genuine list |
| Profile and entitlements | Your developer account | Not applicable | Provisioning profile and entitlements | Team and entitlements |
| Package contents | Your build | Code and resources in the APK | Code and resources in the bundle | Against the release |
Where each checkpoint sits
The order of steps decides whether the check protects you or locks you out. Otukan fits your existing build and release pipeline in this sequence:
- Build. Your pipeline produces the release as it does today.
- Protect. Otukan’s protection is applied, including the signature and content checks.
- Sign. Your team signs the protected build. For store installs, Google Play (with Play App Signing) or the App Store applies the distribution signature. Either way, the identity users receive stays tied to your account.
- Verify. Before distribution, install the signed build on test devices and confirm the check passes for the genuine signature.
- Distribute. Submit to the store or your channel as usual. On the device, the app verifies itself at launch.
A second verification belongs after the store step: install from the store itself and confirm the check still passes, because the certificate your users receive can differ from the one you uploaded with.
Recovery when signing changes
Most failures in re-signing detection happen to genuine builds during a change, not to attackers. Plan these cases before they happen.
Certificate rotation
Android supports signing key rotation with a lineage that links old and new keys. Add the new certificate to Otukan’s genuine list in the release before you rotate, so users on either signature keep passing, then retire the old entry once it has left your installed base.
Expiry
On iOS, an in-house or ad hoc build stops launching when its provisioning profile expires or its certificate is revoked. App Store installs are not affected by the distribution certificate’s expiry. Track expiry dates for each channel and renew with the genuine list updated in advance.
Rollback
If you roll back to an older release, it must carry a genuine list that still matches the certificate in use. Keep the list versioned alongside each release.
Failed installation
Android refuses to install an update signed with a different key over an existing install, unless the rotation lineage links them. If a copy with the same package name is already installed, the genuine app cannot install over it; the user must remove the copy first. The copy’s own signature check can point that user to the official release.
Platform walkthroughs are covered on detecting repackaging in Android apps and preventing mods that need iOS re-signing. For a progressive web app shipped in a store wrapper, see progressive web app protection. To evaluate anti tampering more broadly, see the anti tampering solution guide.