Construirea de aplicații este o pasiune împărtășită de dezvoltatorii de software din întreaga lume. Dar sarcina administrativă de gestionare a semnării codului este plictisitoare. Cum putem să o facem bine de prima dată? Lewis Cianci analizează această problemă.
Dă-mi voie să spun asta de la început.
Semnarea codurilor este atât de plictisitoare încât mă doare dinții. Este un concept care există cu un motiv întemeiat. Adică, vrei ca oamenii să fie siguri că pachetul tău software este de fapt de la tine, nu?! Și totuși, este un lucru pe care atât de mulți dezvoltatori se străduiesc să-l facă bine zilnic. Este ca și cum ți-ai face taxele după un an întreg de muncă și ai avea atâtea formulare de completat. Yippee.
Derulați în jos dacă doriți doar să vedeți ghidul pas cu pas privind semnarea codurilor Android și nu sunteți interesați de motivul pentru care facem acest lucru😉
De ce semnăm coduri
Ne semnăm pachetele astfel încât oamenii care ne descarcă pachetul din Play Store să știe de fapt că suntem noi. Facem acest lucru prin semnarea pachetului nostru cu o cheie pe care o generăm. Când încărcăm pachetul nostru semnat în Google Play, acesta își amintește cheia care a fost folosită pentru a încărca pachetul inițial și se asigură că pachetele ulterioare sunt semnate cu aceeași cheie.
Pentru a atinge acest obiectiv, semnarea pachetelor Android profită de fapt de un instrument care provine din Java Development Framework numit keytool. Keytool există probabil de la fel de mult timp ca și JDK-ul însuși, deci este destul de vechi. Acest lucru se pretează, probabil, la unele dintre motivele pentru care semnarea unui APK sau AAB (pachet de aplicații Android) este atât de confuză cum este.
De ce nu se poate ca Play Store să se ocupe pur și simplu de semnarea codului pentru noi?
Am fi tentați să cerem o nirvana în care am putea să dăm toate pachetele noastre de aplicații nesemnate către Play Store și să-i lăsăm pe ei să se descurce și să le semneze pentru noi. Logica acestui lucru se prăbușește însă rapid. Dacă ați scrie o carte, ați pune pe altcineva să o semneze? Nu. Ai semna-o pentru că tu ești autorul.
În zilele noastre, semnarea codurilor este mult mai ușoară decât era înainte. Atâta timp cât semnăm întotdeauna pachetele noastre cu aceeași cheie (cheia „upload key”), Google Play va genera și va gestiona de fapt cheile noastre de semnare a codului pentru noi.
Dacă sunteți deosebit de întreprinzători, puteți încerca să citiți și să înțelegeți totul aici, dar eu dezvolt pentru Android de aproape trei ani și sunt trist să spun că nici măcar eu nu înțeleg totul în totalitate. Tot ce știu este că, atunci când se strică, este o durere imensă de reparat.
Să ne facem timp să înțelegem nu numai cum să codăm semnul, ci și de ce codăm semnul. Când înțelegem necesitatea acestui proces, va fi mai ușor de realizat.
De ce avem nevoie pentru semnarea codului?
Versiunea scurtă este aici. Pentru semnarea codului avem nevoie de:
- crearea fișierului Java Development Kit (JDK);
- să semnăm pachetul nostru de aplicații sau APK cu cheia noastră privată;
- modificarea build.gradle;
- trimiterea pachetului către distribuitor (Google Play).
În finalul acestui articol veți găsi, de asemenea, cum să faceți să funcționeze semnarea codului cu Codemagic.
Acum o versiune puțin mai lungă cu un ghid pas cu pas despre ce avem nevoie pentru semnarea codului Android și cum să o facem.
Ghid pas cu pas pentru semnarea codului Android
PASUL 1: Kitul de dezvoltare Java (JDK)
Dacă dezvoltați pentru Android, probabil că aveți deja instalate acestea.
Trebuie să creăm un fișier Java Key Store (JKS) care conține informațiile noastre de semnare. Prin generarea unui JKS pentru aplicația noastră, creăm de fapt o cheie privată pe calculatorul nostru. Această cheie privată este protejată de o parolă pe care am setat-o.
Dintr-o linie de comandă, putem tasta următoarele pentru a obține un JKS.
keytool -genkey -v -keystore %DESKTOP%/key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias DEVELOPERNAME
Îi spunem lui keytool
să genereze un Java Key Store și să-l pună în biroul nostru. Această cheie va fi valabilă timp de 10.000 de zile sau aproximativ 27 de ani, permițându-ne să furnizăm actualizări pe toată durata de viață a aplicației noastre. De asemenea, ni se cere să setăm un alias. Eu îl fac pur și simplu numele meu de dezvoltator sau ceva de care să îmi amintesc.
keytool
va solicita diverse informații pe parcurs. Este important să le specificați corect, deoarece în esență definim detaliile pentru cheia noastră privată.
Vă va fi solicitată:
- Parola depozitului de chei – veți avea nevoie de aceasta pentru a debloca din nou acest depozit de chei în viitor. Dacă pierdeți această parolă, este aproape imposibil să o recuperați.
- Reintroduceți parola keystore
- Detalii personale despre ce să puneți în certificatul personal
Ni se va cere să completăm câteva detalii despre noi. Acestea sunt detaliile care sunt asociate cheii noastre private, deci ar trebui să fie oarecum relevante. Depinde de voi ce puneți în aceste câmpuri, dar ca regulă generală, eu nu le-aș face prea nebunești.
Aceasta este ieșirea lui keytool
.
C:\code\signingtest\android\app>keytool -genkey -v -keystore key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias androidappsEnter keystore password:Re-enter new password:What is your first and last name?: Codemagic Article DudeWhat is the name of your organizational unit?: Fantastic Apps And Where To Find ThemWhat is the name of your organization?: GreatappsWhat is the name of your City or Locality?: EstoniaWhat is the name of your State or Province?: TartuWhat is the two-letter country code for this unit?: EEIs CN=Codemagic Article Dude, OU=Fantastic Apps And Where To Find Them, O=Greatapps, L=Estonia, ST=Tartu, C=ES correct?:
Atenție! Dacă doar trimiteți spam Enter prin acest proces, creația se va repeta în buclă la nesfârșit, pe măsură ce răspundeți „nu” la ultima întrebare.
În acest fel, am creat un JKS și am pus în el cheia privată generată de noi înșine. Deoarece am generat-o și am setat parola, putem fi siguri că oricine are acest fișier JKS suntem noi sau este autorizat în mod special să îl folosească.
Dacă cineva are JKS-ul dvs. și acreditările corecte, poate semna pachete ca dvs. sau ca firma dvs. Păstrați-l în siguranță, nu-l puneți pe source control.
Acum avem Java Key Store, deci suntem la jumătatea drumului! Bucurați-vă în consecință.
PASUL 2: Semnarea pachetului nostru de aplicații sau a APK-ului cu cheia noastră privată
Acum, vrem să semnăm pachetul nostru de aplicații cu acel JKS pe care tocmai l-am făcut. Este posibil să semnăm manual codul APK-ului nostru sau al build-ului de lansare de fiecare dată, dar, în realitate, ar fi mai bine să îl configurăm astfel încât, atunci când rulăm flutter build apk --release
, să semneze automat pachetul nostru cu cheia de încărcare corectă. Documentația Flutter vorbește despre cum să actualizăm fișierele Gradle aici, dar noi o vom face încet și vom explica pe parcurs.
Pentru a începe, să deschidem fișierul nostru flutter_app/android/app/build.gradle
. În jurul liniei 49 putem vedea acest lucru:
buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so flutter run --release works. signingConfig signingConfigs.debug }}
Principalul lucru care se întâmplă aici este că compilările noastre sunt semnate cu keystore-ul debug
, astfel încât compilarea noastră de lansare încă funcționează. Vrem să schimbăm acest lucru astfel încât versiunile noastre să fie semnate cu propriul nostru keystore. În acest fel, ele pot fi încărcate în magazinul Google Play.
Primul lucru pe care îl facem este să creăm un key.properties
în directorul nostru de aplicații. Creăm acest lucru în flutter_app/android/key.properties
.
key.properties
Va include toate detaliile de care avem nevoie pentru a semna cu succes pachetul nostru.
storePassword=The JKS store passwordkeyPassword=The key passwordkeyAlias=The alias for your keystoreFile=Where to look for your keystore file
O scurtă notă despre controlul sursei
Ar trebui să vă gândiți înainte de a verifica acest cod în controlul sursei. Dacă actorii răi ar avea acces la keystore și la aceste credențiale și ar avea control asupra conturilor dvs. și ar putea, eventual, să împingă o nouă actualizare a aplicației dvs. cu malware sau alte lucruri rele. Majoritatea soluțiilor CI/CD vă permit să furnizați aceste detalii sub formă de „secrete”, dar implementarea diferă în funcție de platformă.
PASUL 3: Recapitulare &Modificarea build.gradle
Am creat un fișier keystore și am specificat un alias, precum și o parolă pentru a le proteja keystore. Dacă folosim semnarea aplicației Google Play (pe care o folosiți în mod implicit), atunci cheia pe care am generat-o acționează ca cheie de încărcare. Primul pachet pe care îl încărcăm prin intermediul consolei Google Play va fi semnat cu această cheie. Acest lucru îi dovedește lui Google că suntem cine spunem că suntem.
Trece sens? Mișto, haideți să o facem să semneze ca parte a procesului nostru de construire Flutter.
Modificați build.gradle
Deschideți flutter_app/android/app/build.gradle
. Pe aproximativ linia 31 sau cam așa ceva ar trebui să vedeți un text ca acesta:
android { compileSdkVersion 29` lintOptions { disable 'InvalidPackage' }...
Vrem să-i spunem lui Gradle unde să găsească magazinul de chei. Facem acest lucru punând aceste detalii pe aproximativ linia 28, deasupra declarației android {
.
def keystoreProperties = new Properties()def keystorePropertiesFile = rootProject.file('key.properties')if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile))}
Să descompunem cele de mai sus…
Definim o variabilă keystoreProperties
. Apoi, verificăm dacă key.properties
există relativ la rădăcina proiectului nostru android (nu la proiectul Flutter).
Când se execută compilarea noastră, se încarcă key.properties
. key.properties
identifică locația keystore-ului, plus acreditările necesare pentru a debloca Java Key Store pentru a semna pachetul. Cu toate detaliile necesare în mână, Gradle semnează acum pachetul de aplicații sau APK ca parte a construcției noastre de lansare.
Să verificăm de două ori că toate fișierele noastre sunt la locul potrivit.
Dispoziția proiectului nostru android modificat build.gradle
este în flutter_app/android/app/build.gradle
.
Filmul nostru key.jks
este în flutter_app/android/app/key.jks
.
Filmul nostru key.properties
este în flutter_app/android/key.properties
.
După ce suntem siguri de cele de mai sus, ar trebui să putem rula flutter build apk --release
acum și semnarea ar trebui să funcționeze bine.
PASUL 4: Trimiterea la Google Play Store
Acum putem încărca APK-ul nostru sau pachetul de aplicații în Play Store. Când facem acest lucru cu pachetul nostru semnat și cu Google Play Signing activat (ceea ce este în mod implicit), Google va recunoaște cheia pe care am folosit-o pentru a semna pachetul și o va reține ca fiind cheia noastră de încărcare. Google va semna apoi APK-ul sau pachetul nostru de aplicații cu propria lor cheie. Este important ca orice actualizare ulterioară pe care o furnizăm pentru această aplicație, să o semnăm cu aceeași cheie. Google Play recunoaște această cheie ca fiind cheia noastră de încărcare și nu putem lansa actualizări fără ea.
Nu înțeleg nimic din cele de mai sus și aș aprecia o ilustrare incredibil de vizuală a ceea ce se întâmplă exact.
Pot face! Asta este ceea ce se întâmplă.
- Generăm o modalitate super secretă de a ne identifica, aproape ca și cum ne-am face un pașaport pentru noi înșine.
- Pentru că oricine cu acest „pașaport” va putea să se identifice în mod pozitiv ca fiind noi (adică să se dea drept noi fără prea multă rezistență), îl blocăm în spatele unei parole în seiful nostru (JKS, sau Java Key Store).
- Creăm pachetul de aplicații sau APK și apoi semnăm pachetul cu aceeași semnătură pe care am folosit-o pe pașaport. Pentru a accesa acest pașaport, trebuie să deblocăm seiful în care se află pașaportul (furnizând parola și aliasul procesului de construire Gradle).
- Întocmai trimitem pachetul către distribuitor (Google Play). Distribuitorul, văzând pachetul pentru prima dată, ia notă de semnătura noastră pe care am folosit-o pe acest pachet și face o copie a acesteia.
- Când trimitem pachete către distribuitorul nostru (Google Play) în viitor, semnăm aceste pachete cu aceleași detalii pe care le-am folosit inițial. Distribuitorul nostru, amintindu-și detaliile pe care le-am folosit inițial pentru a încărca pachetul, fie acceptă, fie respinge pachetul. Dacă se potrivește (dacă cheia de încărcare este aceeași cu cea pe care am folosit-o inițial), atunci pachetul este acceptat și distribuit. În caz contrar, nu este acceptat.
- Distribuitorul nostru, știind că pachetul inițial și potențialele pachete viitoare provin cu siguranță de la noi, distribuie pachetul.
Făcând ca semnarea codului să funcționeze cu Codemagic
În cele din urmă, dorim să semnăm acest lucru ca parte a fluxului nostru de lucru CI/CD, dar, în același timp, nu dorim să verificăm fișierul nostru keystore și de proprietăți în controlul sursei. În schimb, vrem ca furnizorul nostru CI/CD să construiască pachetul și apoi să îl semneze mai târziu în procesul de construire cu un keystore pe care îl furnizăm noi.
Setting it up with Git
Dacă avem o aplicație Flutter complet nouă, atunci putem trece la dosar și tasta git init
pentru a începe să folosim controlul sursei cu aplicația.
În mod implicit, vom verifica cu plăcere fișierul nostru keystore și keystore properties, ceea ce este o idee proastă din punct de vedere al securității.
Ar trebui să obțineți acest lucru încă de la început
Dacă verificați din greșeală fișierul keystore properties și keystore și împingeți aceste modificări, oamenii vor putea extrage aceste fișiere în orice moment în viitor, uitându-se în istoricul Git. Puteți elimina manual fișierele din Git în viitor sau vă puteți reinitializa depozitul fără acele fișiere, dar este mai bine să nu le verificați de la bun început.
Vrem să adăugăm aceste rânduri la sfârșitul fișierului nostru .gitignore
:
# Don't check in the keystore files or equivalent*.jkskey*.properties
Niciun Java KeyStore (JKS) sau proprietăți pentru semnarea codului nu vor fi verificate în controlul sursei. Cât de drăguț.
Făcând ca build.gradle să nu semneze atunci când rulează pe CI/CD
În timp ce proiectul dumneavoastră se construiește, keystore-ul și setările nu sunt disponibile. Vrem ca build-ul să producă în continuare un build de lansare chiar dacă nu este semnat.
Aceasta este partea din build.gradle
mea care permite acest lucru:
signingConfigs { file(rootProject.file('key.properties')).with { propFile -> if (propFile.canRead()) { release { keyAlias keystoreProperties keyPassword keystoreProperties storeFile file(keystoreProperties) storePassword keystoreProperties } } else { print('not signed') } }}buildTypes { release { file(rootProject.file('key.properties')).with { propFile -> if (propFile.canRead()) { // because we can read the keystore // we are building locally // so sign locally // otherwise build an unsigned apk for later signing by the CI/CD provider signingConfig signingConfigs.release } } applicationVariants.all { variant -> variant.outputs.all { output -> output.outputFileName = "app-release.apk" } } // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. // signingConfig signingConfigs.release }}
Configurarea Codemagic pentru a semna build-urile noastre
În procesul dvs. de construire, găsiți secțiunea de semnare a codului Android (este în secțiunea Publish). Arată cam așa:
Acum, încărcăm keystore-ul nostru și setăm parola, aliasul cheii și parola cheii (care sunt aceleași cu cele pe care le-am setat inițial în fișierul keystore.properties).
Apoi apăsăm „Save”. Când Codmagic rulează procesul nostru de construire, acesta va produce automat un APK sau App Bundle semnat pentru noi.
Și cam asta e tot! Cu acest APK sau App Bundle semnat, vă puteți implementa aplicația în Play Store.
Puteți verifica repo-ul meu Git pentru un exemplu aici (evident, fără keystore sau proprietăți).
Asta este.
Dacă sunteți încă pierduți, nu ezitați să mă anunțați la @azimuthapps și voi încerca să vă ajut. Poate fi frustrant să o faci cum trebuie, dar odată ce o faci, ar trebui să funcționeze în viitorul apropiat.
Lewis Cianci este un dezvoltator de software în Brisbane, Australia. Primul său calculator a avut o unitate de bandă. El dezvoltă software de cel puțin zece ani și a folosit destul de multe cadre de dezvoltare mobilă (cum ar fi Ionic și Xamarin Forms) în timpul său. După ce s-a convertit la Flutter, însă, nu se va mai întoarce niciodată înapoi. Puteți să dați de el pe blogul său, să citiți despre alte lucruri care nu țin de Flutter pe Medium, sau poate că îl puteți zări la cea mai apropiată și mai elegantă cafenea cu el și cu draga lui soție.
Mai multe articole de Lewis: