Under Play App Signing, what is the difference between a Flutter app's upload key and app signing key, and what happens if the team loses the upload keystore?
answer
- you sign uploads, Play signs installs
- bundles require Play App Signing
- lost upload key can be reset
- fingerprints differ between the two keys
- APIs allowlist the app signing fingerprint
basics
~20 sYou sign uploads with an upload key; Google Play signs the APKs users install with an app signing key it holds. A lost upload keystore is replaced by registering a new upload key, since the key devices trust never left Google.
solid answer
~40 sWith Play App Signing there are two keys. The **upload key** is yours: `key.properties` and `signingConfigs` sign the `.aab` with it, and Play only uses it to verify that an upload came from you. The **app signing key** is held by Google, which signs the APKs it generates from your bundle; devices check updates against that key. Publishing app bundles requires enrolling in Play App Signing. If the team loses or leaks the upload keystore, the account owner asks Play to register a new upload key and signing continues, whereas losing a self-managed app signing key would block updates. A common production bug follows from the split: APIs that allowlist a signing-certificate fingerprint must list the **app signing** key's fingerprint from Play, not the upload key's.
go deeper
Know there are two keys: you sign uploads with the upload key, and Google signs what users install with the app signing key.
Explain why bundles require Play App Signing, what each key is used to verify, and why a lost upload key is recoverable.
Diagnose the fingerprint trap in sign-in and restricted API keys, and run a clean upload-key reset after a loss or leak.
Weigh Google holding the app signing key against self-managed keys, and set key-custody rules for who can reset and access them.
## Two keys, two jobs On Android, the certificate an app is signed with is its identity: a device only installs an **update** if it is signed with the same key as the installed version. Google Play's **Play App Signing** splits that responsibility in two: - The **upload key** — generated by you (for a Flutter app, the `upload-keystore.jks` referenced from `android/key.properties`). You sign every `.aab` you upload with it. Play uses it only to **authenticate the upload**. - The **app signing key** — held by Google. When Play builds device-specific APKs from your bundle, it signs them with this key. Devices see only this key. So the key users trust never sits on a developer laptop or CI runner. ## Why a Flutter team cannot avoid it App bundles are the required format for new Play apps, and uploading an app bundle requires enrolling in Play App Signing — Play needs the app signing key to produce the APKs it serves from the bundle. For a first release of a plant-care app, enrolment is therefore part of the process: either let Play generate the app signing key, or upload an existing one if the app was previously published with self-managed signing. ## Losing the upload keystore Because the upload key only authenticates uploads, losing it is **recoverable**: 1. Generate a new keystore with `keytool`. 2. The Play Console account owner requests an **upload key reset**, providing the new certificate. 3. After Play registers it, sign uploads with the new key by updating `key.properties`. The same process handles a **compromised** upload key: reset it so the leaked one can no longer be used to upload. By contrast, an app that manages its own signing key and loses it cannot publish updates that existing installs accept. Practical safeguards: - store the keystore and passwords in a vault or password manager, not only on one machine; - restrict who can read the CI secret holding the keystore; - record which person can request a reset, since that is an account-owner action. ## The fingerprint trap Services that verify **which app** is calling them often allowlist a **certificate fingerprint** (SHA-1 or SHA-256) together with the package name — OAuth clients for Google Sign-In, API keys restricted to an Android app, and similar integrations. Under Play App Signing there are now **three** certificates in play: | Build | Signed with | Fingerprint to allowlist | |---|---|---| | `flutter run` (debug) | local debug key | debug fingerprint | | Locally built release APK | upload key | upload key fingerprint | | Installed from Google Play | app signing key (held by Google) | app signing key fingerprint from Play Console | The classic symptom: sign-in works in debug and in a locally signed release APK, then fails for every user who installs from Play. The fix is to add the **app signing key's** fingerprint, which Play Console shows for the app, alongside the others. ## What changes in the Flutter project Nothing in `build.gradle.kts` refers to Play App Signing directly. The Flutter side stays as configured for release signing: - `signingConfigs.create("release")` reads the **upload** keystore; - `flutter build appbundle` signs the bundle with it; - the rest happens in Play. ## First release checklist For the plant-care app's first upload: - generate the upload keystore and wire `signingConfigs` as for any release; - let Play create the app signing key during enrolment, unless an existing key must be kept; - record the upload key's and the app signing key's fingerprints where the integrations team can find them; - back up the upload keystore and passwords in at least two controlled places. ## Interview angles 1. **"Can Google sign malicious updates?"** — Google holds the key users trust; that is the trade-off Play App Signing makes in exchange for recoverable upload keys and Play-side optimisations. 2. **"Why did our Maps or sign-in integration break after launch?"** — the fingerprint trap above. 3. **"We leaked the keystore in a public repository."** — reset the upload key through Play, remove the file, and rotate CI secrets; the app signing key was never exposed.
- Google Sign-In works in debug and in a locally built release APK but fails for users installing from Play. Why?Play re-signs installed APKs with the app signing key, whose certificate fingerprint differs from the debug and upload keys. The OAuth client or API restriction only lists the fingerprints you knew; add the app signing key's fingerprint, shown in Play Console, and sign-in works for Play installs.
- Does the Flutter project's build.gradle.kts change when you enrol in Play App Signing?No. The release signing config keeps reading the upload keystore from `key.properties`, and `flutter build appbundle` signs with it. Enrolment is a Play Console setting; Play re-signs what it delivers with the app signing key.
Play App Signing works like a notary: you hand documents over with your own ID card (the upload key), and the notary stamps them with an official seal (the app signing key) that recipients trust. Losing your ID card means getting a new one registered with the notary; the seal never left the office.
saying these in an interview costs you the question
- Thinks losing the upload keystore permanently blocks app updates
- Believes Play serves users the APKs signed with the upload key
- Allowlists only the upload key's SHA-1 for sign-in or Maps restrictions
- Assumes app bundles can be published without Play App Signing
- Keeps a single copy of the upload keystore on one laptop