@[TOC](IOS 逆向開發(三)應用簽名)
1. 數字簽名
- 什么是數字簽名?
- 數字簽名(digitally signed):先舉個栗子:老外喜歡用支票,支票上面的簽名能夠證明這玩意是你的.那么數字簽名顧名思義,就是用于鑒別數字信息的方法.這個是個很形象的說法。在IOS app的數字簽名:就是將原始數據通過Hash算法得到原始的hash值,然后通過非對稱加密算法RSA加密hash值,得到最終的加密數據,這個過程就叫做數字簽名。
- 數字簽名(又稱公鑰數字簽名、電子簽章等)是一種類似寫在紙上的普通的物理簽名,但是使用了公鑰加密領域的技術實現,用于鑒別數字信息的方法。一套數字簽名通常定義兩種互補的運算,一個用于簽名,另一個用于驗證。
- 數字簽名,就是只有信息的發送者才能產生的別人無法偽造的一段數字串,這段數字串同時也是對信息的發送者發送信息真實性的一個有效證明。
- 想要證明數字信息(也就是二進制數據,計算機里面的任意數據)的有效性,那么使用什么方式最合適呢?
- 在上一篇博客“IOS 逆向開發(二)密碼學 HASH” 中有講到HASH算法專門用來做文件數據的識別.那么在網絡數據傳遞的過程中,我們可以將明文數據,和數據的HASH值一起傳遞給對方.對方可以拿出HASH值來進行驗證.
- 但是在這個過程中,如何做到數據的保護呢?
明文數據和HASH值如果直接傳遞就有都被篡改的風險.所以這里我們要對數據進行加密.明文數據有時會比較大,不適合使用RSA非對稱加密算法,那么數據的HASH值是比較小的.這個數據是用于校驗的,它完全可以使用RSA來加密.- 所以在數據傳遞的時候,我們將明文數據加上通過RSA加密的校驗數據一并傳遞給對方.那么這個通過RSA加密的校驗數據,我們稱之為簽名.
- 通過下圖,可以弄明白數字簽名是個什么過程?
1.1 數字簽名過程:
- 首先傳遞數據時會將原始的數據和數字簽名一起發送
- 對方拿到數據后,先進行校驗.拿到原始數據,通過同樣的HASH算法得到數據的HASH值.
- 然后通過非對稱加密,將數字簽名中的校驗HASH值解密出來.
最后對比兩個HASH值是否一致.這樣可以很好的判斷數據是否被篡改!
數字簽名驗證過程
- 數字簽名驗證過程
數字簽名技術是將摘要信息用發送者的私鑰加密,與原文一起傳送給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,然后用Hash函數對收到的原文產生一個摘要信息,與解密的摘要信息對比。如果相同,則說明收到的信息是完整的,在傳輸過程中沒有被修改,否則說明信息被修改過,因此數字簽名能夠驗證信息的完整性。
1.2 客戶端,服務器簽名驗證過程:
-
如果客戶端向服務器發生數據時不做任何處理,可能會遭到中間人的竊取攻擊,后果如何嚴重就不說了。那么我們如何防止中間人攔截,或者檢查數據是否被篡改呢?
發送數據 直接用RSA(RSA加密原理)進行加密應該是不滿足我們的需求,RSA只適合對小數據進行加密,我們知道驗證數據的完整性可以用Hash(Hash概述)來驗證,可以對數據進行Hash,把Hash值和原始數據一起打包發送給服務器,服務器將原始數據進行Hash,得到的hash值和客戶端發送的Hash值做對比,如果一致則保證數據有效性。但是這樣會有安全隱患,如果中間人篡改了客戶端發送的數據,當然也可以修改客戶端發送的Hash值,所以這樣操作不可行。
這時我們可以用RSA來對hash值進行保護,此時客戶端發送原始數據,和經RSA加密后的該數據的hash值。
服務器對RSA加密的數據進行解密,得到原始數據的hash值,接下來對原始數據進行通過同樣的Hash算法,將得到的Hash值和解密后的Hash值做對比,如果一致則保證數據有效性,整個過程中,如果解密的Hash值和原始的Hash值不一致,或者無法解密RSA的數據,說明數據被篡改了。
-
驗證數據是否被篡改的過程如下:
驗證數據是否被篡改
2. 代碼簽名
- 什么是代碼簽名?
代碼簽名: 是對可執行文件或腳本進行數字簽名.用來確認軟件在簽名后未被修改或損壞的措施。和數字簽名原理一樣,只不過簽名的數據是代碼而已.代碼簽名就是用來校驗我們的可執行文件的
- 作為IOS開發人員,為什么需要理解代碼簽名的原理?
- iOS工程師用于從本地計算機上安裝的Xcode部署iOS應用程序的日子已經一去不復返了。公司正在采用DevOps和CI / CD來構建軟件,因此所有構建都需要自動化,無需任何人工或GUI交互。
- 由于Xcode的代碼簽名失敗,開發人員試圖通過重新生成和修復證書和配置文件來修復代碼簽名問題,因此浪費了數千個開發人員時間。
- 像Fastlane這樣的第三方工具使iOS開發人員更容易構建腳本。然而,在Apple對底層技術進行更改后,Fastlane不斷破壞,開發人員花費數小時,數天和數周來修復損壞的部署腳本。在某些情況下,工程師必須等到Fastlane實施新的更改。
- 如果您是iOS開發人員/工程師,并希望一生成為iOS工程師,那么您無需了解這些內容。但是,如果您想在職業生涯中成長,那么您必須詳細了解底層工具,技術和整個iOS生態系統。如果您不了解這些底層技術,無論您的iOS開發技能有多好,您都不會獲得iOS技術主管,iOS技術架構師或類似角色。作為技術架構師,您應該能夠快速修復代碼簽名或類似的基礎架構相關問題,而無需依賴Xcode或其他第三方工具。
2.1 簡單的代碼簽名
- 代碼簽名的產生背景
- 在iOS出來之前,以前的主流操作系統(Mac/Windows)軟件隨便從哪里下載都能運行,系統安全存在隱患,盜版軟件,病毒入侵,靜默安裝等等.
- 那么蘋果希望解決這樣的問題,要保證每一個安裝到 iOS 上的 APP 都是經過蘋果官方允許的.
- 要做到上述目的,就需要代碼簽名。
- 怎樣保證安裝的每一個APP都是經過蘋果官方允許的?
- 如果要實現驗證.其實最簡單的方式就是通過蘋果官方生成非對稱加密的一對公私鑰.
- 在iOS的系統中內置一個公鑰,私鑰由蘋果后臺保存,我們傳APP到AppStore時,蘋果后臺用私鑰對APP數據進行簽名,
- iOS系統下載這個APP后,用公鑰驗證這個簽名,若簽名正確,這個APP肯定是由蘋果后臺認證的,并且沒有被修改過,也就達到了蘋果的需求:保證安裝的每一個APP都是經過蘋果官方允許的.
- 整個過程很簡單,這樣就保證了蘋果安裝的每一個APP都是經過蘋果官方允許的。對于大部分普通用戶而言,這樣一個數字簽名就解決了安全隱患問題,但是實際上iOS設備安裝APP并不是只有App Store這一個渠道,比如對于我們iOSer來說,我們在開發APP時還在真機調試,當然蘋果還開放了企業內部分發的渠道,這時就無法通過簡單的代碼簽名來滿足這些需求了。
- 要實現這些要求,需要一種更好的機制,這就是接下來要講的雙向代碼簽名技術
2.2 iOS的雙層代碼簽名
- 雙層代碼簽名的產生背景
- 如果我們iOS設備安裝APP只從App Store這一個入口這件事就簡單解決了,沒有任何復雜的東西,一個數字簽名搞定.
- 但是實際上iOS安裝APP還有其他渠道.比如對于我們開發者iOSER而言,我們是需要在開發APP時直接真機調試的.而且蘋果還開放了企業內部分發的渠道,企業證書簽名的APP也是需要順利安裝的.
- 蘋果需要開放這些方式安裝APP,這些需求就無法通過簡單的代碼簽名來辦到了.
- 蘋果爸爸使用雙層簽名技術來實現以下需求:
(1)安裝包不需要上傳到App Store,可以直接安裝到手機上.
(2)為了保證系統的安全性,又必須對安裝的APP有絕對的控制權
(3)經過蘋果允許才可以安裝
(4)不能被濫用導致非開發APP也能被安裝
2.2.1 雙層代碼簽名原理
首先這里有兩個角色.一個是iOS系統 還有一個就是我們的Mac系統.因為iOS的APP開發環境在Mac系統下.所以這個依賴關系成為了蘋果雙層簽名的基礎.
我們使用的xcode只需要有一個證書,就可以幫我們把ipa安裝到手機中。
xcode 在申請證書的時候,在Mac系統中生成非對稱加密算法的一對公鑰\私鑰(你的Xcode幫你代辦了).這里稱為公鑰M 私鑰M . M = Mac
- 蘋果自己有固定的一對公私鑰,跟之前App Store原理一樣,私鑰在蘋果后臺,公鑰在每個iOS系統中.這里稱為公鑰A , 私鑰A. A=Apple,
- 把公鑰M 以及一些你開發者的信息,傳到蘋果后臺(這個就是CSR文件),用蘋果后臺里的私鑰 A 去簽名公鑰M。得到一份數據包含了公鑰M 以及其簽名,把這份數據稱為證書。
- 如上圖所示,證書雙向簽名驗證流程:
- 我們Xcode找蘋果服務器去要證書,這個過程利用了一個csr文件,其中這個csr文件中有個核心的東西叫公鑰M 。xcode通過csr文件將mac電腦里的公鑰M 發送給蘋果服務器。
- 蘋果服務器收到csr文件后,對公鑰M進行簽名,也就是使用蘋果服務器自己的私鑰A進行非對稱RSA加密。本身這個公鑰M就不大,所以不會很耗時。加密后就得到一個證書。這個證書就是被私鑰A加密過后的一個文件,里面包含公鑰M 。這個證書就是我們的開發者證書。
- Xcode通過Mac電腦上的私鑰M 對我們的app進行簽名。只要我們通過xcode 進行command + B 進行bulid就會有這么一個過程。本地的私鑰m也就是我們的p12文件。
- Xcode幫我們打包簽名的時候,會同時將證書一起打包。
- 在我們安裝ipa包的時候,蘋果會檢查證書,查看證書的頒發機構是否是蘋果。如果不是蘋果頒發的證書,就不能安裝。
- iphone手機用證書里面攜帶的蘋果服務器給的公鑰A對ipa包里面的證書進行解密。如果能夠成功解密,說明是蘋果頒發的證書,如果不是蘋果頒發的,則肯定無法進行解密。
- 接下來就需要驗證app,用公鑰A解密證書得到公鑰M。這樣用公鑰M就能對app進行驗證了。
- 在開發時,編譯完一個 APP 后,用本地的私鑰 M(今后你導出的P12) 對這個 APP 進行簽名,同時把第三步得到的證書一起打包進 APP 里,安裝到手機上。
在安裝時,iOS 系統取得證書,通過系統內置的公鑰 A,去驗證證書的數字簽名是否正確。
驗證證書后確保了公鑰 M 是蘋果認證過的,再用公鑰 M 去驗證 APP 的簽名,這里就間接驗證了這個 APP 安裝行為是否經過蘋果官方允許。(這里只驗證安裝行為,不驗證APP 是否被改動,因為開發階段 APP 內容總是不斷變化的,蘋果不需要管。)
-
雙層代碼簽名總的流程圖
雙層代碼簽名總的流程圖 上面的雙向代碼簽名的過程,已經可以保證開發者的認證,和程序的安全性了。但是,你要知道iOS的程序,主要渠道是要通過APP Store才能分發到用戶設備的,如果只有上述的過程,那豈不是只要申請了一個證書,就可以安裝到所有iOS設備了?
上面的流程能驗證安裝的ipa是蘋果允許的,但是無法驗證ipa的安裝行為。
為了防止濫用,蘋果再加了幾個限制,主要是通過描述文件來限制安裝的設備數量。
接下來我們需要了解一下什么描述文件。
3. 描述文件
3.1 描述文件(Provisioning Profile)
- 什么是描述文件?
- 蘋果官方Xcode對Provisioning Profile的解釋是解釋是:A provisioning profile is a collection of digital entities that uniquely ties developers and devices to an authorized iPhone Development Team and enables a device to be used for testing.
- 描述文件(Provisioning profile)一般包括三樣東西:證書、App ID、設備。當我們在真機運行或者打包一個項目的時候,證書用來證明我們程序的安全性和合法性
Provisioning Profile在這里就起到了一個對設備和開發者授權的作用,他將開發者賬號、證書、entitlements文件以及設備進行了綁定。- 在開發過程中,Xcode 8及后續版本默認情況下會自動幫我們管理Provisioining Profile,自動下載的Provisioning Profile都被存放在
~/Library/MobileDevice/Provisioning\ Profiles/
路徑下,以UUID格式命名。直接拖拽下圖中的齒輪圖標到Finder中也可以將其復制出來。
- 前面我們講到了,通過簡單的代碼簽名的方式,是無法解決蘋果的安全需求的,那么蘋果是如何做到防止申請一個證書可以安裝到所有設備上這個問題的呢?
- 蘋果加了兩個限制:
(1)在蘋果后臺注冊過的設備才可以安裝.
(2)簽名只能針對某一個具體的APP.- 蘋果還想控制App里面的iCloud/PUSH/后臺運行/調試器附加這些權限,所以蘋果把這些權限開關統一稱為Entitlements(授權文件).
- 此外蘋果將這個Entitlements文件放在了一個叫做Provisioning Profile(描述文件)文件中.描述文件是在AppleDevelop網站創建的(在Xcode中填上AppleID它會代辦創建),Xcode運行時會打包進入APP內.
- 作為IOS開發者都知道一個規則:使用CSR申請證書時,我們還要申請一個東西: 就是描述文件
-
在xcode工程里面,我們要真機調試肯定需要通過xcode從蘋果服務器下載描述文件,如下圖:
Xcode文件中的描述文件 描述文件除了包含appid等信息外,還包含了蘋果服務器用私鑰A加密的證書,證書里面含有mac傳給服務器的公鑰M .
生成描述文件的流程
- 生成的這個描述文件里面就是 可以安裝的設備有哪些.. APP的ID是什么.. 權限是些什么!
- 在開發時,編譯完一個 APP 后,用本地的私鑰M對這個APP進行簽名,同時把從蘋果服務器得到的 Provisioning Profile 文件打包進APP里,文件名為embedded.mobileprovision,把 APP 安裝到手機上.
- 我們可以利用
$security cms -D -i embedded.mobileprovision
命令查看Provisioning profile內容,這些Xcode
創建的Profile
文件都存放在~/Library/MobileDevice/Provisioning Profiles/
目錄下
-
我們可以通過MachOView查看我們mach-o可執行文件
code Signature - 我們可以在終端用
security cms -D -i + [名稱]
命令查看描述文件里面的信息,我們會發現,描述文件是一個plist文件
-
上述紅框里面的就是可執行文件的
描述文件內容2 從上面分析可以看出描述文件是一個xml格式的plist文件,下面我們對關鍵一些屬性做一些說明。
DeveloperCertificates: 允許使用的開發者證書,這是一個列表,一般包含生成這個Provisioning Profile文件時,當前開發者賬號下所有有效的Development證書,以base64格式保存,使用base64解碼之后就可以得到DER格式的開發者證書。通過計算每個證書的sha1值,可以看出,前文中新申請的證書,就在這個列表中
Entitlements: 允許使用的權限列表,實際在App中使用的權限必須是這個列表的子集,否則安裝時會無法通過校驗而失敗。如果曾經開啟過某個功能,Xcode自動更新了Provisioning Profile,后來又關閉它,Xcode并不會將其從Provisioning Profile中刪去,如上圖中的com.apple.developer.team-identifier。
ProvisionedDevices: 允許安裝的設備列表,如果目標設備的UUID不在這個列表中,會安裝失敗。對于這一項,普通開發者證書和企業級開發者證書的待遇是不同的。普通開發者證書使用Provisioning Profile的方式安裝App到設備,只是出于測試和調試的需要,因此Apple只允許最多注冊100臺用于測試的設備,否則開發者就可以以測試的名義任意任意分發自己的App了。而對于企業級開發者來說,本身就有任意安裝的需求,因此在分發時,這一項會被ProvisionsAllDevices取代,代表授權任意設備。
這些信息中有任何變動的時候,比如開發者證書有新增或者失效,在Capabilities中啟用了當前App從未使用過的新功能,或是將新的iPhone連接到Xcode用于測試,Xcode都會自動重新申請Provisioning Profile。
每次我們新建項目其實會生成一個描述文件,選擇運行到手機上, 我們只需要編譯一下,在APP包里面就可以看到.
- Provisioning Profile會被內置在App中,置于App根目錄下的embedded.mobileprovision。安裝App時如果簽名校驗通過,這個文件會自動被拷貝到iOS設備的/Library/MobileDevice/Provisioning\ Profiles/路徑下。由于該文件已被Apple官方簽名,系統可以無條件信任它,并用它來校驗App的簽名、權限,以及本機的UUID等是否滿足來自官方的授權。通過這種方式,間接信任了使用開發者證書簽名的App,讓iOS設備可以運行非蘋果官方簽名的App。
- 假如你有一臺越獄的設備,查看任意一個從AppStore上下載下來的App,里面都不會有embedded.mobileprovision這個文件,因為經過Apple重新簽名以后,設備就不再需要它了。
其實我們開發過程中經常接觸到代碼簽名,只是我們都是通過xcode幫我們自動完成了這些工作,所以一般對代碼簽名的原理不是很熟悉。
回想一下,當我們完成開發后,會使用 Xcode 的 Archive(存檔) 的功能進行打包,當我們點擊了 Archive 以后,Xcode 就會對我們的代碼進行編譯和鏈接,最終產生一個后綴為.app文件(嚴格意義上來說這是一個文件夾,是 Mac 上的包文件,終端里頭是把這個文件當做文件夾對待的)。然后 Xcode 會把對應的mobileprovision文件拷貝到 APP 文件中(這個文件就是我們在前面配置 provision profile 后下載下來的文件),這一步的詳情可以在 Archive 的 log 中的『Process product packaging』這一步中看到;再之后,Xcode 會使用codesign這個命令對 APP 文件進行簽名。
如果我們有多個 Signing Identity,我們也可以在工程『Build Settings』選項中進行配置
-
一個沒有被簽名的 APP 文件的結構類似這樣:
未簽名的app結構 codesign 在對 APP 文件進行簽名的時候,會把對應的簽名直接添加到二進制文件的內部,而針對資源文件則是利用一個叫做 『CodeResources』的 plist 文件把對應的資源文件和數字簽名進行記錄。簽名結束后的 APP 文件的內容如下:
- 完成簽名后,我們可以使用 Xcode 打包生成對應的 ipa ,方便之后安裝到設備上。
-
此外,我們可以通過Xcode來查看內容:
描述文件內容 Provisioning profile
本身也是通過簽名認證的,所以別想著你可以更改里面的東西來達到擴充權限\設備的目的.只有老老實實的去網站向Apple申請一份權限更多\設備更多的profile。
3.2 授權文件(Entitlements)
Entitlements
沙盒(Sandbox)技術是iOS安全體系中非常重要的一項技術,他的目的是通過各種技術手段限制App的行為,比如可讀寫的路徑,允許訪問的硬件,允許使用的服務等等,即使應用出現任意代碼執行的漏洞,也無法影響到沙盒外的系統。
在這里插入圖片描述
通常所說的Entitlements(授權文件),也就是指iOS沙盒的配置文件,這個文件中聲明了app所需的權限,如果app中使用到了某項沙盒限制的功能,但沒有聲明對應的權限,可能運行到相關的代碼時會直接Crash。
全新的iOS工程中是沒有這個文件的,如果在Capabilities中開啟了一些需要權限的功能之后,Xcode會自動(Xcode 8及之后的版本)生成Entilements文件,并將對應的權限聲明添加到Entitlements文件中。
Xcode中查看授權文件
- 這個文件其實是xml格式的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>inter-app-audio</key>
<true/>
</dict>
</plist>
- 實際上,這個文件的內容并非是全部的授權內容,因為缺省狀態下,App默認會包含以下與Team ID及App ID相關的權限聲明:
<dict>
<key>keychain-access-groups</key>
<array>
<string>xxxxxxxxxx.*</string>
</array>
<key>get-task-allow</key>
<true/>
<key>application-identifier</key>
<string>xxxxxxxxxx.test.CodeSign</string>
<key>com.apple.developer.team-identifier</key>
<string>xxxxxxxxxx</string>
</dict>
- 其中get-task-allow代表是否允許被調試,它在開發階段是必需的一項權限,而在進行Archive打包用于上架時會被去除。
- 進行代碼簽名時,會將這個Entitlements文件(如有)與上述缺省內容進行合并,得到最終的授權文件,并嵌入二進制代碼中,作為被簽名內容的一部分,由代碼簽名保證其不可篡改性。
4. 簽名數據存放
- App 的簽名數據保存分兩部分:
- Mach-O 可執行文件會把簽名直接寫入文件里
- 其他資源文件則會保存在 _CodeSignature 目錄下在APP包里。
-
Mach-O 可執行文件會把簽名直接寫入文件里
通過MachOView查看Mach-O文件 - 其他資源文件則會保存在 _CodeSignature 目錄下在APP包里。
5. IOS 證書文件
5.1 證書文件相關概念
- 證書: 內容是公鑰或者私鑰,由認證機構對其簽名組成的數據包!我們開發可以使用鑰匙串訪問看到.
- 證書分兩種:開發者證書、發布者證書。前者開發時使用,后者發布使用.
- 模擬器調試無需代碼簽名;真機調試需開發者證書代碼簽名;發布時需發布證書簽名
- 代碼簽名需要:證書+私鑰,缺一不可
- 真機調試時要求在設備上安裝描述文件(provision profile),該文件包含信息:調試者證書,授權調試設備清單,應用ID。一個應用對應一個描述文件.
- 開發者證書按用途可分為Development證書和Distribution證書:
(1) Development證書是用于開發及測試階段使用的證書,它用于在設備安裝上開發階段的App后對App的完整性進行校驗,一般證書名稱為 iPhone Developer: xxxxxxx。如果是多人協作的開發者賬號,任意成員都可以申請自己的Development證書。
(2) Distribution證書是用于提交AppStore的證書,一般命名為 iPhone Distribution: xxxxxxxxx,用于讓AppStore校驗提交上來的App的完整性,只有管理員以上身份的開發者賬號才可以申請,因此可以控制提交權限的范圍。同時,Distribution證書不能用于開
發及調試。
- 企業級開發者證書:
除了普通開發者證書(個人開發者賬號和公司開發者賬號使用的證書)外,還有一種特殊的企業級開發者證書,這種證書簽名的App可以被直接安裝在任意的iOS設備上,只要用戶主動信任該證書即可。它的作用是方便企業給內部員工分發生產力工具,比如往往存在這樣一些場景:企業內部無法訪問互聯網,自然也就無法通過AppStore安裝應用,或是使用私有API,完成一些AppStore不允許的功能。前面所說的不需要蘋果簽名即可安裝運行的機制同樣適用于企業級開發者證書,并且是企業級開發者證書的基礎。
- P12: 就是本地私鑰,可以導入到其他電腦
- Entitlements: 權限文件,包含了APP一些權限的plist文件
- CertificateSigningRequest: CSR文件包含了本地公鑰的數據文件
- Provisioning Profile: 描述文件,包含了證書/Entitlements等數據,并由蘋果后臺私鑰簽名的數據包.
- 團隊開發中如何共用證書?
- 團隊開發中,需要共享證書文件和私鑰。若僅從provisioning portal下載證書文件而無私鑰,xcode會提示出錯:Unable to code design using identities in this team: no private keys available(無法在團隊中進行代碼簽名:找不到有效的私鑰)。
解決辦法:
(1) 打開鑰匙串程序,選擇 ‘秘鑰’ 種類。
(2) 右鍵點擊(或按住control點擊)與開發證書相配套的私鑰(專用密鑰),并點擊 ‘導出’,保存為Personal Information Exchange (.p12) 文件格式.,將提示你創建一個密碼,并需要管理員密碼才可導出。
(3) 拷貝該p12文件到其他機子上,會提示你輸入上一步輸入的密碼。
5.1.1 證書相關資源
鑰匙串程序(常用工具->鑰匙串),用于創建證書請求、安裝證書、導出私鑰等
IOS開發中心:https://developer.apple.com/devcenter/ios/index.action
IOS描述門戶(IOS provisioning Portal),在此配置證書、描述文件、推送服務等:
https://developer.apple.com/ios/manage/overview/index.action,
- IOS程序發布:http://itunesconnect.apple.com/
5.2 開發證書生成流程
5.2.1 生成證書
-
第 1 步:對應的是 keychain 里的 “從證書頒發機構請求證書”,這里就本地生成了一對公私鑰,保存的 CertificateSigningRequest 里面就包含公鑰,私鑰保存在本地電腦里.
保存的 CertificateSigningRequest
這個操作會產生一個名為CertificateSigningRequest.certSigningRequest 的簽名請求文件,在生成這個文件之前其實Keychain已經自動生成了一對公、私鑰
可以在Keychain中選中這個條目,右鍵選擇導出,將密鑰文件導出為p12文件,使用openssl查看其內容
$ openssl pkcs12 -in JustForTesting.p12 -out private_key.pem # 導出p12文件中的密鑰
Enter Import Password: # 輸入p12文件的密碼
MAC verified OK
Enter PEM pass phrase: # 設定導出的密鑰文件的密碼
Verifying - Enter PEM pass phrase: # 確認密碼
$ openssl rsa -in private_key.pem -noout -text # 查看密鑰文件的內容
Enter pass phrase for private_key.pem: # 輸入密鑰文件的密碼
Private-Key: (2048 bit)
modulus:
00:c2:98:f5:02:eb:dc:a6:fd:4b:12:4c:70:17:a6:
xx:xx:xx:xx:xx:xx:xx:...
publicExponent: 65537 (0x10001)
privateExponent:
00:a1:67:68:e1:51:6c:a4:fd:36:45:29:2d:58:10:
xx:xx:xx:xx:xx:xx:xx:...
prime1:
00:f3:91:5d:5b:dc:c1:de:d2:ab:7a:5f:b2:27:41:
xx:xx:xx:xx:xx:xx:xx:...
prime2:
00:cc:87:b5:c9:7e:81:39:94:13:c1:ff:3f:d7:7b:
xx:xx:xx:xx:xx:xx:xx:...
exponent1:
00:a5:a0:22:c0:f5:d3:eb:86:8c:4e:b1:c6:3e:85:
xx:xx:xx:xx:xx:xx:xx:...
exponent2:
00:8b:e1:00:85:a6:7c:10:79:e2:2d:5a:39:3a:51:
xx:xx:xx:xx:xx:xx:xx:...
coefficient:
7e:30:60:84:fc:47:6b:90:fe:e7:32:1a:2f:b0:c4:
xx:xx:xx:xx:xx:xx:xx:...
prime1/prime2
就是生成密鑰所使用的兩個超大的素數p, q
modulus
是這兩個超大素數的乘積 n = p * q
publicExponent
是公鑰因子,也就是前文中的e, 這里固定為 0x10001 (65535)
privateExponent
是私鑰因子,即前文中的d
CSR
文件的內容其實就是個人信息、公鑰(Modulus + PublicExponent),以及自簽名(使用自己的私鑰進行簽名), 可通過openssl
命令查看其內容:
$ openssl req -in ~/Desktop/CertificateSigningRequest.certSigningRequest -text -noout
Certificate Request:
Data:
Version: 0 (0x0)
Subject: emailAddress=me@xelz.info, CN=JustForTesting, C=CN
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c2:98:f5:02:eb:dc:a6:fd:4b:12:4c:70:17:a6:
xx:xx:xx:xx:xx:xx:xx:...
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: sha256WithRSAEncryption
b7:11:aa:48:2f:b3:10:e9:71:c7:93:c3:ec:44:8d:0f:a0:5a:
xx:xx:xx:xx:xx:xx:xx:...
- 第 2 步: 向蘋果申請對應把 CSR 傳到蘋果后臺生成證書.
在蘋果開發者網站,將CSR提交給Apple進行簽名,Apple會返回一個簽好名的證書文件,后綴名為cer。
先查看一下他的sha1值
$ shasum ios_development.cer
11447116f2c5521b057b9b67290f0fdadeadfa0a ios_development.cer
雙擊即可將其導入到Keychain中,Keychain會自動把它之前創建CSR時自動生成的密鑰歸為一組。無論是在證書列表中查看還是在密鑰列表中查看,都能看到與之匹配的另一半。
可以從證書中得到幾個關鍵信息:
- 證書的所有者,這部分信息并非由我們自行指定,而是簽發者Apple根據我們的賬號信息自動生成
- 證書的簽發者,即前文所述的CA
- 證書的公鑰信息,與之前生成的密鑰文件及CSR完全一致
現在應該可以理解證書和密鑰的關系了,密鑰中保存了私鑰和公鑰,私鑰用于簽名,而證書里面有且只有公鑰,并且是被第三方CA “認證” 過,用于解密和校驗。
圖中可以看到這個證書的簽發者是Apple Worldwide Developer Relations Certification Authority,在Keychain中搜索這個名字, 可以看到它的證書詳情。我們會發現,它的類型是中級證書頒發機構(中級CA),它也包含簽名,并且是由另外一個叫做Apple Root CA的根證書頒發機構(根CA)進行簽發的,這樣就形成了一條證書鏈。而繼續查看Apple Root CA的證書,會發現它是自簽名的,因為它會被內置在設備中,設備無條件信任它,也就不需要其他的機構為其背書了。
這樣的證書鏈機制可以簡化根證書頒發機構的工作,同時提升證書管理的安全性。將頒發底層證書的工作分散給多個中級證書頒發機構進行處理,根證書頒發機構只需要對下一級機構的證書進行管理和簽發,降低根證書頒發機構私鑰的使用頻率,也就降低了私鑰泄露的風險。中級證書頒發機構各司其職,即使出現私鑰泄露這樣的重大安全事故,也不至于波及整個證書網絡。
第 3 步:證書下載到本地.這時本地有兩個證書.一個是第 1 步生成的私鑰,一個是這里下載回來的證書,keychain 會把這兩個證書關聯起來,因為他們公私鑰是對應的,在XCode選擇下載回來的證書時,實際上會找到 keychain 里對應的私鑰去簽名.這里私鑰只有生成它的這臺 Mac 有,如果別的 Mac 也要編譯簽名這個 App 怎么辦?答案是把私鑰導出給其他 Mac 用,在 keychain 里導出私鑰,就會存成 .p12 文件,其他 Mac 打開后就導入了這個私鑰.
第 4 步:都是在蘋果網站上操作,配置 AppID / 權限 / 設備等,最后下載 Provisioning Profile 文件。
- 第 5 步: XCode 會通過第 3 步下載回來的證書(存著公鑰),在本地找到對應的私鑰(第一步生成的),用本地私鑰去簽名 App,并把 Provisioning Profile 文件命名為 embedded.mobileprovision 一起打包進去。所以任何本地調試的APP,都會有一個embedded.mobileprovision(描述文件)從App Store下載的沒有.
參考:http://www.lxweimin.com/p/3c9e2055ae5b
https://segmentfault.com/p/1210000018014804/read