Настройка подписи Android-приложения (Keystore, Signing Config)
Потеря keystore-файла — необратима. Если приватный ключ утерян, обновление существующего приложения в Google Play невозможно. Нужно публиковать новое приложение с новым package name, теряя все отзывы, историю загрузок и позиции. Это не преувеличение — именно так заканчиваются истории с keystore «который лежал только на ноутбуке разработчика».
Создание и хранение keystore
Генерация через keytool:
keytool -genkeypair -v \
-keystore release.keystore \
-alias myapp \
-keyalg RSA \
-keysize 2048 \
-validity 10000 \
-storetype JKS
-validity 10000 — примерно 27 лет. Google рекомендует минимум 25 лет для приложений в Play Store. Более короткий срок — и Google Play в будущем откажется принимать обновления.
Keystore нельзя хранить в git-репозитории. Даже в приватном. Правила хранения: зашифрованный бэкап в облачном хранилище (минимум двух), физическая копия вне офиса, пароли — отдельно от файла.
Конфигурация Signing Config в Gradle
Прямое указание пути и паролей в build.gradle — антипаттерн:
// ТАК НЕ ДЕЛАТЬ — пароли в репозитории
signingConfigs {
release {
storeFile file("../keys/release.keystore")
storePassword "mysecretpassword" // в git попадёт
keyAlias "myapp"
keyPassword "mysecretpassword"
}
}
Правильный подход — через переменные окружения или local.properties:
// build.gradle (app)
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('keystore.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias'] ?: System.getenv('KEY_ALIAS')
keyPassword keystoreProperties['keyPassword'] ?: System.getenv('KEY_PASSWORD')
storeFile keystoreProperties['storeFile'] ?
file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword'] ?: System.getenv('STORE_PASSWORD')
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
keystore.properties — в .gitignore. На CI передаём переменные окружения напрямую.
Kotlin DSL вариант
// build.gradle.kts
val keystoreProperties = Properties()
val keystoreFile = rootProject.file("keystore.properties")
if (keystoreFile.exists()) {
keystoreProperties.load(keystoreFile.inputStream())
}
android {
signingConfigs {
create("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
?: System.getenv("KEY_ALIAS")
keyPassword = keystoreProperties.getProperty("keyPassword")
?: System.getenv("KEY_PASSWORD")
storeFile = keystoreProperties.getProperty("storeFile")?.let { file(it) }
storePassword = keystoreProperties.getProperty("storePassword")
?: System.getenv("STORE_PASSWORD")
}
}
}
Play App Signing
Google предлагает Play App Signing — ваш upload key подписывает APK/AAB при загрузке, Google перепаковывает с отдельным app signing key. Это страховка: если upload key утерян, Google может его ротировать. При этом fingerprint сертификата для SHA-256 (нужен для Firebase, OAuth, deeplinks) берётся с app signing key, не с upload key — путают регулярно.
Включить Play App Signing: Play Console → Release → Setup → App signing. После включения нельзя отключить.
# Проверить fingerprint текущего keystore
keytool -list -v -keystore release.keystore -alias myapp
# В Play Console: Setup → App signing → App signing key certificate — сравнить SHA-256
CI/CD интеграция
На GitHub Actions:
- name: Sign APK
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > release.keystore
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=$(pwd)/release.keystore \
-Pandroid.injected.signing.store.password=$STORE_PASSWORD \
-Pandroid.injected.signing.key.alias=$KEY_ALIAS \
-Pandroid.injected.signing.key.password=$KEY_PASSWORD
Keystore кодируем в base64 (base64 release.keystore) и сохраняем в secrets репозитория. На агенте декодируем в файл, используем, удаляем.
Процесс работы
Генерация production keystore с корректным сроком действия, безопасное хранение.
Настройка Signing Config в Gradle через переменные окружения, без паролей в коде.
Опционально: подключение Play App Signing, получение нового fingerprint для Firebase/OAuth.
Конфигурация CI/CD pipeline с секретами, тестовая сборка release APK/AAB.
Ориентиры по срокам
Настройка Signing Config и CI/CD для одного флейвора — 2–4 часа. При нескольких flavor-конфигурациях и интеграции с Play App Signing — 1 день.







