devsnack
Free tool

Play Store Signing Key Generator

Fill in your app details and get the exact keytool command, key.properties file and Gradle signing config for a Flutter or Android release build.

Certificate identity — optional

These go into the certificate. Nobody sees them on the store listing and none of them can be changed later, so a company name you will still recognise in ten years is enough. Leave them blank and keytool asks for each one at the prompt instead.

  1. 01

    Generate the key

    Run this from anywhere. It writes the keystore to ~/keys/ — deliberately outside the project, so it can never be committed by accident. keytool will prompt for your name and organisation interactively, then for a password twice. Fill in the identity fields above to skip the prompts.

    mkdir -p ~/keys
    keytool -genkeypair -v \
      -keystore ~/keys/upload-keystore.jks \
      -storetype PKCS12 \
      -keyalg RSA -keysize 2048 \
      -validity 9855 \
      -alias upload
  2. 02

    Keep it out of git

    .gitignore · android/.gitignore

    The keystore lives outside the repo, but the properties file holding its password does not. Add these before the first commit — a password in git history stays there after you delete the line.

    key.properties
    *.jks
    *.keystore
    *.p12
  3. 03

    Point Gradle at the key

    android/key.properties

    Passwords stay in this file, and this file stays out of git. It sits next to android/app, not at the Flutter project root. Use an absolute path for storeFile — a relative one resolves differently depending on which directory Gradle was invoked from.

    storePassword=<the password you just set>
    keyPassword=<the same password>
    keyAlias=upload
    storeFile=/Users/you/keys/upload-keystore.jks
  4. 04

    Wire the signing config

    android/app/build.gradle.kts

    The two imports have to sit at the very top of the file, above the plugins block — Kotlin DSL rejects an import anywhere else. The exists() guard is what lets the project still build on a machine that has no key, which is what you want for CI that only runs tests.

    import java.util.Properties
    
    val keystoreProperties = Properties()
    val keystorePropertiesFile = rootProject.file("key.properties")
    if (keystorePropertiesFile.exists()) {
        keystorePropertiesFile.inputStream().use { keystoreProperties.load(it) }
    }
    
    android {
        signingConfigs {
            create("release") {
                keyAlias = keystoreProperties["keyAlias"] as String
                keyPassword = keystoreProperties["keyPassword"] as String
                storeFile = file(keystoreProperties["storeFile"] as String)
                storePassword = keystoreProperties["storePassword"] as String
            }
        }
    
        buildTypes {
            release {
                signingConfig = signingConfigs.getByName("release")
            }
        }
    }
  5. 05

    Build the bundle you upload

    Play requires an .aab, not an .apk. The file lands at build/app/outputs/bundle/release/app-release.aab. If it builds but Play rejects it as debug-signed, the signingConfig line inside buildTypes is missing — Gradle falls back to the debug key silently rather than failing.

    flutter build appbundle --release
  6. 06

    Read the fingerprints back

    SHA-1 and SHA-256 from this keystore are what Firebase, Google Sign-In and Android App Links need. Register the upload key's fingerprint now, then add the one Play generates after your first release — with Play App Signing there are two, and only registering one is why sign-in works in debug and fails in production.

    keytool -list -v -keystore ~/keys/upload-keystore.jks -alias upload

Back the key up before you publish, not after

Losing the upload key is recoverable — Google can reset it if you have Play App Signing enabled, which is the default for new apps. Losing the app signing key on an older app that opted out is not: no update can ever be published to those installs again. Copy the keystore and its password to somewhere that survives a dead laptop, and do it now rather than at the first update. Renaming the project the key belongs to is a separate checklist, and the walkthrough for a bought template covers both together.