一、概述
相比於Android系統,iOS對下載到裝置中的軟體有比較嚴格的限制;絕大多數人,只會從AppStore下載App,這也杜絕了很多安全隱患;但是對於iOS開發者來說,需要搞明白很多事情(如:iOS App的簽名原理),甚至需要做一些小動作(如重簽名)來達到自己(友好的)目的。
1、基礎概念
-
摘要演算法:把一個任意長度的位元組串對映 為一定長度的十六進位制的數字串;這個數字串稱為雜湊值。常見有:MD5、SHA1、SHA256、SHA512等
-
對稱加密:加密和解密使用相同金鑰,常見有:DES演算法、3DES演算法和AES演算法等;
-
非對稱加密:加密和解密使用不同金鑰的加密演算法,用公鑰加密的資料,要用私鑰才能解密,用私鑰加密的資料,要用公鑰才能解密;常用加密演算法有:RSA、Elgamal、揹包演算法等;
-
數字簽名(digital signature):
- 是非對稱加密與摘要演算法的結合,用於驗證資料的完整性及不可抵賴性;
- 傳送方對資料計算出摘要資訊,然後用傳送方私鑰加密,得到摘要密文,這就是數字簽名;
- 接收方收到後,利用傳送方的公鑰和非對稱演算法從數字簽名中獲取摘要明文;根據原始內容計算出摘要 和 解密出來的摘要明文進行對比;不一致,說明內容被篡改 or 收到內容不是指定傳送方;
-
數字證書(digital certificate):
- 數字證書數為了保護髮送方公鑰不被偽造而發明的,引入證書中心(Certificate Authority,CA)概念,CA用自己的私鑰,對傳送方的公鑰和一些相關資訊一起加密,生成"數字證書"(Digital Certificate)。
- CA的數字證書中有:簽發者、證書用途、傳送方公鑰、傳送方非對稱加密演算法、傳送方HASH演算法和到期時間等
- 接收方拿到數字證書後,先從數字證書中解密出傳送方公鑰(用的是CA的公鑰和CA解密演算法);然後根據傳送方公鑰去解密數字證書,得到摘要;最後比對原始資料計算出的摘要是否一致。
- CA是第三方機構,CA公鑰是公開的,接收方可以跟別人比對(比如網上查),因此不可能偽造。而傳送方公鑰,是接收方從數字證書中獲得的。
- 數字證書在https協議實現中有重要應用
2、簽名相關的幾個概念
名稱 | 作用 |
---|---|
證書(cer) | 內容是公鑰或私鑰,由其他機構對其簽名組成的資料包。 |
Entitlements | 包含了 App 許可權開關列表 |
CertificateSigningRequest | 本地公鑰 |
p12 | 本地私鑰,可以匯入到其他電腦。 |
Provisioning Profile | 包含了 證書 / Entitlements 等資料,並由蘋果後臺私鑰簽名的資料包。 |
3、iOS包渠道及其簽名機制
-
iOS裝置上App的渠道粗分有AppStore渠道和非AppStore渠道,非AppStore包有:Testflight內測包、In-House 企業內部分發包、Ad-Hoc(相當於企業分發的限制版,限制安裝裝置梳理)和Xcode除錯安裝;(越獄包不在此範圍)。
-
AppleStore中渠道包簽名驗證
- 蘋果官方生成一對公私鑰,在 iOS 系統中內建一個公鑰,私鑰由蘋果後臺儲存。
- App 上傳到 App Store 時,蘋果後臺用私鑰對 App 資料進行簽名(計算出摘要,再私鑰加密);
- iOS 下載這個 App 後,用公鑰驗證這個簽名,如果簽名正確則這個 App 肯定是由蘋果後臺認證的,並且沒有被修改或損壞。
-
非AppleStore渠道包的簽名驗證需要使用雙重簽名機制,保證不被濫用。
二、雙重簽名機制
1、簡介
- 使用兩對公私鑰做加密驗證,分別是 Mac本地的一對公私鑰和 Apple提供的一對公私鑰(私鑰在蘋果後臺,公鑰在每個 iOS 裝置上)。
- 雙重簽名的存在是為了滿足:
- App 需要經過蘋果允許才能安裝;
- 在 Apple 後臺中註冊過的裝置才能安裝,比如在 TestFlight 內測、真機除錯模式下;
- 限制簽名只能對應唯一的 App;
2、重要概念
-
Mac 上執行鑰匙串訪問 -> 證書助理 -> 從證書頒發機構請求證書...,就會在Mac本地生成了一對公私鑰,匯出的 CSR 檔案(
CertificateSigningRequest.certSigningRequest
)就是 Mac 公; -
將CSR 檔案上傳到蘋果後臺,蘋果用Apple私鑰對其簽名,並生成一份包含Mac公鑰資訊 和 蘋果簽名資訊的開發/釋出證書cer;
-
當我們將cer下載並安裝到Mac後,keychain會把CertificateSigningRequest和cer證書關聯起來。在鑰匙串中找到該證書,可以匯出Mac私鑰(
.p12
檔案) -
在蘋果後臺需要配置AppID、可用裝置IDs(企業證書不需要) 和 Entitlements(App 許可權開關列表),對這些額外資訊 和 cer證書使用Apple私鑰簽名,最後蘋果將證書 + 額外資訊 + 簽名組成一個Provisioning Profile檔案(字尾mobileprovision),可下載到Mac上。
Provisioning Profile檔案又被成為描述檔案,安裝好後,存放在~/Library/MobileDevice/Provisioning Profiles路徑下 複製程式碼
3、App簽名和驗證
-
在Mac上編譯完一個App後,Mac先用Mac私鑰對App簽名,並將Provisioning Profile檔案也打包到App中,檔名為embedded.mobileprovision。
-
iOS系統安裝App時,蘋果通過內建在手機中的Apple公鑰驗證embedded.mobileprovision中的簽名是否正確,接著驗證證書中的簽名是否正確。
-
在確保embedded.mobileprovision裡的資料都是蘋果授權以後,就從裡面取出資料,做後續各種驗證,包括
- 用Mac公鑰驗證App簽名
- 驗證裝置 ID 是否在 ID 列表上
- 驗證證書是否過期
- 驗證AppID 是否對應得上
- 驗證許可權開關是否跟 APP 裡的 Entitlements 對應等等。
-
如果別的 Mac 也要編譯後簽名這個 App,就必須要獲取申請生成cer證書那個Mac機器上的私鑰;這個比較簡單,只需要在那臺機器的鑰匙串中找到cer證書,然後右鍵匯出Mac私鑰(
.p12
檔案); -
簡單來說,要在別人裝置上成功編譯成功並將App安裝到裝置中,需要cer證書匯出的**.p12檔案和Provisioning Profile檔案**(描述檔案)
4、補充
- 雙層程式碼簽名是針對開發測試包、In-House 企業簽名、Ad-Hoc 包為例的簽名和驗證的流程,只是企業簽名不限制安裝的裝置數,因此描述檔案中不會有裝置列表,而是一條
ProvisionsAllDevices
記錄。 - 從 App Store 上下載的安裝包,裡面是沒有描述檔案的,但上架之前還是要配置證書、PP 檔案,因為 App ID 和許可權的檢驗還是需要做的。但 App 上傳到 AppStore 以後就跟 PP 檔案沒有關係了,所以我們可以理解為 App Store 上包的簽名驗證採用就是前面說的最簡單的簽名方式,Apple 後臺直接用私鑰簽名 App 就可以了。
三、App重簽名
1、概述
- 重簽名本質是將已釋出/未釋出的包重新簽名為自己的證書和簽名,關鍵點是替換
ipa
內的證書和描述檔案; - 使用codesign工具
2、重簽名方案
-
檢視ipa包是否加殼,只有未加殼的包才可以重簽名。
otool -l app_name.app/app_name | grep crypt # 輸出cryptid為0代表已經砸殼,即解密,為1或者2表示以第1類或者第2類加密方案加密。 複製程式碼
-
檢視本地證書列表並記錄下要用來簽名的證書名,例如”iPhone Distribution: XXXXX (XXX)”
security find-identity -v -p codesigning # 輸出有效的證書列表 複製程式碼
-
建立一個和App同名的工程,從上步得到有效證書列表中,選擇一個,編譯後生成新App;將這個新App裡
embedded.mobileprovision
檔案取出替換iap包中的檔案。 -
刪除ipa包內部不能被重簽名的外掛(PlugIns資料夾 和 Watch資料夾)
-
將ipa包內的所有Framework中Mach-O檔案重簽名(Frameworks目錄下有Framework)
# 命令參考
codesign -fs [證書名稱] [要簽名的檔案]
#如果沒有許可權,執行chmod +x app_name.app/app_name 給Mach-O檔案新增可執行許可權
#Frameworks資料夾裡面的.framework本質還是資料夾,真正要重籤的是.framework裡面的MachO可執行檔案
複製程式碼
-
將ipa包內info.plist的
BundleId
修修改為新App對應的的BundleId
。 -
用命令檢視
embedded.mobileprovision
檔案,找到其中的entitlements欄位,並且複製entitlements欄位和其中的內容。security cms -D -i 「embedded檔案路徑」 複製程式碼
-
新建entitlements.plist檔案,將複製內容拷貝到檔案中,然後將entitlements.plist複製到ipa的同級目錄下。
-
對App進行重簽名,並壓縮成新的ipa包
# 重簽名 $ codesign -fs "iPhone Distribution: XXXXX (XXX)" --no-strict --entitlements=entitlements.plist // --no-strict 不嚴謹的 // --entitlements=entitlements.plist許可權所在檔案是entitlements.plist codesign -fs 簽名證書 --no-strict --entitlements=entitlements.plist app_name.app # 壓縮ipa包 $ zip -r 「輸出的檔名(.ipa)」 Payload/ 複製程式碼
-
將ipa包安裝到手機,若能同時存在兩個應用且能正常執行則表示重簽名成功。
3、防止App被重簽名辦法
- 校驗描述檔案資訊:在啟動時校驗描述檔案資訊與打包時是否一致。例如判斷組織單位: 先記錄證書中的組織單位資訊。
- sysctl檢測是否被除錯,具體可見iOS安全防護之重簽名防護和sysctl反調
4、目的
- 對於大多數iOS開發,瞭解App簽名原理,知道要對App做防止重簽名的保護即可。
- 本人並非從事越獄安全工作;使用重簽名,主要是為了讓測試包可以支援IAP測試,搞過IAP的同學應該明白IAP測試中的痛點: 使用TestFlight or ad-hoc包測試的效率真的會把人逼瘋,企業內測又不支援[坑]