Code Signing (підпис коду) — механізм цифрового підпису виконуваних файлів, що гарантує справжність розробника та цілісність додатка. В Android кожен APK-файл обов'язково підписується сертифікатом перед встановленням на пристрій або публікацією в Google Play. За даними Google, 2024, Android підтримує чотири покоління схем підпису: від v1 на основі JAR до v4 для потокового встановлення.
Головне
Code Signing — криптографічний процес, у ході якого розробник підписує виконуваний код своїм цифровим сертифікатом. Підпис створюється з використанням асиметричного шифрування: закритим ключем розробника генерується цифровий підпис, а відкритий ключ вбудовується в сертифікат. Будь-хто може перевірити підпис, використовуючи відкритий ключ, але змінити код без порушення підпису неможливо.
У мобільній розробці підпис коду виконує три функції. Перша — автентифікація: користувач і платформа можуть ідентифікувати розробника додатка. Друга — цілісність: будь-яка зміна APK після підписання робить підпис недійсним. Третя — довірене оновлення: платформа дозволяє оновлювати додаток тільки тими APK, які підписані тим самим сертифікатом, що й встановлена версія.
Цифровий підпис Android-додатків має юридичне значення. Відповідно до законодавства РФ (63-ФЗ) та європейського eIDAS, кваліфікований електронний підпис прирівнюється до власноручного. Однак підпис APK з використанням самопідписаного сертифіката (звичайна практика в Android) не є кваліфікованим — він підтверджує цілісність, але не особу розробника з юридичної точки зору.
Android підтримує чотири схеми підпису APK, кожна з яких вирішує проблеми попередньої версії та додає нові можливості. Всі схеми можуть співіснувати в одному APK — це необхідно для зворотної сумісності зі старими версіями Android.
Схема v1 (JAR signing) з'явилася в Android 1.0. Вона підписує окремі файли всередині APK-архіву за допомогою записів у META-INF/MANIFEST.MF. Недолік: можна змінити APK (додати або видалити файли) і перепідписати тільки змінені, не торкаючись підпису інших. Це робить v1 вразливою для деяких атак. Схема v2 (APK Signature Scheme), введена в Android 7.0, підписує весь APK-файл цілком, включаючи всі байти крім самого підпису, що виключає можливість вибіркової модифікації.
| Схема | Android | Особливість | Ротація ключа |
|---|---|---|---|
| v1 (JAR) | 1.0+ | Підпис кожного файлу | Ні |
| v2 | 7.0+ | Підпис всього APK | Ні |
| v3 | 9.0+ | Підпис + ротація | Так |
| v4 | 11.0+ | Потоковий + ADB | Так |
Схема v3, представлена в Android 9.0, вирішує давню проблему: що робити, якщо ключ підпису скомпрометовано або термін його дії закінчився? Раніше зміна ключа підпису означала, що додаток сприймається як новий — його не можна встановити поверх існуючого. v3 додає механізм ротації: в APK можна включити доказ зміни ключа (proof-of-rotation), підписаний старим ключем. Система перевіряє ланцюжок і дозволяє оновити додаток, підписаний новим ключем.
Keystore — захищений контейнер, що містить закриті ключі та сертифікати для підпису додатків. У Android-розробці використовується формат JKS (Java KeyStore) або PKCS12. Keystore створюється утилітою keytool, що входить до складу JDK. Кожен ключ у сховищі ідентифікується псевдонімом (alias) і захищений паролем.
Сертифікат у keystore містить відкритий ключ та інформацію про власника: назву організації, країну, термін дії. Для Android-додатків сертифікат може бути самопідписаним — Google не вимагає звернення до центру сертифікації (CA), що відрізняє Android від iOS. Однак термін дії сертифіката повинен бути не менше 25 років, оскільки додаток оновлюватиметься цим же ключем.
# Створення нового keystore для підпису
keytool -genkey -v -keystore my-release.keystore \
-alias my-app-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# Перегляд вмісту keystore
keytool -list -v -keystore my-release.keystore
Android підтримує два алгоритми для ключів підпису: RSA та ECDSA. RSA з розміром ключа 2048 біт — стандарт де-факто, підтримуваний всіма версіями Android. ECDSA (алгоритм цифрового підпису на еліптичних кривих) з кривою P-256 забезпечує таку ж криптостійкість при меншому розмірі ключа. Починаючи з Android 9.0 рекомендується використовувати ECDSA, оскільки він швидший у верифікації на мобільних пристроях.
У Android Gradle Plugin підпис налаштовується через блок signingConfigs у build.gradle рівня модуля. Для debug-збірок Android Studio автоматично створює налагоджувальний keystore з відомими паролями. Для release-збірок розробник вказує шлях до свого keystore, псевдонім ключа та паролі. Рекомендується зберігати паролі в окремих конфігураційних файлах, виключених із системи контролю версій.
Сучасна практика — централізоване управління підписом через CI/CD. Jenkins, GitLab CI або GitHub Actions можуть зберігати keystore як захищений артефакт, а паролі — у секретах середовища. Це запобігає витоку ключів через репозиторій і спрощує зміну ключа при необхідності.
// build.gradle (рівень додатка) — конфігурація підпису
android {
signingConfigs {
release {
storeFile file("my-release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
Для максимальної сумісності APK повинен бути підписаний всіма трьома схемами (v1 + v2 + v3). Android Gradle Plugin за замовчуванням включає всі схеми. APK, підписаний тільки v2, не встановиться на Android 6.0 і нижче. APK тільки з v1 не отримає переваги цілісності v2 на Android 7.0+. Включення всіх схем не збільшує розмір APK більш ніж на 1–2% і забезпечує сумісність з будь-яким пристроєм.
Play App Signing — сервіс Google Play, який централізовано керує ключами підпису додатків. Розробник завантажує в Google Play Console APK, підписаний ключем завантаження (upload key), а Google Play перепідписує його ключем поширення (distribution key) перед доставкою користувачам. Це захищає ключ поширення від втрати або компрометації.
Переваги Play App Signing: безпека — ключ поширення зберігається в захищеному сховищі Google; ротація — можна запросити зміну ключа через консоль; відновлення — при втраті ключа завантаження можна згенерувати новий. Недолік: для додатків, що існували до впровадження Play App Signing, перехід вимагає створення нового додатка, оскільки старий ключ поширення вже використовується.
# Отримання відбитка сертифіката (SHA-256)
keytool -list -v -keystore my-release.keystore \
-alias my-app-alias | grep "SHA256"
# Перевірка підпису APK через apksigner
apksigner verify --verbose app-release.apk
Якщо ключ підпису втрачено, а Play App Signing не використовується, відновити можливість оновлення додатка неможливо — доведеться створювати новий додаток з новим ім'ям пакета. Це одна з головних причин використовувати Play App Signing. Google рекомендує зберігати резервну копію keystore в захищеному офлайн-сховищі (зашифрований USB-носій, банківська комірка).
При встановленні APK Android виконує верифікацію підпису в кілька етапів. Перший — перевірка сертифіката: чи не закінчився термін дії, чи коректний формат. Другий — перевірка підпису: чи збігається криптографічний підпис із вмістом APK. Третій — порівняння сертифіката зі встановленою версією: якщо додаток вже є на пристрої, сертифікат повинен збігатися, інакше встановлення блокується.
Система верифікації вбудована в PackageManagerService. При обробці запиту на встановлення PMS витягує підпис з APK, перевіряє його за допомогою класу android.util.PackageParser і порівнює зі збереженим підписом встановленого додатка (якщо він існує). При неспівпадінні користувач отримує помилку “INSTALL_FAILED_UPDATE_INCOMPATIBLE”. Цей механізм запобігає атакам підміни (malware не може оновити легальний додаток своєю версією).
Розробник може самостійно перевірити підпис APK за допомогою утиліти apksigner з Android SDK Build Tools. Команда apksigner verify --verbose app.apk показує, якими схемами підписано APK, чи дійсні сертифікати та чи збігаються підписи з вмістом. Для програмної перевірки підпису встановленого додатка використовується PackageManager.getPackageInfo() з прапорцем GET_SIGNATURES.
// Програмна перевірка підпису встановленого додатка
fun getAppSignature(context: Context, packageName: String): String? {
val pm = context.packageManager
val info = pm.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
return info.signatures?.firstOrNull()?.toCharsString()
}
Безпека ключа підпису — критичний аспект Android-розробки. Компрометація ключа дозволяє зловмиснику підписувати оновлення вашого додатка своїм кодом. Основні правила: ніколи не зберігайте ключ у репозиторії, не використовуйте один ключ для різних додатків, не передавайте ключ через незахищені канали (email, месенджери).
Рекомендована практика — розділення ключів. Використовуйте окремий ключ для кожного додатка та окремий ключ для завантаження в Google Play (upload key). Для налагоджувальних збірок Android Studio створює спільний debug.keystore — його не можна використовувати для release-збірок. Термін дії сертифіката повинен становити 25–30 років (діючий стандарт, підтверджений Google).
| Практика | Рекомендація |
|---|---|
| Зберігання ключа | Зашифрований носій, CI/CD секрети |
| Термін сертифіката | Не менше 25 років |
| Алгоритм | RSA 2048+ або ECDSA P-256 |
| Розділення | Окремий ключ на додаток |
| Резервування | Офлайн-копія keystore |
Регулярно перевіряйте цілісність ланцюжка підпису. При зміні співробітників, які мають доступ до ключів, оновлюйте upload key через Google Play Console. Використовуйте інструменти на кшталт Google Play Integrity API для перевірки, що ваш додаток не був підроблений на пристроях користувачів. API повертає дані про підпис, цілісність і відправляє їх на сервер для верифікації.
Часті запитання
Code Signing — це цифровий підпис APK-файлу, який підтверджує, що додаток створено конкретним розробником і не було змінено після підписання. Без підпису APK не встановиться на пристрій.
Використовуйте утиліту keytool з JDK: keytool -genkey -v -keystore my-release.keystore -alias my-alias -keyalg RSA -keysize 2048 -validity 10000. Отриманий keystore вкажіть у build.gradle в блоці signingConfigs.
Якщо ключ втрачено і ви не використовуєте Play App Signing, оновлення додатка стане неможливим. Доведеться створювати новий додаток у Google Play з новим package name. Використовуйте Play App Signing для захисту від втрати ключа.
v1 підписує кожен файл всередині APK окремо — зловмисник може змінити один файл і перепідписати тільки його. v2 підписує весь APK цілком — будь-яка зміна робить підпис недійсним, що забезпечує вищий рівень безпеки.
Play App Signing — сервіс Google Play, який централізовано зберігає ключ поширення додатків. Розробник завантажує APK, підписаний upload key, а Google перепідписує його перед доставкою користувачам, захищаючи ключ від втрати або крадіжки.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також