アプリケーションの構築は世界中のソフトウェア開発者が共有する熱意であります。 しかし、コード署名を管理するための管理上のオーバーヘッドはしょぼいものです。 どうすれば、最初から正しく行えるのでしょうか。
先に言っておきますが、コード署名は歯がゆくなるほど退屈なものです。 それは、正当な理由があって存在する概念です。 つまり、自分のソフトウェア パッケージが実際に自分のものであることを人々に確信してもらいたいのですよね! しかし、多くの開発者が日常的に苦労していることでもあります。 それはまるで、1年間働いてきて、たくさんの書類に記入しなければならなくなった後で税金を払うようなものです。 Yippee.
Scroll down if you just want to see the step-by-step guide on Android code signing and not interested about why we do this😉
Why we code sign
We sign our package so people download our package from Play Store actually it is know us.これは、PDAのパッケージをダウンロードした人々が、私たちのパッケージであることが分かるようにするためです。 これは、私たちが生成したキーでパッケージに署名することで行います。 署名済みパッケージを Google Play にアップロードすると、最初のパッケージをアップロードするために使用されたキーを記憶し、以降のパッケージが同じキーで署名されていることを確認します。
この目標を達成するために、Android のパッケージ署名では、実際には keytool と呼ばれる Java Development Framework に付属するツールを利用しています。 Keytool はおそらく JDK 自体と同じくらい長い間存在しており、かなり古いものです。 これは、APK または AAB (android app bundle) への署名がなぜこれほどまでに混乱するのか、おそらくその理由のいくつかに関係しています。
Play ストアがコード署名を処理してくれないのですか
私たちは、署名されていないアプリ バンドルをすべて Play ストアに渡して、彼らがそれを解決して署名してくれるという涅槃を求めているような気がしています。 しかし、その論理はすぐに破綻してしまいます。 もしあなたが本を書いたら、他の人にサインしてもらいますか? いいえ、あなたが著者であるため、署名するでしょう。
These days code signing is a lot easier than what it used to be. 常に同じキー (アップロード キー) でパッケージに署名していれば、Google Play が実際にコード署名キーを生成して管理してくれます。
特に進取の気性がある方なら、ここですべてを読んで理解しようと試みることができますが、私は Android の開発を始めて 3 年余りになりますが、悲しいかな、私でさえ完全に理解しているわけではありません。 私が知っているのは、それが壊れると、修正するのが非常に面倒だということだけです。
符号化する方法だけでなく、なぜ符号化するのかも時間をかけて理解しましょう。
コード署名に必要なもの
簡単に説明しますと、以下のとおりです。
- Java Development Kit (JDK) ファイルを作成する;
- アプリ バンドルまたは APK に秘密鍵で署名する;
- build.gradle を変更する;
- パッケージを配布元 (Google Play) に送る。
この記事の最後には、Codemagic でコード署名を有効にする方法も記載されています。
Step-by-step guide for Android code signing
STEP 1: The Java Development Kit (JDK)
Android向けに開発している場合、おそらくこれらはすでにインストールされています。
署名情報を含むJava Key Store (JKS) ファイルを作成する必要があります。 アプリ用の JKS を生成する際、実際にはコンピューター上に秘密鍵を作成しています。 このプライベート キーは、設定したパスワードで保護されます。
コマンド プロンプトから以下を入力して、JKS を取得できます。
keytool -genkey -v -keystore %DESKTOP%/key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias DEVELOPERNAME
私たちは keytool
に対して、Java Key Store を生成してデスクトップに配置するよう指示しています。 このキーは 10,000 日間または約 27 年間有効であり、アプリのライフタイムの間、更新をプッシュできるようにします。 また、エイリアスを設定する必要があります。 4268>
keytool
は途中でさまざまな情報の断片を要求します。
Keystore password – このパスワードは、今後この鍵屋のロックを解除するのに必要です。 このパスワードを紛失すると、復元することはほとんど不可能です。
私たちに関するいくつかの詳細を記入するよう求められます。 これらは、私たちの秘密鍵に関連する詳細情報なので、ある程度関連性があるはずです。 これらのフィールドに何を入れるかはあなた次第ですが、経験則から言うと、あまりクレイジーにしない方がいいでしょう。
これが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?:
注意!
こうすることで、JKSを作成し、そこに自分たちで生成した秘密鍵を入れているのです。
誰かがあなたのJKSと正しい認証情報を持っていれば、その人はあなたやあなたの会社としてパッケージに署名することができるのです。 それを安全に保管し、ソース管理上に置かないでください。
Java Key Store ができたので、これで半分終わったことになります! 4268>
STEP 2: 秘密鍵でアプリ バンドルまたは APK に署名する
さて、先ほど作成した JKS でアプリ バンドルに署名したいと思います。 APK やリリース ビルドに毎回手動で署名することも可能ですが、実際には、flutter build apk --release
を実行すると自動的に正しいアップロード キーでパッケージに署名するように設定する方がよいでしょう。 Flutter のドキュメントでは、ここで Gradle ファイルを更新する方法について説明されていますが、私たちはゆっくりとそれを見ていき、途中で説明します。 49 行目あたりに、次のようにあります。
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 }}
ここで起こっている主なことは、ビルドが debug
keystore で署名されており、リリース ビルドがまだ動作しているということです。 これを変更して、リリースが独自の keystore で署名されるようにしたいのです。 そうすれば、Google Play ストアにアップロードできます。
最初に行うことは、app ディレクトリに key.properties
を作成することです。 これは flutter_app/android/key.properties
に作成します。
key.properties
には、パッケージに正常に署名するために必要なすべての詳細情報が含まれます。
storePassword=The JKS store passwordkeyPassword=The key passwordkeyAlias=The alias for your keystoreFile=Where to look for your keystore file
A quick note on source control
このコードをソース コントロールにチェックする前に考えるべきことです。 悪質な業者が鍵ストアとこれらの資格情報にアクセスし、あなたのアカウントを制御できた場合、マルウェアやその他の悪いものを含む新しいアップデートをアプリにプッシュできる可能性があります。 ほとんどの CI/CD ソリューションでは、これらの詳細を「秘密」として提供できますが、プラットフォームごとに実装が異なります。
STEP 3: まとめ & build.gradle の変更
keystore ファイルを作成し、エイリアスと keystore を保護するパスワードを指定しました。 Google Play アプリ署名を使用している場合 (デフォルトで使用)、生成したキーがアップロード キーとして機能します。 Google Playコンソールからアップロードする最初のパッケージは、このキーで署名されます。 これは、Google に対して、私たちが何者であるかを証明するものです。
意味はわかりますか? Cool, let’s make it sign as part of our Flutter build process.
Modify the build.gradle
Open up flutter_app/android/app/build.gradle
…このように、Flutterのビルドプロセスの一部として署名させます。 31 行目くらいに、次のようなテキストが表示されます:
android { compileSdkVersion 29` lintOptions { disable 'InvalidPackage' }...
Gradle に、キー ストアを見つける場所を教えたいのですが、どうすればいいですか?
def keystoreProperties = new Properties()def keystorePropertiesFile = rootProject.file('key.properties')if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile))}
上記を分解してみましょう…
変数 keystoreProperties
を定義しているところです。 そして、key.properties
が android プロジェクト (Flutter プロジェクトではない) のルートに対して存在するかどうかを確認します。
ビルドが実行されると、key.properties
が読み込まれます。 key.properties
はキーストアの場所を特定し、さらにパッケージに署名するために Java キーストアのロックを解除するのに必要な認証情報を指定します。
Let’s just double check that all our files are in the right spot.
Our modified build.gradle
is in flutter_app/android/app/build.gradle
.This is in the right spot.
Our key.jks
file is in flutter_app/android/app/key.jks
.
Our key.properties
file is in flutter_app/android/key.properties
.
上記について確認したら、flutter build apk --release
を実行でき、署名はうまくいくはずです。
STEP 4: Sending it to Google Play Store
ここでAPKまたはアプリバンドルはPlayストアにアップロードできるようになりました。 署名済みのパッケージで Google Play の署名をオンにしてアップロードすると (デフォルト)、Google はパッケージの署名に使用したキーを認識し、それをアップロード キーとして記憶します。 その後、Googleは独自の鍵でAPKまたはアプリバンドルに署名します。 このアプリの後続のアップデートは、この同じ鍵で署名することが重要です。 Google Play はこのキーを私たちのアップロード キーとして認識し、このキーなしではアップデートをリリースできません。
上記のいずれも理解できません。 4268>
- 私たちは、自分自身を識別するための超秘密の方法を生成します。
- この「パスポート」を持つ誰もが、私たちであることを明確に識別できるため (つまり、あまり抵抗なく私たちになりすますことができる)、金庫 (JKS または Java Key Store) のパスワードの後ろにロックします。 このパスポートにアクセスするには、パスポートが入っている金庫のロックを解除する必要があります (パスワードとエイリアスを Gradle ビルド プロセスに提供することにより)。 ディストリビューターは、初めてパッケージを見たとき、このパッケージに使用した私たちの署名をメモし、そのコピーを取ります。
- 今後、ディストリビューター (Google Play) にパッケージを送信するとき、最初に使用したのと同じ詳細でこれらのパッケージに署名します。 配信元は、私たちが最初にパッケージをアップロードするために使用した詳細を覚えており、パッケージを受け入れるか拒否するかを決定します。 もし一致すれば(アップロードキーが最初に使ったものと同じであれば)、そのパッケージは受け入れられ、配布されます。
- 配信者は、最初のパッケージと将来のパッケージが間違いなく私たちからのものであることを知っているので、パッケージを配布します。
Codemagic でコード署名を動作させる
私たちは最終的に CI/CD ワークフローの一部として署名したいと思いますが、同時にソース管理に対してキーストアとプロパティ ファイルをチェックインしたくないと思います。 その代わり、CI/CD プロバイダーがパッケージをビルドし、ビルド プロセスの後半で、私たちが提供する keystore を使用して署名するようにします。
Setting it up with Git
まったく新しい Flutter アプリがある場合、フォルダに切り替え、git init
を入力して、アプリでソース管理を使用することができます。
デフォルトでは、keystore と keystore プロパティ ファイルに喜んでチェックインしますが、これはセキュリティの観点からは悪い考えです。
You should get this right from the start
keystore properties と keystore ファイルに誤ってチェックインしてそれらの変更点を push すると、将来いつでも Git の履歴を見てそれらのファイルを抜き出すことができるようになってしまうでしょう。 将来 Git からファイルを手動で削除したり、それらのファイルなしでリポジトリを再初期化したりできますが、そもそもチェックしない方がよいでしょう。
.gitignore
ファイルの最後に次の行を追加したいと思います:
# Don't check in the keystore files or equivalent*.jkskey*.properties
No Java KeyStore (JKS) or properties for code signing will be checked in to source control. なんと素敵なことでしょう。
CI/CD で実行するときに build.gradle を署名しないようにする
プロジェクトのビルド中は、キーストアと設定は使用できません。 署名されていないにもかかわらず、リリース ビルドを生成するようにしたいのです。
これを可能にするのが、私の build.gradle
の部分です:
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 }}
Setting up Codemagic to sign our builds
構築プロセスにおいて、Android コード署名セクションを見つけます (Publish セクション内にあります)。 次のようになります:
ここで、キーストアをアップロードし、パスワード、キー エイリアス、およびキー パスワード (keystore.properties ファイルで最初に設定したものと同じ) を設定します。
それから「保存」キーを押します。 Codmagic がビルド プロセスを実行すると、署名済み APK または App Bundle が自動的に生成されます。 この署名済み APK または App Bundle を使って、アプリを Play Store にデプロイできます。
Git リポジトリにある例 (当然、鍵ストアやプロパティはありません) をここで確認できます。
以上です。 うまくいくまではイライラするかもしれませんが、一度うまくいけば、当分の間はうまくいくはずです。
Lewis Cianci はオーストラリアのブリスベンでソフトウェア開発者をしています。 彼の最初のコンピューターにはテープ ドライブがありました。 彼は少なくとも 10 年間ソフトウェアを開発しており、その間にかなりの数のモバイル開発フレームワーク (Ionic や Xamarin Forms など) を使用してきました。 しかしFlutterに転向してからは、もう元には戻れない。 彼のブログにアクセスしたり、MediumでFlutter以外のことについて読んだり、あるいは最寄りの最もファンシーなコーヒーショップで彼と彼の親愛なる妻を見かけたら、ぜひ連絡してみてください。