Mac App Store外で配布するmacOSアプリは、アーカイブを作ってからDeveloper ID署名のアプリとしてエクスポートする。xcodebuildでは、archiveと-exportArchiveの2段階で実行する。
$ xcodebuild -project [プロジェクト名].xcodeproj -scheme [スキーム名] -configuration Release \
-archivePath build/[アプリ名].xcarchive archive
$ xcodebuild -exportArchive -archivePath build/[アプリ名].xcarchive \
-exportPath build -exportOptionsPlist ExportOptions.plist
実行すると、build/[アプリ名].appにDeveloper ID Applicationで署名されたアプリが出力される。実行例はXcode 27.0、macOS 27.0.1のもの。事前に、Developer ID Application証明書がキーチェーンに登録されている必要がある。
- 前の記事: 【Xcode】公証のためにHardened Runtimeを有効にする
- 親記事: GitHubを使い、macOSアプリを署名・公証・自動アップデート付きで公開する
- 次の記事: 【codesign】署名の内容と整合性を検証する
ExportOptions.plistを用意する
エクスポートの設定は、ExportOptions.plistに書く。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>developer-id</string>
<key>teamID</key>
<string>[Team ID]</string>
<key>signingStyle</key>
<string>manual</string>
<key>signingCertificate</key>
<string>Developer ID Application</string>
</dict>
</plist>
各キーの意味は次のとおりである。
| キー | 値 |
|---|---|
method | 配布方法。developer-idは、Mac App Store外でのDeveloper ID配布 |
teamID | Apple DeveloperのTeam ID |
signingStyle | 署名方法。manualは、署名に使う証明書を自分で指定する |
signingCertificate | 署名に使う証明書。名前またはSHA-1ハッシュを指定する |
Team IDは、Apple Developerの「Membership details」で確認できる。
アーカイブを作る
archiveで、ビルドの成果物を.xcarchiveにまとめる。
$ xcodebuild -project [プロジェクト名].xcodeproj -scheme [スキーム名] -configuration Release \
-archivePath build/[アプリ名].xcarchive archive
...
** ARCHIVE SUCCEEDED **
署名の設定がAutomaticのままであれば、アーカイブ内のアプリはApple Developmentの証明書で署名される。
$ codesign -dv --verbose=2 build/[アプリ名].xcarchive/Products/Applications/[アプリ名].app 2>&1 | grep Authority
Authority=Apple Development: [名前] ([ID])
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
配布に使うのは、次のエクスポートで再署名したアプリである。
エクスポートする
-exportArchiveで、アーカイブからDeveloper ID署名のアプリを取り出す。
$ xcodebuild -exportArchive -archivePath build/[アプリ名].xcarchive \
-exportPath build -exportOptionsPlist ExportOptions.plist
Exported [アプリ名] to: [出力先のパス]
** EXPORT SUCCEEDED **
-exportPathに指定したディレクトリには、次のファイルが出力される。
$ ls build
DistributionSummary.plist
ExportOptions.plist
Packaging.log
[アプリ名].app
[アプリ名].xcarchive
[アプリ名].appが、Developer ID署名のアプリである。Packaging.logには、エクスポートの処理のログが記録される。
署名を確認する
エクスポートしたアプリは、Developer ID Applicationで署名されている。
$ codesign -dv --verbose=2 build/[アプリ名].app 2>&1 | grep -E 'flags|Authority|Timestamp|TeamIdentifier'
CodeDirectory v=20500 size=488 flags=0x10000(runtime) hashes=4+7 location=embedded
Authority=Developer ID Application: [名前] ([Team ID])
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=[署名した日時]
TeamIdentifier=[Team ID]
AuthorityにDeveloper ID Applicationが表示され、Timestampが含まれている。flags=0x10000(runtime)は、Hardened Runtimeが有効であることを表す。
署名の整合性は、codesign --verifyで検証できる。
$ codesign --verify --deep --strict --verbose=2 build/[アプリ名].app
build/[アプリ名].app: valid on disk
build/[アプリ名].app: satisfies its Designated Requirement
どの証明書で署名されたかを確認する
同じ名前のDeveloper ID Application証明書が複数あると、codesignのAuthorityでは見分けられない。エクスポート先に出力されるDistributionSummary.plistには、署名に使った証明書の情報が記録される。
$ plutil -extract '[アプリ名].0.certificate' json -o - build/DistributionSummary.plist
{"SHA1":"[SHA-1ハッシュ]","type":"Developer ID Application","dateExpires":"2031\/09\/17"}
SHA-1ハッシュが、security find-identity -v -p codesigningで表示される証明書のハッシュと一致していれば、意図した証明書で署名されている。
同名の証明書が複数ある環境では、ExportOptions.plistのsigningCertificateにSHA-1ハッシュを指定すると、使う証明書を確実に固定できる。
<key>signingCertificate</key>
<string>[SHA-1ハッシュ]</string>
DistributionSummary.plistには、アプリのバージョン、ビルド番号、署名時のentitlementsなども記録される。
参考: 【notarytool】アプリを公証してstaple(公証チケットを添付)する
参考: 【GitHub Actions】CIでだけ署名設定をDeveloper IDに切り替える
