判斷框:適合先排查,不適合立即重建憑證。 Apple 將
errSecInternalComponent視為通用的程式碼簽名錯誤;如果圖形會話能完成簽名、SSH 卻失敗,應先在同一個使用者下比較兩種會話,再依序檢查簽名身份、匹配私鑰、Keychain 狀態與信任鏈,而不是先撤銷或重新申請憑證。這也是 Apple 程式碼簽名排障資料 所支持的排查方向。
最後更新於 2026-08-25;資料核實自 Apple Developer Documentation、Developer Account Help 及 Apple Developer Forums。
這篇文章適合以下讀者:
- 透過 SSH 登入遠端 Mac 後簽名失敗,但圖形介面仍可完成 Archive 的獨立開發者。
- 使用腳本、fastlane 或自託管 Runner 執行無人值守簽名的小型 App 團隊。
- 搬遷打包環境後,已匯入憑證卻仍無法使用 Apple Distribution 或 Developer ID 身份的維護者。
00先保留失敗現場,再建立可比較的基線
不要先執行刪除身份、清空 Keychain、撤銷憑證或重新產生 Provisioning Profile。這些操作可能破壞目前唯一可用的回退路徑,也會讓後續難以判斷原始故障究竟來自會話權限還是簽名資產。
先記錄以下內容,敏感值全部脫敏:
| 要保存的資訊 | 建議記錄方式 | 不應直接公開的內容 |
|---|---|---|
| 實際構建使用者 | whoami、id、工作目錄 |
真實帳戶名稱、主機識別 |
| Keychain 狀態 | security list-keychains、security default-keychain |
Keychain 密碼、完整私有路徑 |
| 簽名身份 | security find-identity -v -p codesigning |
憑證完整指紋、Team ID |
| 失敗階段 | codesign、xcodebuild archive 或導出階段 |
Bundle ID、產品名稱、原始日誌中的令牌 |
同一個待簽名產物、同一個構建使用者與同一個簽名身份,分別在圖形終端和 SSH 執行最小測試。命令中的使用者、路徑、憑證哈希、Team ID、Bundle ID 與產物名稱,應使用以下類型的占位符:
/usr/bin/codesign --force --sign "<SIGNING_IDENTITY>" \
--keychain "/Users/<BUILD_USER>/Library/Keychains/<BUILD_KEYCHAIN>.keychain-db" \
"/path/to/<TEST_APP>.app"
若只有 SSH 或自動化任務失敗,優先看 Keychain 是否鎖定、搜尋路徑是否不同,以及簽名工具是否要求互動授權。若兩種會話都失敗,才把重點移到身份完整性、私鑰和證書信任鏈。Apple 的 Keychain 技術文件 可用來核對 Keychain 的資料與存取模型。
01第一個定位點:分清身份列表與完整簽名資產
security find-identity -v -p codesigning 列出的項目,只能說明系統找到了可被枚舉的簽名身份;它不能單獨證明目前 SSH 工作能使用對應私鑰,也不能證明待簽名 App 的 Provisioning Profile 和 entitlements 相容。
一個可用的簽名身份至少要同時處理以下關係:
| 元件 | 它代表什麼 | 常見錯誤表現 |
|---|---|---|
| 簽名憑證 | Apple 發出的公開身份與公鑰資訊 | 已過期、類型不對、同名重複 |
| 匹配私鑰 | 實際產生簽名所需的私密部分 | 憑證可見,但私鑰不在目前 Keychain |
| 數位身份 | 憑證與對應私鑰可共同使用的完整組合 | 圖形會話可用,SSH 無法授權 |
| Provisioning Profile | 將 App ID、團隊與能力限制綁定到建置 | Archive 或導出階段才失敗 |
| 信任鏈 | 憑證、中間憑證與系統信任關係 | 出現無法建立證書鏈或身份無效 |
可先在構建使用者上下文中執行:
security find-identity -v -p codesigning
security find-certificate -a -c "<CERTIFICATE_NAME>"
security find-key -a -t private
再比較圖形終端與 SSH 的輸出是否一致。若 SSH 找不到私鑰,或私鑰位於另一個 Keychain,這不是重新生成 Apple Distribution 憑證的充分理由。應先確認目前任務實際載入的 Keychain;Apple TN3161 程式碼簽名憑證技術說明 可用於區分憑證內容、公開金鑰與私鑰的角色。
同名身份重複時,不要按名稱猜測正確項目。比較指紋、有效期、憑證類型和私鑰歸屬;若兩個身份都存在,刪除其中一個前,先匯出並保存可回退的數位身份,且確認沒有其他工作依賴它。
02第二個定位點:把 SSH 會話恢復成非互動式環境
當圖形會話成功而 SSH 失敗,優先修復的是「構建使用者能否在非互動狀態存取正確 Keychain」,而不是關閉安全機制。sudo 也不是常規修復方式,因為它可能把檔案擁有者、HOME、Keychain 路徑和簽名身份切換到另一個使用者。
按照實際構建帳戶執行以下流程:
- [ ] 用
whoami和echo "$HOME"確認 SSH 工作沒有切換成管理員或其他帳戶。 - [ ] 用
security list-keychains確認工作使用的 Keychain 路徑,而不是只依賴預設登入 Keychain。 - [ ] 在明確指定的 Keychain 上執行解鎖,密碼透過受保護的 CI Secret 注入,不寫入 Shell 歷史或腳本。
- [ ] 用
security show-keychain-info或同等輸出確認 Keychain 沒有在任務開始後立即重新鎖定。 - [ ] 為實際使用的簽名工具設定最小必要的私鑰存取權限,避免把整個 Keychain 開放給所有程式。
- [ ] 不使用永久暴露 Keychain 密碼、停用系統安全功能或廣泛授權作為長期方案。
- [ ] 在同一個 SSH 工作中重跑最小
codesign,保存成功或失敗輸出。
security unlock-keychain 的具體參數、Keychain 名稱與 CI Secret 管理方式,必須依目標 macOS 環境測試;不能把其他主機的路徑直接複製過來。若需要查找遠端登入和構建權限的基本操作,可參考 NUKCLOUD 的遠端 Mac 使用說明,但簽名身份與 Apple 憑證規則仍應以 Apple 文件為準。
注意: 修改私鑰存取控制會影響所有依賴該私鑰的自動化工作。修改前先記錄原有設定;若修復後圖形會話或其他工作反而失敗,應立即回退權限變更,而不是繼續擴大授權範圍。
03第三個定位點:從最小簽名推進到完整 Archive
最小 codesign 成功,只代表目前產物在該時刻能完成一段簽名;它不代表 Xcode Archive、嵌套 Framework、Extension、entitlements、導出或上傳流程全部恢復。
可按以下順序逐段驗證:
| 驗證層級 | 要檢查的結果 | 失敗時的判斷 |
|---|---|---|
| App 本體 | codesign --verify --deep --strict 能完成 |
優先查身份、私鑰與 Keychain |
| 嵌套程式碼 | Framework、Extension 使用預期身份 | 查嵌套目標的簽名設定 |
| Archive | xcodebuild archive 完成 |
查構建設定、Profile 與 entitlements |
| 導出 | ExportOptions 與發布身份一致 | 查 App Store 用 Profile 和身份類型 |
| 上傳 | App Store Connect 接受產物 | 分開查上傳憑據與簽名鏈 |
Xcode 的簽名設定可能由工程檔、命令列參數或 CI 環境變數共同決定,因此要保存實際 xcodebuild 指令和有效設定,不要只看 Xcode 圖形介面的勾選狀態。可用 Apple Xcode Build Settings Reference 核對相關設定。
若錯誤變成「無法建立證書鏈」,先檢查中間憑證是否存在並由系統信任;若變成「身份無效」或「私鑰缺失」,再依證據選擇重新匯入完整數位身份。Provisioning Profile 則需確認 App ID、團隊、能力和分發用途;Apple App Store Provisioning Profile 建立說明 可用來核對 Profile 的用途,不應用錯誤類型的 Profile 掩蓋 Keychain 問題。
04第四個定位點:用故障後重試驗證無人值守能力
遠端簽名真正的驗收標準,不是某次 SSH 指令偶然成功,而是主機在沒有人工點擊授權視窗的情況下,仍能完成真實 Archive。這一點對使用 iOS 打包伺服器的獨立開發者尤其重要,因為發版時才發現 Keychain 鎖定,通常已經沒有足夠時間重新整理證書鏈。
建議把以下結果寫入環境驗收記錄:
| 狀態 | 必須觀察的結果 | 不合格訊號 |
|---|---|---|
| 圖形會話 | Archive 和導出均可完成 | 本地也無法使用身份 |
| 退出圖形會話 | SSH 初始化後可完成真實任務 | 需要人工解鎖視窗 |
| SSH 重新連線 | 仍使用同一構建使用者與 Keychain | HOME 或 Keychain 路徑改變 |
| 任務失敗後重試 | 初始化步驟可重複執行 | 只有第二次手動處理才成功 |
| 主機重新啟動 | 重新載入身份後可簽名 | 必須先登入圖形桌面 |
如果只有最小測試成功,完整 Archive 仍失敗,應回到失敗階段,不要再次刪除所有證書。若退出圖形會話後必須人工保持桌面登入,則現有打包環境尚未達到無人值守標準;此時可評估使用能持續在線、保留構建使用者與完整權限的遠端 Mac。需要比較不同遠端工作方式時,可先查看 NUKCLOUD 的遠端 Mac 方案,再按工作負載決定是否遷移。
05FAQ:把常見的 SSH 簽名疑問對應到證據
為什麼終端成功,SSH 卻失敗?
兩者可能使用不同的使用者、HOME、Keychain 搜尋路徑或解鎖狀態。圖形會話能取得互動授權,不代表 SSH 工作同樣能存取私鑰。先比較 whoami、security list-keychains 和最小 codesign 輸出,再判斷會話問題或資產問題。
是否應立即重建 Apple Distribution 憑證?
不應立即重建。若圖形會話可簽名,優先檢查 SSH 的 Keychain 鎖定、私鑰存取控制與使用者上下文。只有在憑證過期、私鑰缺失、身份重複或信任鏈確實損壞時,才進入重新導入或輪換路徑;Apple 證書類型概覽 可協助確認身份用途。
怎樣確認憑證和私鑰是匹配的?
不要只看憑證名稱或 find-identity 的列出結果。應在實際構建使用者下確認憑證和私鑰位於可用的同一 Keychain,並用最小 codesign 測試驗證實際存取。若需要重新下載或管理 Profile,應先保存現有可用資產,並參照 Apple Profile 編輯、下載與刪除說明。
06結論:先修會話,再決定是否更換資產
codesign errSecInternalComponent 不等於 Apple Distribution 憑證已經損壞。對遠端 Mac 而言,最可靠的順序是保留現場、比較圖形會話與 SSH、核對完整簽名身份、恢復非互動式 Keychain 存取,再用退出登入、重新連線、失敗重試和主機重啟完成真實 Archive 驗收。
如果目前方案必須長時間保持人工圖形會話、依賴某位維護者手動解鎖,或把簽名 Keychain 放在不穩定的臨時環境中,問題就不只是一次錯誤:它會增加發版等待、權限暴露和故障恢復成本。相較之下,具備完整權限與持續在線能力的 NUKCLOUD 遠端 Mac,更適合用來建立可重複的 SSH 簽名和 iOS 打包環境;若只是臨時測試、短期 Archive 或驗證現有腳本,租用環境也比專門購置一台 Mac 作為打包機更容易控制投入。需要時可從 NUKCLOUD 的遠端 Mac 訂購方案開始評估,並先以一次完整的無人值守驗收作為遷移門檻。