Edited at

iOSアプリの署名を付け替える

More than 5 years have passed since last update.

業務で iOSアプリの開発をしていると、品質保証のためのテストや第三者検証のために、事前にデバイス登録をした機器にだけインストールできる AdHoc配布用の ipaファイルをテストチームにリリースすることが多いと思います。この ipaファイルは、AdHoc専用の証明書を使ってデジタル署名を行って作成します。

一方、実際に AppStoreに出す時は、Store用の証明書で署名を付けることになります。

AdHoc用の ipaを使ってテストを回し、これが全部終わって出荷可能の判断がくだされた後、Store用にビルドをしなおして Storeに上げる、という運用をしていることもあるでしょう。

もちろんこの場合も「全く同じソースコードベース」で「全く同じビルド設定」でビルドをして、Provisioning Profile と署名用証明書だけが異なるようにすれば理論的には問題ありません。ソースコードだけでいえば、Subversion や Git などのSCMを使っていれば、同じコードベースからのビルドであることはほぼ保証できるでしょう。

ビルド設定についてはどうでしょう。異なる署名でビルドする為にビルド構成(Debug, Release の他に Release_For_Storeを作るとか)を増やしたり、対応するSchemeを増やしたりすることになります。しかしこの方法だと、ビルド設定を変える必要が生じた時に忘れずに Release と Release_For_Store の両方に同じ変更を加える必要がでてきたりして、 人為ミスが入りこむ余地が生じ、メンテナンスリスクが存在します。

そうではなく、 Store用の署名をした ipaをベースに、署名だけを AdHoc用に付け替えることができれば、テスト対象にしたipaと、実際に Storeにアップロードする ipaの実行バイナリ同一性を担保できます。

ここでは、その方法を説明してみます。


Step1:Store用署名をした ipaファイルを zip展開する

% unzip TheApplication.ForStore.ipa

ipa ファイルは実際にはzip圧縮されたデータですので、まずはこれを展開します。展開すると Payload という名前のディレクトリが出来るはずです。このディレクトリの中に、実際のアプリケーションパッケージ(ここでは Payload/TheApplication.app)があり、署名はそのパッケージ全体に対して付されています。


Step2:アプリケーションパッケージの中の Provisioning Profileを置き換える

% cp ForAdHoc.mobileprovision Payload/TheApplication.app/embedded.mobileprovision

アプリケーションパッケージの中にはビルド時に参照した Provisioning Profileも格納されています。署名を付け替えるのであれば、この Provisioning Profileに紐付けられた証明書と整合してなければ最終的に実機でアプリを起動できません。よって、署名を付け替える前に AdHoc配布用の Provisioning Profileのファイルで上書き置換をする必要があります。ファイル名は embedded.mobileprovisionという名前決め打ちです。


Step3:署名をし直す

% codesign --force --sign 'iPhone Distribution: MyCompany ForAdHoc (XXXXXX)' --resource-rules 'Payload/TheAppliation.app/ResourceRules.plist' 'Payload/TheApplication.app'

codesignコマンドを使って署名をし直しましょう。--force オプションはすでに署名がされていても、それを消して署名を上書きするためのオプションで、今回は必須です。--resource-rules オプションは署名の際に参照されるルールファイルの指定で、これもアプリケーションパッケージの中に格納されています。

なお、署名に使う証明書の識別子を --sign オプションの引数に渡しますが、当該マシンに入っていて、署名に使うことができる証明書(証明書に対応する秘密鍵も存在している状態のもの)の識別子リストは、下記のコマンドで一覧を得られます。(今回の例では仮に iPhone Distribution: MyCompany ForAdHoc (XXXXXX)という識別子を想定しています)

また、securityコマンドではなく、キーチェーンアクセスからGUI上で確認することもできます。

% security find-identity -p codesigning -v


Step4:圧縮&アーカイブして AdHoc用 ipaファイルにする

% zip -ry TheApplication.ForAdHoc.ipa Payload

Payloadディレクトリを zip圧縮して AdHoc用ipaを作ります。ダイナミックリンクライブラリなどによっては パッケージの中に相対参照のシンボリックリンクファイルが存在する可能性があるので、 zipコマンドの -y オプションを念の為に付けています。自分のアプリでは不要であればこのオプションは付けなくてもよいでしょう。


署名付け替えのステップは以上です。

私の現場では、これをさらに Jenkinsに組みこみ、普段は AdHoc用の ipaだけが生成されるが、任意のタイミングで Store用/AdHoc用両方を生成できる仕組みも構築しています。

Jenkinsのパラメータ付きビルドの仕組みを使って、必要な時だけ署名用証明書の秘密鍵をアップロードすることで実現しているのですが、これについてもいずれ機会があれば書いてみたいと思います。