Jump to content

蘋果系統運行著一些現有的最大和最賺錢的軟件應用程序生態系統。理論上,要進入這些生態系統,傳統上需要使用macOS,並加入蘋果開發者計劃(Apple Developer Program)。

如果你想為Apple 操作系統開發應用程序,你可能會使用Apple 的操作系統和Apple 的官方工具進行開發和分發。但對於開源開發人員通常希望以最小的努力分發跨平台應用程序。在整個編程語言生態系統中,你運行的操作系統被抽象為許多應用程序的實現細節。通過創建macOS、iOS 等開發需要直接訪問macOS 和通常高於市場價格的Apple 硬件的要求,蘋果軟件生態系統強加的分發要求是有效的排他性,並阻止利益相關方對進入其生態系統。

在蘋果平台上發佈軟件的一個問題是代碼簽署和公證,即你需要:

1.在應用程序中嵌入加密簽名,有效地證明來自Apple Developer Program 關聯帳戶的真實性。 (這是簽名。)

2.將你的應用程序上傳到Apple,以便他們對其進行檢查,驗證它符合要求,可能還會存儲一個副本。然後,蘋果會發布自己的加密簽名,即公證書,然後需要將其嵌入到正在分發的應用程序上,這樣蘋果的操作系統才能信任它。 (這是公證。)

從歷史上看,這些步驟需要Apple 專有軟件專門從macOS 運行。這意味著,即使你在Rust、Go 等軟件生態系統或Web 平台中,你可以在不直接訪問macOS 的情況下交叉編譯應用程序(測試顯然是另一回事),如果你願意,你仍然需要macOS簽署和公證你的申請。由於默認的安全設置,在macOS上需要有效的簽名和公證。在iOS 等移動平台上,除非你運行的是越獄設備,否則不可能發布未經簽名和公證的應用程序。

如果我不需要macOS來構建我的應用程序,為什麼我要被迫把蘋果設備作為我的軟件發布過程的一部分?為什麼在發布的時候,我必須簽署和公證我的申請,它不能更簡化嗎?

如果能重新實現Apple 代碼簽名,以便開發人員有更多的靈活性和機會將應用程序分發到Apple 的生態系統。其最終目標是擴大Apple 生態系統對更多開發者的訪問。

首先,得益於rcodesign 0.14.0的發布。這是我第一次發布rcodesign 的預構建二進製文件(Linux、Windows 和macOS)。

macOS rcodesign 可執行文件是自簽名的,它由GitHub Actions Linux 運行程序使用YubiKey 獨有的代碼簽名證書進行簽名。

2021年,apple-codesign 項目/Rust crate 發生了很大變化!只需查看更改日誌!

這個項目從tugger-apple-codesign改名而來。

如果你是通過cargo install 安裝的,你需要cargo install --force apple-codesign 來強制Cargo 用另一個crate 中的一個來覆蓋rcodesign 可執行文件。

rcodesign CLI可執行文件仍然存在,而且比以往任何時候都更強大。你仍然可以在Linux、Windows、macOS和任何其他平台上對Apple應用程序進行簽名,你可以在這些平台上編譯Rust程序。

Sphinx 文檔請點擊這裡,這與PyOxidizer 的文檔一起發佈在readthedocs.io 上(因為我使用的是monorepo)。那裡有一些通用文檔,例如有關如何通過將你自己的替代代碼簽名PKI 部署到並行Apple 來選擇性地繞過Gatekeeper 的指南。

支持簽名包、DMG 和.pkg 安裝程序當我去年宣布這個項目時,只有Mach-O 二進製文件和非常簡單的.app 包是可簽名的。即便如此,也有很多微妙的問題。

Rcodesign sign現在可以對更複雜的包進行簽名,包括許多嵌套的包。有報導稱iOS應用包簽名正確。

該工具還支持簽名.dmg磁盤映像文件和.pkg扁平封裝包安裝程序。

已知的簽名限制現在記錄在Sphinx 文檔中。

我相信rcodesign 現在支持對用於Apple 軟件分發的所有主要文件格式進行簽名。

