Vytváření aplikací je vášní, kterou sdílí vývojáři softwaru po celém světě. Ale administrativní režie spojená se správou podepisování kódu je únavná. Jak to udělat správně hned napoprvé? Lewis Cianci se tomu věnuje.
Nechte mě to říct předem.
Podepisování kódu je tak nudné, až z toho bolí zuby. Je to koncept, který existuje z dobrého důvodu. Vždyť chcete, aby si lidé byli jisti, že váš softwarový balíček je skutečně od vás, ne?! A přesto je to něco, s čím se mnoho vývojářů denně potýká. Je to, jako když si po celoroční práci děláte daně a musíte vyplnit tolik formulářů. Yippee.
Přejděte dolů, pokud se chcete jen podívat na průvodce krok za krokem podepisováním kódu pro Android a nezajímá vás, proč to děláme😉
Proč podepisujeme kód
Podepisujeme naše balíčky, aby lidé, kteří si stáhnou náš balíček z Obchodu Play, skutečně věděli, že jsme to my. Děláme to tak, že náš balíček podepisujeme námi vygenerovaným klíčem. Když náš podepsaný balíček nahrajeme do služby Google Play, zapamatuje si klíč, který byl použit k nahrání původního balíčku, a zajistí, aby byly následující balíčky podepsány stejným klíčem.
Pro dosažení tohoto cíle podepisování balíčků v systému Android ve skutečnosti využívá nástroj, který pochází z vývojového rámce Java a nazývá se keytool. Nástroj keytool existuje pravděpodobně stejně dlouho jako samotné JDK, takže je poměrně starý. To propůjčuje pravděpodobně některé z důvodů, proč je podepisování APK nebo AAB (balíčku aplikací pro Android) tak matoucí, jak je.
Proč za nás nemůže podepisování kódu vyřešit Obchod Play?
Byli bychom v pokušení žádat o nirvánu, kdy bychom mohli všechny naše nepodepsané balíčky aplikací dát do Obchodu Play a oni by to prostě vyřešili a podepsali za nás. Logika takového postupu se však rychle hroutí. Kdybyste napsali knihu, nechali byste si ji podepsat od někoho jiného? Ne, podepsali byste ji vy, protože jste její autor.
Dnes je podepisování kódu mnohem jednodušší, než bývalo. Pokud své balíčky podepisujeme vždy stejným klíčem („upload key“), Google Play za nás skutečně vygeneruje a spravuje naše klíče pro podepisování kódu.
Jste-li obzvlášť podnikaví, můžete se pokusit si vše přečíst a pochopit zde, ale já vyvíjím pro Android už skoro tři roky a musím bohužel říct, že ani já tomu úplně nerozumím. Jediné, co vím, je, že když se to rozbije, je to obrovská otrava to opravovat.
Nechte si čas na to, abychom pochopili nejen to, jak znak kódovat, ale také proč znak kódovat. Když pochopíme nutnost tohoto procesu, usnadní nám to jeho dokončení.
Co potřebujeme k podepisování kódu?“
Krátká verze je zde. Pro podepisování kódu potřebujeme:
- vytvořit soubor Java Development Kit (JDK);
- podepsat náš balíček aplikace nebo APK naším soukromým klíčem;
- upravit build.gradle;
- odeslat balíček distributorovi (Google Play).
V závěru tohoto článku se také dozvíte, jak zprovoznit podepisování kódu pomocí programu Codemagic.
Nyní trochu delší verze s průvodcem krok za krokem, co potřebujeme pro podepisování kódu pro Android a jak to provést.
Průvodce krok za krokem pro podepisování kódu pro Android
KROK 1: Vývojová sada Java (JDK)
Pokud vyvíjíte pro Android, pravděpodobně je již máte nainstalované.
Potřebujeme vytvořit soubor Java Key Store (JKS), který obsahuje naše podpisové informace. Při vytváření souboru JKS pro naši aplikaci vlastně vytváříme soukromý klíč v našem počítači. Tento soukromý klíč je chráněn námi nastaveným heslem.
Z příkazového řádku můžeme zadat následující příkaz pro získání souboru JKS.
keytool -genkey -v -keystore %DESKTOP%/key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias DEVELOPERNAME
Povíme keytool
, aby vygeneroval soubor Java Key Store a umístil jej na naši pracovní plochu. Tento klíč bude platný 10 000 dní nebo zhruba 27 let, což nám umožní posílat aktualizace po celou dobu životnosti naší aplikace. Musíme také nastavit alias. Já si prostě vytvořím své vývojářské jméno nebo něco, co si budu pamatovat.
keytool
bude po cestě vyžadovat různé informace. Je důležité je zadat správně, protože v podstatě definujeme údaje pro náš soukromý klíč.
Budete vyzváni k zadání:
- Hesla keystoru – budete ho potřebovat, abyste mohli v budoucnu tento keystore opět odemknout. Pokud toto heslo ztratíte, je v podstatě nemožné ho obnovit.
- Znovu zadejte heslo úložiště klíčů
- Osobní údaje o tom, co má být uvedeno v osobním certifikátu
Budeme vyzváni k vyplnění některých údajů o nás. Jedná se o údaje, které jsou spojeny s naším soukromým klíčem, takže by měly být do jisté míry relevantní. Je na vás, co do těchto políček uvedete, ale zpravidla bych to nedělal příliš šíleně.
Toto je výstup 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?:
Dávejte pozor! Pokud budete tímto procesem jen spamovat Enter, bude se vytváření jen stále dokola opakovat, protože na poslední otázku odpovídáte „ne“.
Při tom jsme vytvořili JKS a vložili do něj vlastní vygenerovaný soukromý klíč. Protože jsme ho vygenerovali a nastavili heslo, můžeme si být jisti, že každý, kdo má tento soubor JKS, jsme buď my, nebo má výslovné povolení k jeho použití.
Pokud má někdo váš soubor JKS a správné přihlašovací údaje, může podepisovat balíčky jako vy nebo vaše společnost. Mějte ho v bezpečí, nedávejte ho do správy zdrojových kódů.
Nyní máme náš Java Key Store, takže jsme v polovině! Podle toho se radujte.
KROK 2: Podepsání našeho balíčku aplikací nebo APK naším soukromým klíčem
Nyní chceme podepsat náš balíček aplikací tím JKS, který jsme právě vytvořili. Je možné pokaždé ručně podepsat kódem náš APK nebo sestavení verze, ale ve skutečnosti bude lepší, když to nakonfigurujeme tak, že když spustíme flutter build apk --release
, tak to prostě automaticky podepíše náš balíček správným nahrávacím klíčem. V dokumentaci k aplikaci Flutter se píše o tom, jak aktualizovat soubory Gradle zde, ale my to projdeme pomalu a vysvětlíme si to průběžně.
Pro začátek otevřeme náš soubor flutter_app/android/app/build.gradle
. Přibližně na řádku 49 vidíme toto:
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 }}
Hlavní věc, která se zde děje, je, že naše sestavení jsou podepsána pomocí úložiště klíčů debug
, takže naše sestavení pro vydání stále funguje. Chceme to změnit tak, aby naše vydání byla podepsána naším vlastním úložištěm klíčů. Tak je budeme moci nahrát do obchodu Google Play.
První věc, kterou uděláme, je vytvoření key.properties
v adresáři naší aplikace. Ten vytvoříme v adresáři flutter_app/android/key.properties
.
key.properties
bude obsahovat všechny údaje, které potřebujeme k úspěšnému podepsání našeho balíčku.
storePassword=The JKS store passwordkeyPassword=The key passwordkeyAlias=The alias for your keystoreFile=Where to look for your keystore file
Krátká poznámka ke správě zdrojů
Než tento kód zaškrtnete ve správě zdrojů, měli byste se zamyslet. Pokud by zlí hráči získali přístup k úložišti klíčů a těmto pověřením a měli by kontrolu nad vašimi účty, mohli by potenciálně prosadit novou aktualizaci vaší aplikace s malwarem nebo jinými špatnými věcmi. Většina řešení CI/CD umožňuje zadat tyto údaje jako „tajemství“, ale implementace se liší podle platformy.
KROK 3: Rekapitulace & Úprava souboru build.gradle
Vytvořili jsme soubor úložiště klíčů a zadali alias a také heslo, které chrání jejich úložiště klíčů. Pokud používáme podepisování aplikací Google Play (které používáte ve výchozím nastavení), pak klíč, který jsme vygenerovali, funguje jako náš nahrávací klíč. První balíček, který odešleme prostřednictvím konzoly Google Play, bude podepsán tímto klíčem. Tím společnosti Google prokážeme, že jsme tím, za koho se vydáváme.
Dává to smysl? Super, zařídíme, aby se podepsal jako součást našeho procesu sestavení Flutteru.
Modifikujte build.gradle
Otevřete flutter_app/android/app/build.gradle
. Přibližně na řádku 31 nebo tak nějak byste měli vidět text v tomto znění:
android { compileSdkVersion 29` lintOptions { disable 'InvalidPackage' }...
Chceme říct Gradle, kde má najít úložiště klíčů. Uděláme to tak, že tyto údaje uvedeme asi na řádku 28, nad příkazem android {
.
def keystoreProperties = new Properties()def keystorePropertiesFile = rootProject.file('key.properties')if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile))}
Výše uvedené rozebereme…
Definujeme proměnnou keystoreProperties
. Poté zkontrolujeme, zda key.properties
existuje vzhledem ke kořenu našeho projektu android (nikoli projektu Flutter).
Při spuštění našeho sestavení se načte key.properties
. key.properties
identifikuje umístění úložiště klíčů a také potřebné pověření k odemčení úložiště klíčů Java pro podepsání balíčku. Se všemi potřebnými údaji v ruce nyní Gradle podepíše balíček aplikací nebo APK jako součást našeho sestavení pro vydání.
Jen dvakrát zkontrolujeme, zda jsou všechny naše soubory na správném místě.
Náš upravený build.gradle
je v flutter_app/android/app/build.gradle
.
Náš key.jks
soubor je v flutter_app/android/app/key.jks
.
Náš key.properties
soubor je v flutter_app/android/key.properties
.
Jakmile si budeme jisti výše uvedeným, měli bychom být nyní schopni spustit flutter build apk --release
a podepisování by mělo fungovat bez problémů.
KROK 4: Odeslání do obchodu Google Play
Nyní můžeme nahrát náš APK nebo balíček aplikací do obchodu Play. Když to uděláme s naším podepsaným balíčkem a se zapnutým podepisováním Google Play (což je ve výchozím nastavení), Google potvrdí klíč, který jsme použili k podepsání balíčku, a zapamatuje si ho jako náš klíč pro odeslání. Google pak podepíše náš balíček APK nebo aplikaci svým vlastním klíčem. Je důležité, abychom všechny následné aktualizace, které pro tuto aplikaci poskytneme, podepisovali stejným klíčem. Google Play tento klíč rozpozná jako náš klíč pro nahrávání a bez něj nemůžeme vydávat aktualizace.
Ničemu z výše uvedeného nerozumím a ocenil bych neuvěřitelně názornou ilustraci toho, co se přesně děje.
Můžu! Přesně to se děje.
- Vytváříme si super tajný způsob identifikace, skoro jako bychom si dělali pas.
- Protože kdokoli s tímto „pasem“ se bude moci pozitivně identifikovat jako my (tj.: bez většího odporu se za nás vydávat), uzamkneme ho za heslem v našem sejfu (JKS neboli Java Key Store).
- Vytvoříme balíček aplikací neboli APK a pak balíček podepíšeme stejným podpisem, jaký jsme použili na pase. Abychom získali přístup k tomuto pasu, musíme odemknout trezor, ve kterém se pas nachází (zadáním hesla a přezdívky procesu sestavení Gradle).
- Odesíláme balíček distributorovi (Google Play). Distributor, který balíček vidí poprvé, si všimne našeho podpisu, který jsme na tomto balíčku použili, a pořídí si jeho kopii.
- Pokud budeme v budoucnu posílat balíčky distributorovi (Google Play), podepíšeme tyto balíčky stejnými údaji, které jsme použili na začátku. Náš distributor si pamatuje údaje, které jsme původně použili k odeslání balíčku, a balíček buď přijme, nebo odmítne. Pokud se shodují (pokud je klíč pro odeslání stejný jako ten, který jsme použili na začátku), je balíček přijat a distribuován. V opačném případě není přijat.
- Náš distributor, který ví, že původní balíček a případné budoucí balíčky jsou určitě od nás, balíček distribuuje.
Zprovoznění podepisování kódu pomocí Codemagic
Chceme to nakonec podepsat jako součást našeho pracovního postupu CI/CD, ale zároveň nechceme kontrolovat naše úložiště klíčů a soubor vlastností ve správě zdrojů. Místo toho chceme, aby náš poskytovatel CI/CD sestavil balíček a později ho v procesu sestavování podepsal pomocí námi poskytnutého úložiště klíčů.
Nastavení pomocí Git
Pokud máme zcela novou aplikaci Flutter, můžeme se přepnout do složky a zadat git init
, abychom začali s aplikací používat správu zdrojů.
Ve výchozím nastavení jen vesele zaškrtneme náš soubor úložiště klíčů a soubor vlastností úložiště klíčů, což je z hlediska bezpečnosti špatný nápad.
To byste měli mít hned od začátku
Pokud omylem zaškrtnete soubor vlastností úložiště klíčů a soubor úložiště klíčů a tyto změny odešlete, lidé budou moci tyto soubory kdykoli v budoucnu vytrhnout nahlédnutím do historie systému Git. V budoucnu můžete soubory ze systému Git ručně odstranit nebo můžete úložiště znovu inicializovat bez těchto souborů, ale je lepší je prostě v první řadě nezkontrolovat.
Na konec našeho souboru .gitignore
chceme přidat tyto řádky:
# Don't check in the keystore files or equivalent*.jkskey*.properties
Žádný Java KeyStore (JKS) ani vlastnosti pro podepisování kódu nebudou do správy zdrojů kontrolovány. Jak krásné.
Způsob, aby se build.gradle nepodepisoval při spuštění na CI/CD
Když se váš projekt sestavuje, úložiště klíčů a nastavení nejsou k dispozici. Chceme, aby sestavení stále vytvářelo sestavení pro vydání, i když není podepsané.
Toto je část mého build.gradle
, která to umožňuje:
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 }}
Nastavení Codemagic pro podepisování našich sestavení
V procesu sestavování najděte sekci podepisování kódu Androidu (je v sekci Publish). Vypadá to takto:
Nyní nahrajeme naše úložiště klíčů a nastavíme heslo, alias klíče a heslo klíče (které jsou stejné jako ty, které jsme původně nastavili v našem souboru keystore.properties).
Poté stiskneme tlačítko „Uložit“. Když Codmagic spustí náš proces sestavení, automaticky pro nás vytvoří podepsaný soubor APK nebo App Bundle.
A to je v podstatě vše! S tímto podepsaným APK nebo App Bundle můžete nasadit svou aplikaci do Obchodu Play.
Můžete se podívat do mého repozitáře Git na příklad zde (samozřejmě bez úložiště klíčů a vlastností).
To je vše.
Pokud se stále ztrácíte, neváhejte mi dát vědět na @azimuthapps a já se pokusím pomoci. Může to být frustrující, ale jakmile se vám to podaří, mělo by to v dohledné době fungovat.
Lewis Cianci je softwarový vývojář v Brisbane v Austrálii. Jeho první počítač měl páskovou jednotku. Vývojem softwaru se zabývá nejméně deset let a za tu dobu použil poměrně dost frameworků pro vývoj mobilních zařízení (například Ionic a Xamarin Forms). Po přechodu na Flutter se však už nikdy nevrátí zpět. Můžete ho zastihnout na jeho blogu, přečíst si o dalších neflutterovských věcech na Medium nebo ho možná zahlédnout v nejbližší a nejfajnovější kavárně s ním a jeho drahou ženou.
Další články od Lewise: