diff --git a/android/README.md b/android/README.md index a101be7..c681b17 100644 --- a/android/README.md +++ b/android/README.md @@ -60,7 +60,7 @@ npm run assemble:debug # → android/app/build/outputs/apk/debug/app-debug.a ### Release AAB + APK (signed) ```bash -export LOTO_KEYSTORE_PATH=$HOME/.android/loto-release.jks +export LOTO_KEYSTORE_PATH=$HOME/.android/miti99-apps.p12 export LOTO_KEYSTORE_PASSWORD= export LOTO_KEY_ALIAS= export LOTO_KEY_PASSWORD= @@ -137,13 +137,13 @@ Both workflows checkout the loto submodule, install npm deps, build loto, | Secret | Required for | Description | |--------|--------------|-------------| -| `KEYSTORE_BASE64` | signed build | `base64 -w0 loto-release.jks` | +| `KEYSTORE_BASE64` | signed build | `base64 -w0 miti99-apps.p12` | | `KEYSTORE_PASSWORD` | signed build | Keystore password | | `KEY_ALIAS` | signed build | Key alias | | `KEY_PASSWORD` | signed build | Key password | | `PLAY_SERVICE_ACCOUNT_JSON` | Play Store auto-publish (optional) | Full JSON content of Google Cloud service account key | -**Never commit `*.jks`, `*.keystore`, `*.json` (service-account), or `.env`.** +**Never commit `*.jks`, `*.keystore`, `*.p12`, service-account JSON, or `.env`.** ## Google Play Store @@ -157,16 +157,16 @@ Both workflows checkout the loto submodule, install npm deps, build loto, ### Auto-publish setup (after first manual upload) -1. Play Console → **Setup → API access** → link/create a Google Cloud project -2. In Google Cloud Console: create a **Service Account** with role *Service Account User* +1. Create/select a Google Cloud project and enable the **Google Play Android Developer API** +2. In Google Cloud Console, create a **Service Account** without granting broad Cloud project roles 3. **Keys → Add Key → JSON** — download the JSON file -4. Back in Play Console API access: grant the service account **Admin (all permissions)** for the Lo To app, or the minimum: *Release manager* + *View app information* +4. In Play Console → **Users and permissions**, invite the service-account email and grant app-scoped *Release apps to testing tracks* + *View app information* permissions for Lo To 5. Copy the entire JSON contents into a GitHub repo secret named `PLAY_SERVICE_ACCOUNT_JSON` 6. Tag a release (`git tag v1.0.1 && git push origin v1.0.1`) — `release.yml` will: - Build signed AAB + APK - Upload to GitHub Release - **If the secret is set**: upload AAB to Play Console **Internal track** -7. Promote internal → closed → open → production via the Play Console UI (or change `track: internal` in `release.yml` to automate further) +7. Promote internal → closed → open → production via the Play Console UI (or change `tracks: internal` in `release.yml` to automate further) **Important:** every release must increment `versionCode` in `android/app/build.gradle` before tagging — Play Console rejects duplicate versionCodes. diff --git a/android/plans/reports/260721-1328-shared-android-signing-key.md b/android/plans/reports/260721-1328-shared-android-signing-key.md new file mode 100644 index 0000000..8808389 --- /dev/null +++ b/android/plans/reports/260721-1328-shared-android-signing-key.md @@ -0,0 +1,41 @@ +# Shared Android Signing Key Research + +--- +date: 2026-07-21 +status: completed +scope: Android signing and GitHub Actions secret storage +--- + +## Summary + +Using one `miti99-apps.p12` PKCS12 keystore and one `games` alias across multiple games is technically valid. The same certificate creates a shared security identity across those apps, so compromise affects every game using it. + +The keystore must not be committed. A small PKCS12 file can be Base64-encoded into the encrypted GitHub Actions secret `KEYSTORE_BASE64`; passwords and alias belong in separate encrypted secrets. The release workflow decodes the PKCS12 file only on the runner and signs both APK and AAB outputs. + +## Findings + +- Android requires release APKs and upload AABs to be signed. +- Android supports multiple apps signed by the same certificate, including signature-level permissions between them. +- Play App Signing separates the locally held upload key from the app-signing key Google uses for distribution. +- GitHub supports Base64-encoded small binary blobs in Actions secrets. +- GitHub Actions secrets have a 48 KB limit; Base64 is encoding, not encryption. +- The keystore and passwords require an independent, durable backup. Losing or compromising a self-managed signing key can prevent safe future updates. + +## Recommendation + +1. Generate `C:\Users\miti99\.android\miti99-apps.p12` as a PKCS12 keystore. +2. Create alias `games` with RSA 4096 and long certificate validity. +3. Use strong generated store and key passwords. +4. Save the PKCS12 file and credentials in an encrypted password manager or offline encrypted backup. +5. Configure `KEYSTORE_BASE64`, `KEYSTORE_PASSWORD`, `KEY_ALIAS`, and `KEY_PASSWORD` as GitHub Actions secrets. +6. Never commit the PKCS12 file, Base64 material, or passwords. + +## References + +- [Android: Sign your app](https://developer.android.com/studio/publish/app-signing) +- [GitHub: Using secrets in GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions) + +## Unresolved Questions + +- Where the recoverable offline copy of the keystore and credentials will be stored. +- Whether this shared key will remain only an upload key under Play App Signing or also be supplied as the shared app-signing key.