Android signing
Skill almasumdev/awesome-mobile-release-agent-skills/.github/skills/signing/android-signing
Agent skills for mobile release engineering: signing, versioning, store submissions, and rollouts.
npx -y skills add almasumdev/awesome-mobile-release-agent-skills --skill android-signingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Generate keystores, enrol in Play App Signing, and understand v1/v2/v3/v4 APK signature schemes. Use this when setting up Android release signing.
SKILL.md
4.8 KB, as published. Nobody here has run it
Android Signing
Instructions
Signing is the single most brittle step of an Android release. Get it right once, lock it down, and never touch it again.
1. Keystore Generation
Generate a 25-year RSA 2048 upload key (never commit the file):
keytool -genkey -v \
-keystore upload-keystore.jks \
-keyalg RSA -keysize 2048 -validity 9125 \
-alias upload \
-storetype JKS \
-storepass "$KEYSTORE_PASSWORD" \
-keypass "$KEY_PASSWORD" \
-dname "CN=My Company, OU=Mobile, O=My Company, L=City, S=State, C=US"
Store the .jks file, KEYSTORE_PASSWORD, KEY_ALIAS, KEY_PASSWORD in your CI secret store and 1Password. Losing the key means losing the ability to update the app unless you're on Play App Signing.
2. Gradle Wiring
android/key.properties (git-ignored):
storeFile=../upload-keystore.jks
storePassword=...
keyAlias=upload
keyPassword=...
android/app/build.gradle.kts:
val keystoreProperties = Properties().apply {
val f = rootProject.file("key.properties")
if (f.exists()) load(FileInputStream(f))
}
android {
signingConfigs {
create("release") {
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
}
}
buildTypes {
release { signingConfig = signingConfigs.getByName("release") }
}
}
3. Play App Signing (mandatory for new apps)
Google holds the app signing key; you hold the upload key. Benefits:
- Lost upload key can be reset by Play support (app signing key cannot be).
- Google re-signs each install, enabling automatic APK optimisation.
- Required for Android App Bundles, which are the only accepted format for new apps since August 2021.
Enrol at Play Console → Setup → App integrity → App signing. Upload your upload certificate (.pem), not the private key.
4. Signature Schemes v1 / v2 / v3 / v4
| Scheme | Protects | Added |
|---|---|---|
| v1 (JAR) | Individual files inside the APK | Android 1.0 |
| v2 (APK) | The entire APK (faster install, tamper-proof) | Android 7.0 |
| v3 (APK) | v2 + key rotation | Android 9.0 |
| v4 (APK) | Incremental install (.apk.idsig) | Android 11 |
AGP 8.4+ signs with v1+v2+v3 by default. v4 is emitted automatically for bundletool build-apks --local-testing.
5. Extracting the Upload Certificate
keytool -export -rfc \
-keystore upload-keystore.jks \
-alias upload \
-file upload_certificate.pem
Upload this .pem to Play Console when enrolling.
6. Verify a Signed AAB / APK
apksigner verify --verbose --print-certs app-release.apk
bundletool validate --bundle=app-release.aab
Confirm the SHA-256 matches the fingerprint Play shows under App integrity.
7. CI: Decoding the Keystore
- name: Decode keystore
run: |
echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > android/upload-keystore.jks
cat > android/key.properties <<EOF
storeFile=../upload-keystore.jks
storePassword=${{ secrets.KEYSTORE_PASSWORD }}
keyAlias=${{ secrets.KEY_ALIAS }}
keyPassword=${{ secrets.KEY_PASSWORD }}
EOF
8. Key Rotation (v3)
If you suspect the upload key is compromised:
- Generate a new keystore.
- Play Console → App integrity → Request upload key reset (upload new
.pem). - Wait for Google's approval (typically 1–2 business days).
- Update CI secrets and delete the old
.jkseverywhere.
The app signing key is never rotated for existing apps.
9. Common Gotchas
jarsigneralone is insufficient for modern Android; always useapksigner(invoked by AGP).storeFilepaths are relative toandroid/, not the project root — a leading../is usually required.- Keystore type mismatch (JKS vs PKCS12) after
keytoolupgrades. Convert withkeytool -importkeystore -srcstoretype JKS -deststoretype PKCS12. - Different upload key per variant (e.g. dev/staging/prod) — staging builds are often signed with a debug-like keystore checked into the repo.
10. Checklist
- Upload keystore generated with RSA 2048+, 25-year validity.
- Enrolled in Play App Signing; upload certificate uploaded to Play Console.
-
key.propertiesand*.jksgit-ignored; CI decodes from base64 secret. -
signingConfigwired toreleasebuild type only. -
apksigner verifyrun on CI artifact before upload. - Fingerprints recorded in 1Password alongside the keystore.
- Rotation procedure documented in
docs/signing-rotation.md.