MyFamilyTracker
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Learn how to securely manage the Android Keystore in your Kotlin app to prevent key loss and ensure smooth app updates from your Bangkok solo dev studio.
On this page
Losing your Android Keystore key means your app can’t sign updates, and you’re forced to publish a new package ID — a nightmare for any solo developer. In this post I’ll show you a battle‑tested workflow to generate, protect, rotate, and recover your keystore without ever jeopardizing your 22‑app portfolio.
The Android Keystore system stores cryptographic keys in a hardware‑backed or software‑only repository that is isolated from the app’s code. It protects private keys from extraction, even if the device is rooted. However, the keystore itself can be lost if you delete the
keystore| Keystore Type | Storage Location | Security Level | Typical Use |
|---|---|---|---|
| Software | code code | Moderate | Development, CI pipelines |
| Hardware‑backed | TPM or Secure Enclave | High | Production, Play Store releases |
| Cloud‑based (e.g., Firebase) | Managed service | Variable | Distributed teams |
[!TIP] Store your keystore password in a secure environment variable rather than hard‑coding it in source files.
A typical key generation command looks like this:
keytool -genkeypair \
-v \
-keystore ~/keystore.jks \
-alias my_key_alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storepass $KEYSTORE_PASSWORD \
-keypass $KEY_PASSWORD \
-dname "CN=Your Name, OU=Your Org, O=Your Company, L=Bangkok, S=Bangkok, C=TH"In Kotlin, you retrieve the key like this:
val keyStore = KeyStore.getInstance("JKS")
keyStore.load(FileInputStream(keystorePath), keystorePassword.toCharArray())
val keyAlias = "my_key_alias"
val privateKey = keyStore.getKey(keyAlias, keyPassword.toCharArray()) as PrivateKey
val cipherCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipherCipher.init(Cipher.ENCRYPT_MODE, privateKey)[!NOTE] The
andcodekeystorePasswordshould never be hard‑coded; use Android’scodekeyPasswordor a secure vault.codeBuildConfig
For a solo developer managing dozens of apps, the biggest risk is a single point of failure: a lone keystore file on your workstation. Here are three strategies that keep your keys safe while staying practical.
Separate Development and Production Keys
Keep a development keystore (
dev.jksprod.jksAutomate Key Rotation
Rotate keys every 12 months or when a compromise is suspected. Automation reduces human error. The script below rotates a key by creating a new alias and updating the Gradle signing config.
#!/usr/bin/env bash
set -e
KEYSTORE=~/keystore.jks
ALIAS_PREFIX="auto_rotated_"
NEW_ALIAS="${ALIAS_PREFIX}$(date +%Y%m%d%H%M%S)"
keytool -genkeypair -v \
-keystore "$KEYSTORE" \
-alias "$NEW_ALIAS" \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storepass "$KEYSTORE_PASSWORD" \
-keypass "$KEY_PASSWORD" \
-dname "CN=Your Name, OU=Your Org, O=Your Company, L=Bangkok, S=Bangkok, C=TH"
# Update gradle.properties with the new alias (example)
sed -i "s/old_alias/$NEW_ALIAS/" ~/gradle.properties
echo "Rotated to $NEW_ALIAS"[!IMPORTANT] Never commit the keystore file or passwords to version control. Use
and CI secret masks.code.gitignore
Leverage Android Gradle Plugin Signing Config
The
signingConfigsbuild.gradleandroid {
signingConfigs {
release {
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "")
storePassword = System.getenv("KEYSTORE_PASSWORD")!!
keyAlias = System.getenv("KEY_ALIAS")!!
keyPassword = System.getenv("KEY_PASSWORD")!!
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}[!WARNING] If you lose the keystore file and have no backup, you must create a new package name and publish a fresh app, breaking continuity for all users.
Automation is the backbone of a resilient keystore strategy. Below is a step‑by‑step workflow that you can embed in your CI pipeline (e.g., GitHub Actions).
A minimal GitHub Actions snippet:
name: Key Rotation
on:
workflow_dispatch:
jobs:
rotate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: Rotate Key
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
bash ./scripts/rotate_keystore.sh
- name: Build Release APK
run: ./gradlew assembleRelease
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: release-apk
path: app/build/outputs/apk/release/app-release.apk[!TIP] Keep the rotation script idempotent; re‑running it should not break existing builds.
| Pitfall | Impact | Solution |
|---|---|---|
| Hard‑coding passwords in code | Keys leak if repo is public | Use environment variables or a vault |
| Storing only one keystore on a laptop | Device loss = app signing loss | Keep backups on encrypted cloud storage |
| Forgetting to update the alias in Gradle after rotation | Build fails with “alias not found” | Automate alias update and verify with code |
| Using the same key for debug and release | Debug key can be compromised, affecting release signing | Separate debug ( code code |
[!WARNING] Never ship an app signed with a debug keystore to the Play Store; it will be rejected and may cause user data loss.
Sudarshan Chaudhari
AI Systems Builder / Product Engineer
Bangkok, Thailand
Solo Android developer with 13+ years in QA, building Android apps, AI automation systems, and developer tools at SudarshanTechLabs.
Related Posts
Related Apps
Real-time family location sharing — Firebase Realtime DB for sub-second propagation, WorkManager + ForegroundService for OS-compliant background collection, geofencing via Google Maps API.
Building something? Available for Android dev and QA consulting.
Work with meComments — powered by Giscus