どうも亀山です。急に雪が降ってきました。気温も低いので、風邪などにお気をつけください。
今回は、Mac アプリを CI でビルドするときに証明書周りで発生したエラーを調べる中で知った p12 ファイルの仕組みについて説明します。
p12 ファイルはキーチェーンアクセスから書き出すことができる、秘密鍵を受け渡すためのファイル形式です。iOS 開発者にはおなじみです。
CI で Mac アプリをビルドして署名を行うために、security import
コマンドを使って秘密鍵をインポートする下記のスクリプトを書きました。Base64化したバイナリからファイルを生成してインポートするというコードを繰り返しています。それぞれ証明書2つと秘密鍵2つ分あります。
set -ex security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security set-keychain-settings -t 3600 -u $KEYCHAIN_PATH security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH echo "$DEVELOPER_ID_APPLICATION_KEY_BASE64" | base64 --decode > developer_id_application.p12 security import developer_id_application.p12 -k $KEYCHAIN_PATH -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign -T /usr/bin/pkgbuild rm developer_id_application.p12 echo "$DEVELOPER_ID_INSTALLER_KEY_BASE64" | base64 --decode > developer_id_installer.p12 security import developer_id_installer.p12 -k $KEYCHAIN_PATH -P $CERTIFICATE_PASSWORD -T /usr/bin/codesign -T /usr/bin/pkgbuild rm developer_id_installer.p12 echo "$DEVELOPER_ID_APPLICATION_CER_BASE64" | base64 --decode > developer_id_application.cer security import developer_id_application.cer -k $KEYCHAIN_PATH -T /usr/bin/codesign -T /usr/bin/pkgbuild rm developer_id_application.cer echo "$DEVELOPER_ID_INSTALLER_CER_BASE64" | base64 --decode > developer_id_installer.cer security import developer_id_installer.cer -k $KEYCHAIN_PATH -T /usr/bin/codesign -T /usr/bin/pkgbuild rm developer_id_installer.cer security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
環境構築のために用意した p12 ファイルでは上記のエラーは出なかったのですが、本番用の p12 を使ったとき以下のようなエラーがでました。
security: SecKeychainItemImport: The specified item already exists in the keychain.
どうやら cer ファイル (証明書) をインポートする際に、すでに証明書が存在するというエラーのようです。これは p12 に同じ証明書が含まれていたために発生しました。
対応方法
証明書を含まない p12 ファイルを書き出すか、cer のインポートを行わないようにします。通常、証明書を含んだ p12 ファイルを使っていると思うので cer のインポートは必要ないでしょう。
証明書の確認
p12 に証明書が含まれているかどうか下記の openssl
コマンドで知ることができました。
openssl pkcs12 -info -in 証明書.p12 -nokeys -legacy
証明書が入っている場合
キーチェーンアクセスで見ると >
マークが付いていて証明書と紐づけされています。これを右クリックで ...を書き出す
を選択して p12 ファイルを生成すると、証明書が同梱された p12 になります。
前述の openssl コマンドで確認すると証明書の情報が取得できます。
MAC: sha1, Iteration 1 MAC length: 20, salt length: 8 PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048 Certificate bag Bag Attributes friendlyName: Developer ID Installer: covelline, LLC. (K45ES832VB) localKeyID: subject=UID = K45ES832VB, CN = "Developer ID Installer: covelline, LLC. (K45ES832VB)", OU = K45ES832VB, O = "covelline, LLC.", C = US issuer=CN = Developer ID Certification Authority, OU = Apple Certification Authority, O = Apple Inc., C = US -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- PKCS7 Data Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
証明書が入っていない場合
キーチェーンアクセスで見ると >
マークが付いておらず、証明書と紐づけされていない事がわかります。キーチェーンアクセス上で証明書を削除すると秘密鍵だけが残り、この状態になります。書き出すと証明書が同梱されていない p12 になります。
先程と同様に openssl コマンドで証明書の情報を取得しようとすると、何も出てきません。
MAC: sha1, Iteration 1 MAC length: 20, salt length: 8 PKCS7 Data Shrouded Keybag: pbeWithSHA1And3-KeyTripleDES-CBC, Iteration 2048
まとめ
security import
コマンドで p12 ファイルをインポートすると、同梱された証明書が一緒にインポートされます。cer ファイルをインポートする際に重複するとエラーになります。キーチェーンアクセスで秘密鍵を書き出す際に、証明書が紐づけられていると証明書が同梱された p12 ファイルになります。openssl
コマンドで p12 に証明書が同梱されているか確認できます。