Vibeloy
Sign Up
All posts

Blog

How to Create an Android Keystore (Step-by-Step Guide)

Published: Updated: 7 min read

What is an Android keystore, and why do you need one?

A keystore is an encrypted file that holds the private/public key pair used to sign an app. Google Play requires every AAB you upload to carry a valid signature; an unsigned or incorrectly signed package is rejected by Play Console at upload time.

Flutter and Android Studio auto-generate a "debug keystore" for local development; it ships with a fixed password, is meant only for testing on your own device, and no store accepts it. The package you upload to a store must be signed with a "release" or "upload" keystore you generate yourself.

Every subsequent update to the same app must be signed with the same key (or a signing chain Google recognizes); otherwise Play Console rejects the update as "signed with a different certificate," forcing users to uninstall and reinstall. That makes your keystore file a permanent part of your app's identity.

Generating the keystore with keytool

keytool is a command-line tool bundled with the Java Development Kit (JDK); since your Flutter or Android Studio install already ships a JDK, you usually don't need a separate install. The standard command recommended in Flutter's official documentation is: keytool -genkey -v -keystore upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload. The -storetype JKS flag here matters: since Java 9, keytool's default store type is PKCS12, so without this flag the resulting file would have a .jks extension but actually contain PKCS12 data.

-keyalg RSA -keysize 2048 sets the key algorithm and length, -validity 10000 keeps the key valid for roughly 27 years, and -alias upload is the short name you give the key, which you'll reuse in key.properties. When you run the command it prompts, in order, for a store password, a key password, and your name/organization details.

On macOS and Linux, keytool runs directly from the terminal if the JDK is on your PATH. On Windows, run flutter doctor -v first to see exactly which JDK is in use, and look for the "Java binary at:" line in its output; keytool lives in that directory's bin folder (assuming "%JAVA_HOME%\bin\keytool" can point you at the wrong JDK if the variable isn't set or you have more than one JDK installed). Adjust the file path in the -keystore parameter to your own user directory, and note the directory you ran the command from — you'll need that path again in the next step.

Wiring it into key.properties and Gradle

Create a file named key.properties inside android/ and add lines for storePassword, keyPassword, keyAlias, and storeFile (the full path to your keystore file). This file is plain text and carries your passwords in the open, so it must never go into version control — add a key.properties line to .gitignore as your very first step.

In android/app/build.gradle.kts (the current Kotlin DSL), you read this file and define a signingConfigs.release block, with keyAlias, keyPassword, storeFile, and storePassword pulled from key.properties. You then assign signingConfig = signingConfigs.getByName("release") on the release build type so every release package produced is signed with this key.

If R8/ProGuard shrinking (isMinifyEnabled=true) is on, test the signed release package on a real device before uploading it to the store; some packages relying on reflection get affected by shrinking and only crash in the release build. This isn't related to signing itself, but it's a common thing to forget at the same step.

Play App Signing: upload key vs. app signing key

Since 2021, Google has required Play App Signing for new apps and the opt-out option no longer exists. This model has two distinct keys: the "upload key" you generate with keytool and use to sign every AAB, and the "app signing key" Google stores in its own secure infrastructure and uses to give the final signature to the package distributed to users. You never see or hold the app signing key yourself.

If you lose your upload key (the file or its passwords) but you are enrolled in Play App Signing, there is a way out: in Play Console, go to Protected with Play > Play Store protection > Manage Play app signing, then open a "Request upload key reset" request from the "Upload Key Certificate" section. The process works like this: generate a new upload keystore with keytool, export its certificate to PEM format with keytool -export -rfc -keystore upload-keystore.jks -alias upload -file upload_certificate.pem, then upload that PEM file to Play Console along with a note explaining the reason for the reset. Once Google reviews and approves the request, the new upload key becomes active; because the actual signing key never left Google's hands, your app's store identity, reviews, and install count are unaffected.

If you never enrolled in Play App Signing — typically the case for older apps published before it became mandatory — and you lose your one and only signing key, there is no way back: you can never upload another update to that app. The only option is to open a brand-new listing under a new applicationId, which means losing existing reviews, install count, and search ranking.

Safe storage practices

Keeping the keystore file on a single local disk is risky: a disk failure, a fresh format, or a computer swap can permanently lose the file. Keep at least one encrypted backup (an external drive, encrypted cloud storage) and never add the file to your project repository — like key.properties, the keystore file belongs in .gitignore too.

Store the store password and key password in a password manager, and note the alias name too; without all three, the file itself is useless. Never share the passwords as plain text over email or chat apps; if you work as a team, limit access to only the people who need it.

Vibeloy Keystore Vault stores your keystore file and passwords end-to-end encrypted; instead of keeping the file as a single local copy, you can hold it securely in an account-linked vault reachable from any device. This is a premium Vibeloy feature.

Frequently asked questions

I lost my keystore file — what should I do?
If you are enrolled in Play App Signing, you can open an upload key reset request from the "Upload Key Certificate" section under Play Console's Protected with Play > Play Store protection > Manage Play app signing: generate a new upload keystore, export its certificate to PEM with keytool -export -rfc, and upload it along with a reason; the new key activates once Google approves it. If you were not enrolled, the loss is permanent — you can never update that app again.
What is key.properties, and why is it needed?
It is a plain-text configuration file kept in android/ that holds your keystore file's path and passwords. Gradle reads this information from it when signing the release build; the file must never be committed to git.
I forgot my keystore password but I still have the file — can I recover it?
No — the password is the cryptographic piece that makes the file usable, and it cannot be recovered. For your app, this has the same practical outcome as losing the file entirely: an upload key reset if you're enrolled in Play App Signing, or starting over with a new applicationId if you're not.
What is the difference between a debug keystore and a release (upload) keystore?
The debug keystore is auto-generated by Flutter/Android Studio, uses a fixed, publicly known password, is meant only for local testing, and no store accepts it. The release (upload) keystore is the one you generate yourself with keytool, whose password only you know, and which signs the package you upload to the store.
Should I add the keystore file to my project repository (git)?
No. The keystore file and key.properties should be added to .gitignore and never committed; leaking either into a public repository would let anyone who obtains the key attempt to sign packages under your app's identity.