Code Signing (потписивање кода) — механизам дигиталног потписивања извршних датотека, који гарантује аутентичност програмера и интегритет апликације. У Android-у, свака APK датотека мора бити потписана цертификатом пре инсталације на уређају или објављивања у Google Play. Према Google, 2024, Android подржава четири генерације шема потписа: од v1 заснованог на JAR-у до v4 за стриминг инсталацију.
Главно
Code Signing — криптографски процес у којем програмер потписује извршни код својим дигиталним цертификатом. Потпис се креира коришћећем асиметричне енкрипције: приватним кључем програмера генерише се дигитални потпис, а јавни кључ се уграђује у цертификат. Свако може да потврди потпис коришћећем јавног кључа, али је измена кода без нарушавања потписа немогућа.
У мобилном развоју потписивање кода има три функције. Прва — аутентификација: корисник и платформа могу да идентификују програмера апликације. Друга — интегритет: свака измена APK-а након потписивања поништава потпис. Трећа — поуздано ажурирање: платформа дозвољава ажурирање апликације само оним APK-овима који су потписани истим цертификатом као и инсталирана верзија.
Дигитални потпис андроид апликација има правни значај. У складу са законодавством Руске Федерације (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 (Elliptic Curve Digital Signature Algorithm) са кривом P-256 пружа исту криптографску снагу уз мању величину кључа. Од Android 9.0 препоручује се коришћење ECDSA, јер је бржи у верификацији на мобилним уређајима.
У Android Gradle Plugin-u потпис се подешава кроз блок 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, опоравак могућности ажурирања апликације је немогућ — мораћете креирати нову апликацију у Google Play-у са новим именом пакета. То је један од главних разлога за коришћење Play App Signing. Google препоручује чување резервне копије keystore-а у заштићеном офлайн складишту (шифровани USB медијум, банковски сеф).
При инсталацији APK-а, Android врши верификацију потписа у неколико корака. Први — провера цертификата: није ли истекао, да ли је формат исправан. Други — провера потписа: поклапа ли криптографски потпис са садржајем APK-а. Трећи — поређење цертификата са инсталираном верзијом: ако апликација већ постоји на уређају, цертификат мора бити исти, иначе ће инсталација бити блокирана.
Систем за верификацију је уграђен у PackageManagerService. При обради захтева за инсталацију, PMS извлачи потпис из APK-а, проверава га класом android.util.PackageParser и пореди га са сачуваним потписом инсталиране апликације (ако постоји). У случају непоклапања, корисник добија грешку „INSTALL_FAILED_UPDATE_INCOMPATIBLE”. Овај механизам спречава нападе замене (злонамјерни софтвер не може да ажурира легитимну апликацију својом верзијом).
Програмер може самостално да провери потпис 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). За debug изградње, 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-у са новим именом пакета. Користите Play App Signing за заштиту од губитка кључа.
v1 потписује сваку датотеку унутар APK-а појединачно — нападач може да измени једну датотеку и поново је потпише само њу. v2 потписује цеокупни APK у потпуности — свака измена поништава потпис, што осигурава виши ниво безбедности.
Play App Signing — Google Play сервис који централизовано чува кључ за дистрибуцију апликација. Програмер отпрема APK потписан upload key-ом, а Google га поново потписује пре достављања корисницима, штитећи кључ од губитка или крађе.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође