Android App Signing Setup
Use this skill when you need to set up or manage app signing for Google Play.
Understanding Android App Signing
Android apps must be signed with a certificate before upload. Two signing approaches:
- •App Signing by Google Play (Recommended) - Google manages your signing key
- •Manual Signing (Legacy) - You manage your signing key
Create a New Keystore
Generate keystore
keytool -genkey -v \ -keystore release.keystore \ -alias my-app-key \ -keyalg RSA \ -keysize 2048 \ -validity 10000
You'll be prompted for:
- •Keystore password (store securely!)
- •Key password (can be same as keystore password)
- •Your name/organization details
Keystore file location
- •Development: Keep locally, never commit to git
- •Production: Store in secure location (password manager, secrets vault)
- •CI/CD: Use encrypted secrets
Configure Gradle Signing
gradle.properties (gitignored)
KEYSTORE_FILE=/path/to/release.keystore KEYSTORE_PASSWORD=your_keystore_password KEY_ALIAS=my-app-key KEY_PASSWORD=your_key_password
app/build.gradle
android {
signingConfigs {
release {
storeFile file(project.property('KEYSTORE_FILE'))
storePassword project.property('KEYSTORE_PASSWORD')
keyAlias project.property('KEY_ALIAS')
keyPassword project.property('KEY_PASSWORD')
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Using environment variables (CI/CD)
android {
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE_FILE") ?: "release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
}
Play App Signing Setup
Enable Play App Signing (New App)
- •
Build and sign AAB with upload key:
bash./gradlew bundleRelease
- •
Upload AAB to Play Console:
bashgplay release \ --package com.example.app \ --track internal \ --bundle app-release.aab
- •
Google Play generates app signing key automatically
- •
Download upload certificate:
- •Go to Play Console → App → Setup → App signing
- •Download "Upload certificate" (will be used for future uploads)
Migrate Existing App to Play App Signing
If your app uses manual signing:
- •
Export upload key:
bashkeytool -export -rfc \ -keystore release.keystore \ -alias my-app-key \ -file upload_cert.pem
- •
Encrypt private key (required by Google):
bash# Generate password for encryption openssl rand -base64 32 > encryption_password.txt # Export and encrypt private key keytool -importkeystore \ -srckeystore release.keystore \ -destkeystore encrypted.p12 \ -deststoretype PKCS12 \ -srcalias my-app-key \ -deststorepass $(cat encryption_password.txt)
- •
Upload to Play Console:
- •Go to Play Console → App → Setup → App signing
- •Choose "Export and upload a key"
- •Upload encrypted.p12 and encryption_password.txt
- •
Download new upload key:
- •After migration, download new upload certificate
- •Use this for all future uploads
Verify Keystore
List keys in keystore
keytool -list -v -keystore release.keystore
Check certificate validity
keytool -list -v \ -keystore release.keystore \ -alias my-app-key \ | grep Valid
Extract certificate fingerprint
# SHA-256 (for Firebase, etc.) keytool -list -v \ -keystore release.keystore \ -alias my-app-key \ | grep SHA256
Verify APK/AAB Signature
Check AAB signature
jarsigner -verify -verbose -certs app-release.aab
Check APK signature
jarsigner -verify -verbose -certs app-release.apk
CI/CD Signing
GitHub Actions Example
- name: Decode keystore
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
- name: Build signed AAB
env:
KEYSTORE_FILE: release.keystore
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: |
./gradlew bundleRelease
- name: Clean up keystore
if: always()
run: rm -f release.keystore
Store keystore as base64
# Encode keystore to base64 base64 -i release.keystore -o keystore_base64.txt # Add to GitHub Secrets as KEYSTORE_BASE64
Upload Certificate Management
Register upload certificate for existing app
If you lose your upload key:
- •
Generate new keystore (as shown above)
- •
Export certificate:
bashkeytool -export -rfc \ -keystore new-upload.keystore \ -alias my-app-key \ -file new_upload_cert.pem
- •
Contact Google Play support to reset upload key:
- •Go to Play Console → Help
- •Request upload certificate reset
- •Provide new_upload_cert.pem
Security Best Practices
DO:
- •✅ Use strong passwords (16+ characters)
- •✅ Store keystore in multiple secure locations
- •✅ Use different keys for different apps
- •✅ Enable Play App Signing
- •✅ Keep upload key separate from production
- •✅ Document key details securely (not passwords!)
- •✅ Set calendar reminder for key expiration (10-25 years)
DON'T:
- •❌ Commit keystores to git
- •❌ Share keystores via email/chat
- •❌ Use weak or obvious passwords
- •❌ Store passwords in code
- •❌ Forget to backup keystores
- •❌ Use same key for debug and release
Keystore Backup Strategy
What to backup:
- •Keystore file (
release.keystore) - •Key alias name
- •Keystore password (in password manager)
- •Key password (in password manager)
Where to backup:
- •Password manager (1Password, LastPass, etc.)
- •Encrypted cloud storage
- •Company secrets vault
- •Physical secure storage (for enterprise)
Test restore process:
# Verify you can use the backup keytool -list -v -keystore backup/release.keystore
Troubleshooting
"jarsigner: unable to sign jar"
- •Check keystore password is correct
- •Verify keystore file path
- •Ensure keystore alias exists
"Failed to read key from keystore"
- •Key alias might be wrong
- •Key password might be wrong
- •Keystore might be corrupted
"Upload certificate doesn't match"
- •You're using wrong keystore
- •Keystore was regenerated (contact support)
- •Using app signing key instead of upload key
Lost keystore?
- •If using Play App Signing: Contact Google to reset upload key
- •If not using Play App Signing: Cannot recover, must publish new app
Multiple Apps, Multiple Keys
Organize multiple keystores
~/keystores/ ├── app1-release.keystore ├── app2-release.keystore └── app3-release.keystore
Use different gradle.properties per app
# app1/gradle.properties KEYSTORE_FILE=~/keystores/app1-release.keystore KEY_ALIAS=app1-key # app2/gradle.properties KEYSTORE_FILE=~/keystores/app2-release.keystore KEY_ALIAS=app2-key
Key Rotation
Android apps are typically signed with long-lived keys (10-25 years), but if you need to rotate:
- •Only possible with Play App Signing enabled
- •Contact Google Play Support to rotate app signing key
- •Upload new upload certificate when prompted
- •All future builds must use new upload key
Documentation Template
Keep this info in your password manager:
App Name: My Awesome App Package: com.example.app Keystore File: release.keystore (backed up in Dropbox) Keystore Password: [IN PASSWORD MANAGER] Key Alias: my-app-key Key Password: [IN PASSWORD MANAGER] Certificate Validity: Valid until 2035-02-05 SHA-256 Fingerprint: AB:CD:EF:12:... Play App Signing: Enabled Notes: Upload key only, Google manages app signing key