酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

ipaファイルを再署名(resign)する

現在出力しているipaファイルを新しいProvisioning Profileを使って再署名することができます。

利用用途としては、新しいIPAファイルは作成したくないがProvisioning Profileが失効してしまったり対応するUDIDが増えた時に、Provisioning Profileのみを入れ替えたいという時によく使います。

目次

ipaファイルを再署名(resign)する

再署名の方法はいくつかあります。

コマンドラインで再署名する

一番スタンダードな方法です。iOS 4くらいの時代からこの方法で再署名してきた記憶があります。

のちほど紹介するiReSignやiReSignShellも基本的にこの再署名+αの処理をおこなっています。

# ipaを解凍
unzip -d /PATH/unzipdirectory "/APP_PATH/MyApplication.ipa"

cd /PATH/unzipdirectory

# 現在の署名を`enetitlements.plist` として出力する
codesign -d --entitlements :- Payload/MyApplication.app > ../enetitlements.plist

# 署名ディレクトリ(消さなくてもいいけど念のため)
rm -rf ./Payload/MyApplication.app/_CodeSignature

# mobileprovisionファイルを差し替える
cp -p /PROVISIONING_PATH/xxxx.mobileprovision \
    ./Payload/MyApplication.app/embedded.mobileprovision

# 再署名
codesign --force --sign "${CODE_SIGN_ID}" \
    --entitlements ../enetitlements.plist \
    --timestamp=none "./Payload/MyApplication.app/"

# 再圧縮(ipaを作る)
zip -ry "${APP_PATH}" Payload

(2017/5/24追記) この方法は推奨しません。少し前まではこの方法で問題なく再署名できていたのですが、アプリによって再署名に失敗するケースがでてきました。個人的には最新版のiReSignを使うことをオススメします。

GUIツール「iReSign」使って再署名する

ipaファイルの再署名は前述の通りコマンドラインだけでできるので開発者であれば難しいものではありません。ただ、コマンドラインで作業することに慣れていないと倦厭しがちです。また手作業にするとミスが混入してしまいます。

個人的に、オススメなのがGUIで再署名をすることが可能な「iReSign」です。

オリジナルの方はすでにメンテナンスされておらず、現時点での最新環境のmacOS Sierra(10.12.5にて確認)ではentitlement.plistの生成に失敗してしまい正しく再署名できません。

少し面倒くさいのですが、qiaoxueshiさんがforkしたブランチをcloneして、自分でビルドして使いましょう。

iReSignのコマンドライン版「iReSignShell」を使って再署名する

iReSignをコマンドラインで使えるようにしたiReSignShellというクローンもあります(別作者のアプリです)。

iResignShellを使った場合の再署名は下記のようにおこないます。

iResignShell -s "iPhone Distribution: CH3COOH INC." \
    -m /PROVISIONING_PATH/xxxx.mobileprovision 
    "/APP_PATH/MyApplication.app"

JenkinsなどのCIツールを使用している場合、こちらのiResignShellの方が使い勝手が良いでしょう。

ただし、メンテナンスがおこなわれていないのと、本家のiReSignからポーティングしたものですので、macOS Sierraでは正しく動きませんでした。

トラブルシューティング

私自身がipaファイルを再署名するにあたって遭遇したトラブルをメモしておきます。

再署名したipaファイルをインストールすることができるが起動後するにクラッシュしてしまう

1年前にビルドしたAd-Hocバイナリを再署名して使えるようにしてほしいと依頼を受けました。該当のバイナリはタイムスタンプから2016年4月時点のもので古いものではなさそうです。

再署名自体は問題なく成功しました。再署名後のバイナリをiOSデバイスにインストールすることも無事できました。しかし、アプリ起動時にクラッシュしてしまいました。取得できたクラッシュログは以下の通りです。

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001200e1088
Triggered by Thread:  0

Filtered syslog:
None found

Dyld Error Message:
Dyld Message: Library not loaded: @rpath/libswiftCore.dylib
  Referenced from: /var/containers/Bundle/Application/XXXX-XXXX-XXXX-XXXX-XXXX/MyApp.app/MyApp

Dyld Message: Library not loaded: @rpath/libswiftCore.dylibをどのように対処して良いのかわかりません。

Stack Overflowでは証明書とProvisioning Profileを再発行すると再署名に成功したという回答が付いており、実際に質問者もその方法で治ったと書かれていました。

証明書とppは最近更新しているはずなので、ここで書かれている方法では治らない気がしています。

また、Apple社のテクニカルQAでは下記のように掲載されていました。

Swiftのコードが混ざったアプリを実行する際には、Team IDに設定されたSubject Organizational Unit(OU)の証明書を利用して署名しておく必要があるようです。iOS 8以前の環境でビルドしたアプリは再度Archiveしなおせとも書いているように読めました。

結果として、iReSignの最新版*1にて再署名することで表題の問題を解決することができました。

関連記事

xcodebuildについての関連記事はこちらでも確認することができます。

この他にもiOSアプリ開発で見つけたネタや悩んだ内容など紹介しています。Tipsをまとめておりますのでこちらのページをご参照ください。

*1:オリジナルではなくforkされた最新版 https://github.com/qiaoxueshi/iReSign