支持Linux、Windows 和macOS 上的公證

蘋果發布了一個名為Transporter的Java工具,可以讓你上傳文物到蘋果進行公證。它們使這個工具可用於Linux、Windows,當然還有macOS。

雖然這個工具不是開源的,但使用這個工具可以讓你在Linux 和Windows 上進行公證,同時仍然使用Apple 的官方工具與他們的服務器通信。

rcodesign 現在支持調用Transporter 並將工件上傳到Apple 進行公證。我們現在支持公證包、dmg 磁盤映像和.pkg 扁平封裝安裝程序包。我已經成功地從Linux 公證了所有這些應用程序類型。

由於支持對所有應用程序類型進行簽名和公證,現在可以在沒有macOS 參與發布過程的情況下發布Apple 軟件。

YubiKey 集成我嘗試盡可能多地使用我的YubiKey,因為存儲在YubiKey 上的密鑰或私鑰可能比位於某個文件系統上的密鑰或私鑰更安全。如果你破解了我的設備,你很可能會獲得我的私鑰。但是你需要物理訪問我的YubiKey 並強迫或強迫我解鎖它,以獲得訪問其私鑰的權限。

rcodesign 現在支持使用YubiKeys 進行簽名操作。

這確實需要默認的智能卡Cargo 功能。因此,如果手動構建,你將需要例如cargo install --features smartcard apple-codesign.

YubiKey 集成來自yubikey 。這個crate 將直接與macOS 和Windows 中內置的智能卡API 對話。所以如果你有一個啟用了YubiKey 支持的rcodesign 構建,YubiKeys 應該可以工作。通過插入YubiKey 並運行rcodesign smartcard-scan 進行嘗試。

YubiKey 集成文檔可以點此查看。

我甚至實現了一些命令來輕鬆管理YubiKey 上的代碼簽名證書。例如,你可以直接在設備上運行rcodesign smartcard-generate-key --smartcard-slot 9c 以生成新的私鑰,然後rcodesign generate-certificate-signing-request --smartcard-slot 9c --csr-pem-path csr.pem將該證書導出到證書籤名請求(CSR),你可以在developer.apple.com 上交換Applie 頒發的簽名證書。這意味著你可以輕鬆創建其私鑰直接在硬件設備上生成且永遠無法導出的代碼簽名證書。以這種方式生成密鑰比將密鑰存儲在軟件庫(比如蘋果的Keychains)中更安全。

遠程代碼簽名我最感興趣的功能是我稱之為遠程代碼簽名的功能。

我在GitHub託管的Linux GitHub Actions運行程序上簽署了一個macOS通用Mach-O可執行文件,使用的YubiKey物理連接到我桌子旁邊的Windows 11設備上。未在計算機之間複製簽名的應用程序。

我有一個調用rcodesign sign --remote-signer 的GitHub Actions 工作流程。我手動觸發了該工作流程,並開始使用瀏覽器觀察近乎實時的作業輸出。 rcodesign sign --remote-signer 打印出一些指令(包括一堵base64 編碼數據的牆)以指示下一步該做什麼。重要的是,它要求其他人運行rcodesign remote-sign 以繼續簽名過程。

該日誌向我們展示了使用YubiKey 進行連接和身份驗證,以及一些關於與遠程服務器對話的狀態更新。

遠程簽名使我能夠從GitHub 運營的GitHub Actions 運行程序簽署macOS 應用程序,同時使用安全存儲在我的YubiKey 上的代碼簽名證書,該證書插入到距GitHub Actions 運行程序數百公里的Windows 設備上。

這裡發生的是2 個rcodesign 進程通過中央中繼服務器橋接的websocket 相互通信。我免費操作一個默認服務器。服務器是開源的,如果你想運行你自己的服務器,你可以使用terrform模塊,希望只需要花幾分鐘時間。當啟動設備希望創建簽名時,它向請求加密簽名的簽名者發送一條消息。然後將簽名發送回發起者,發起者將其合併。

