ZapretKVN-android/SIGNING.md
2026-07-22 14:44:50 +03:00

60 lines
3.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Подпись Zapret KVN Android
Release APK всегда должен быть подписан одним постоянным ключом. GitHub Actions получает
ключ и пароли только через secrets среды `release`; ключ, `.properties` и пароли в Git
не добавляются.
## Однократное создание ключа офлайн
На отключённой от сети машине с JDK 17:
```bash
keytool -genkeypair \
-keystore zapret-kvn-release.jks \
-alias zapret-kvn-release \
-keyalg RSA -keysize 4096 -validity 10000
sha256sum zapret-kvn-release.jks > zapret-kvn-release.jks.sha256
gpg --symmetric --cipher-algo AES256 zapret-kvn-release.jks
keytool -exportcert -rfc -keystore zapret-kvn-release.jks -alias zapret-kvn-release \
| openssl x509 -outform DER \
| sha256sum
```
Сделать минимум две офлайн-копии `zapret-kvn-release.jks.gpg` и checksum на разных
носителях. Проверить восстановление на третьем временном носителе командами
`gpg --decrypt` и `sha256sum -c`, затем безопасно удалить расшифрованную проверочную
копию. Потеря ключа означает невозможность обновить уже установленное приложение.
## GitHub environment `release`
Добавить environment с обязательным ручным approval и secrets:
- `ANDROID_SIGNING_KEYSTORE_BASE64` — `base64 -w0 zapret-kvn-release.jks`;
- `ANDROID_SIGNING_STORE_PASSWORD`;
- `ANDROID_SIGNING_KEY_ALIAS` — `zapret-kvn-release`;
- `ANDROID_SIGNING_KEY_PASSWORD`;
- `ANDROID_SIGNING_CERT_SHA256` — 64 hex-символа из команды выше, без имени файла.
Workflow восстанавливает JKS только во временный каталог runner, проверяет подпись
готового APK через pinned Android `apksigner`, сравнивает сертификат с закреплённым
`ANDROID_SIGNING_CERT_SHA256` и удаляет JKS в шаге `always()`.
`scripts/ci-build.sh` автоматически отключает Gradle configuration cache, когда переданы
`ZAPRET_SIGNING_*`, чтобы пароли не попали в повторно используемый Gradle state.
## Финальный approval, версии и публикация
Среда `release` должна иметь обязательного reviewer. Workflow запускается только вручную
для уже существующего tag; оператор ставит `final_gate_approved=true` лишь после закрытия
всех пунктов «Финальный gate» в `IMPLEMENTATION_PLAN.md`, физической матрицы
`GATE8_RESULTS.md` и проверки production-signed arm64 APK на реальном устройстве. Push tag
сам по себе ничего не публикует.
- stable tag: `vMAJOR.MINOR.PATCH`;
- beta tag: `vMAJOR.MINOR.PATCH-beta.N`, где `N` от 1 до 98;
- versionCode вычисляется детерминированно; stable получает slot 99 и поэтому новее beta
той же версии;
- опубликованные assets не заменяются: исправление выпускается только новым tag.
Release workflow публикует подписанный arm64 APK, отдельный `.sha256` и
`release-metadata.json` с package, version, точным commit ядра, signing fingerprint и
размером APK.