Code Signing Demystified: Certificates, Provisioning Profiles and Keystores
React Native code signing explained: iOS certificates and provisioning profiles, Android keystores, upload vs app signing keys, and how EAS manages it all.
Full-Stack, Mobile & AI Engineer
Code signing is the part of mobile development that makes experienced web developers feel like beginners. Certificates, provisioning profiles, keystores, upload keys and SHA fingerprints all have to line up, and when they don't, the error messages rarely say which piece is wrong.
React Native code signing is simpler than it looks, because underneath it's just the standard iOS and Android systems. This guide explains what each piece of iOS and Android code signing does, how they fit together, what happens when one is lost, and how to let EAS manage them so most of your team never has to think about it.
Key takeaways
- iOS signing needs a certificate (proving who you are) and a provisioning profile (saying which app, on which devices, with which capabilities).
- Android signing needs a keystore containing your key. With Play App Signing, you sign uploads with an upload key, and Google signs what users download with the app signing key.
- Losing an Android upload key is recoverable with Play App Signing; losing the only signing key without it can mean publishing a new app.
- EAS can create, store and reuse all of these, which removes most signing problems for Expo and React Native teams.
- Google Sign-In, Firebase and Android App Links need the app signing key's SHA-256 fingerprint from Play Console, not just your local one.
iOS: certificates and provisioning profiles
| Piece | What it is | Notes |
|---|---|---|
| Signing certificate | Proves an app was built by your Apple Developer team | "Apple Development" for testing, "Apple Distribution" for TestFlight and the App Store; the private key must be kept safe |
| App ID (bundle identifier) | Your app's unique ID, like com.company.app | Capabilities such as push or Sign in with Apple are enabled here |
| Provisioning profile | Ties the app ID, a certificate and (for testing) device list together | Development, Ad Hoc and App Store profiles |
| APNs key (.p8) | Lets your server send push notifications | Separate from app signing; one key works across your apps |
A build is signed with a certificate's private key, and the provisioning profile says that this certificate may sign this app ID, with these capabilities, for these devices (or for the App Store). If any of those don't match, for example a capability enabled in code but not in the profile, the build or upload fails.
Certificates expire, and profiles become invalid when their certificate expires. Plan renewals rather than discovering them on release day.
Android: keystores, upload keys and app signing keys
On Android, the signature identifies the app's author for its whole life. Every update must be signed by the same key as the previous version, or Android refuses to install it.
| Key | Who holds it | Used for |
|---|---|---|
| Upload key | You (or EAS) | Signing the app bundle you upload to Google Play |
| App signing key | Google, with Play App Signing | Signing the APKs Google delivers to users' devices |
| Debug key | Your machine | Local development builds only |
With Play App Signing (standard for new apps, which must be uploaded as Android App Bundles), Google keeps the app signing key. If you lose your upload key, you can request a reset in Play Console and register a new one. Without Play App Signing, a lost key means you can't update the app, and the only way forward is a new listing.
To create an upload key yourself, the React Native docs use keytool:
keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore \
-alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000Store the keystore file and its passwords in a password manager or secret store. Never commit them to the repository.
The SHA fingerprint trap
Services that verify your Android app by its signature, such as Google Sign-In, Firebase and Android App Links (for verified deep links), need the SHA-256 or SHA-1 fingerprint of the key that signs the app users install. With Play App Signing, that's Google's app signing key, which you find in Play Console under app integrity, not your upload key. A classic symptom: Google Sign-In works in your local build but fails for users who installed from Google Play. Register both fingerprints where the service allows it.
Letting EAS manage signing
With EAS Build, signing becomes mostly automatic:
- iOS: on the first build, EAS signs in to your Apple account and can create the distribution certificate and provisioning profile, then stores them encrypted and reuses them.
- Android: EAS can generate an upload keystore and store it, or use one you provide.
- Inspect and manage everything with
eas credentials, including downloading backups.
You can also supply your own credentials in a credentials.json file if your organisation requires it. Whatever you choose, keep the Apple and Google developer accounts in your company's name, and keep an offline backup of the Android upload key.
From the field: Signing is part of the release path I own on the apps I ship, from EAS builds and submissions to store review. The rule I'd apply to any project: credentials live in a managed store, a backup lives with the client, and nothing depends on one person's laptop.
Troubleshooting common signing errors
| Error or symptom | Likely cause | Fix |
|---|---|---|
| "No profiles for 'com.company.app' were found" | Missing or expired provisioning profile | Regenerate with EAS (eas credentials) or in the Apple Developer portal |
| Push notifications don't arrive on iOS | Push capability not in the profile, or wrong APNs key or environment | Enable push for the app ID, regenerate the profile, check the APNs key |
| "Upload certificate does not match" on Google Play | Bundle signed with a different upload key | Sign with the registered upload key, or request an upload key reset |
| Google Sign-In fails only for store users | App signing key fingerprint not registered | Add the Play App Signing SHA fingerprints to your Firebase or Google Cloud project |
| Android app won't update over the old one | Different signing key than the installed version | Use the original key; a different key can't update the app |
FAQ
What is a provisioning profile?
A provisioning profile is a file from Apple that links your app ID, a signing certificate and, for testing builds, a list of devices, along with the capabilities the app may use. iOS checks it to decide whether a signed app may be installed and run.
What happens if I lose my Android keystore?
If your app uses Play App Signing, Google holds the app signing key, and you can request an upload key reset in Play Console, then sign future uploads with a new key. Without Play App Signing, you can't publish updates to the existing app, so keep secure backups of your keys.
Do I need a Mac to sign iOS apps?
Not with EAS Build, which creates credentials through your Apple account and signs builds in the cloud. Signing locally with Xcode does require a Mac.
Where do I find my app's SHA-256 fingerprint for Firebase?
For apps distributed through Google Play with Play App Signing, use the app signing key certificate fingerprint shown in Play Console's app integrity section. Add your upload key's fingerprint too if you test builds signed with it.
Next steps
If signing errors are blocking a release, or your keys live on one developer's laptop, I can move them into a managed, backed-up setup and get the build shipping. Get in touch, or see my services.
Sources
- App credentials, Expo
- Publishing to Google Play Store (generating an upload key), React Native docs
- Use Play App Signing, Google Play Console Help
- Certificates overview, Apple Developer
- Sign your app, Android Developers
Related
EAS Build Explained: Profiles, Credentials, and What It Costs
EAS Build explained for 2026: build profiles in eas.json, managed credentials, local builds, versioning, and what Expo's plans and per-build prices cost.
Versioning a React Native App: versionCode, buildNumber, runtimeVersion
React Native app versioning explained: version vs build number on iOS and Android, runtimeVersion for OTA updates, auto-increment and update checks.
Fastlane for React Native in 2026: When You Still Need It
Fastlane for React Native in 2026: what it automates, when EAS replaces it, when you still need it, and a working Fastfile for TestFlight and Google Play.