我設計這個特性時考慮到了CI系統的自動發布(比如GitHub Actions)。我想要一種方法,可以簡化應用程序的代碼簽名和發布過程,而不必給CI中的低信任設備無限訪問我的私人簽名密鑰的權限。這可能在許多其他場景中都是有用的。你是否曾經因為沒有蘋果發行的代碼簽名證書而通過電子郵件或下拉框將應用程序發送給別人簽名?現在你有了一個不需要復製文件的替代解決方案。只要你可以看到啟動設備的日誌輸出,或者將輸出傳遞給你(例如通過聊天應用程序或電子郵件),你就可以在另一台設備上遠程簽署文件!

關於遠程簽名安全性Websockets 通過由第三方操作的中央服務器?授予遠程設備訪問權限以對任意內容執行代碼簽名?你的恐懼和懷疑是100% 有道理的:我也會這麼想!

促進遠程代碼簽名的服務會成為一個非常有利可圖的攻擊目標,如果被濫用,它可能被用來強制使用有效的代碼簽名證書的各方簽署不想要的代碼,如惡意軟件。實現這樣的功能有很多很多很多錯誤的方法。

遠程代碼簽名設計和安全注意事項包含了我的一些高級設計目標和安全評估。遠程代碼簽名協議詳細介紹了通信協議,包括所涉及的加密(實際的加密,而不是流行的加密)。關鍵在於協議和服務器的設計使惡意服務器或中間人無法偽造簽名請求。簽名會話在幾分鐘後過期,第三方或服務器無法注入會導致不需要簽名的惡意消息。通過初始握手獲得會話臨時共享加密密鑰,並從那裡使用對稱加密密鑰,因此對等方之間的所有有意義的消息都是端到端加密的。惡意服務器可以做的最糟糕的事情就是進行拒絕服務。

我相信我的遠程簽名實現比許多常見做法更安全,因為今天的常見做法需要復制私鑰並讓低信任度設備(如CI 工作人員)訪問私鑰或者文件在沒有加密監管鏈的情況下被複製以證明不會被篡改。是的,遠程簽名為遠程訪問引入了使用簽名密鑰的向量。但是按照我的意圖進行實踐,遠程簽名可以消除複製私鑰或授予對它們的無限訪問權限的需要。從威脅建模的角度來看,我認為密鑰訪問中的網絡限制使得遠程簽名比現在許多人使用的私鑰管理實踐更安全。

話雖如此,這裡的星號是我實現了我自己的密碼系統來實現端到端消息安全。如果在設計或實現中存在漏洞,密碼系統可能會崩潰,從而帶來對消息偽造的防禦。屆時,惡意服務器或特權網絡攻擊者可能會強迫某人簽署不需要的軟件。但這很可能是損害的程度:對簽名密鑰的脫機攻擊是不可能的,因為簽名需要存在,而且私鑰永遠不會通過網絡傳輸。即使沒有端到端加密,該系統也比將你的私有密鑰作為一個容易被竊取的CI秘密(或類似的)留在周圍更安全。

Apple 鑰匙串支持從0.14 版本開始,我們現在可以提前支持使用存儲在Apple 鑰匙串中的代碼簽名證書進行簽名!如果你在Keychain Access 或Xcode 中創建了Apple 代碼簽名證書,那麼這可能就是你的代碼簽名證書所在的位置。

我拖延了很長一段時間,因為我沒有意識到這有什麼好處:如果你使用macOS,只需使用蘋果的官方工具。但是隨著rcodesign獲得了對遠程代碼簽名的支持,以及其他一些功能,這些功能可以讓它成為所有平台上蘋果工具的有力替代品,我認為我們應該提供這個功能,這樣我們就不會再阻止人們從keychain導出私鑰了。

Apple 的代碼簽名很複雜。 蘋果的工具和rcodesign之間很容易出現細微差別。

rcodesign 現在有print-signature-info 和diff-signatures 命令來轉儲和比較與代碼簽名相關的YAML 元數據,以便更容易地比較代碼簽名實現甚至多個簽名操作之間的行為。

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...