iOS證書籤名原理分析,簽名過程,重簽名原理

iOS簽名原理

在iOS真機調試和發佈上線的時候,我們可能已經習慣了配置各種證書、描述文件,等這一繁瑣的步驟。但是對於背後我們為什麼要配置這些東西,以及其背後的原理之前一直沒有做過分析研究,最近有空就簡單的研究了一下!

一、背景

我們都知道蘋果手機的正版APP只能去App Store下載,而其他系統的手機比如安卓手機的APP現在的途徑有很多,這些軟件是不需要簽名的。而蘋果為了控制每一個安裝在蘋果手機上的APP都是經過蘋果官方認證的,於是就採用了簽名機制。

1.對稱加密

對稱加密是密碼學中一類加密算法的統稱,這類算法在加密與解密時使用相同的密鑰,或者使用兩個可以簡單的相互推算的密鑰。常見的對稱加密算法有DES、3DES、AES、RC5等。相比非對稱加密算法,對稱加密算法的優點是加解密的速度很快。

2.非對稱加密

非對稱加密是指加密密鑰與解密密鑰是成對出現的,其中一個對外公開,叫公鑰,另一個末公開的叫私鑰,幾乎不能從一個密鑰計算出另一個密鑰。通過私鑰加密的只能通過公鑰解密,公鑰加密的只能通過私鑰解密。最著名的非對稱加密算法是RSA算法。當然如此強大可靠的安全性是在犧牲加密速度的基礎上得到的。

通常我們所說的簽名就是數字簽名,它是基於非對稱加密算法實現的。對稱加密是通過同一份密鑰加密和解密數據,而非對稱加密則有兩份密鑰,分別是公鑰和私鑰,用公鑰加密的數據,要用私鑰才能解密;用私鑰加密的數據,要用公鑰才能解密。這裡的非對稱加密就是我們所熟知的RSA,要了解RSA背後的數學原理可以參考RSA算法原理(一)(二)

二、從App Store安裝APP

這個過程的簽名方式相對簡單一些。蘋果官方生成一對公私鑰,在蘋果手機裡面內置一個公鑰,私鑰由蘋果後臺保存,我們傳App上AppStore時,蘋果後臺用私鑰對App數據值的MD5值進行簽名,iOS系統下載這個App後,用公鑰驗證這個簽名,若簽名正確,這個App肯定由蘋果後臺認證的,並且沒有被修改過,也就達到了蘋果的需求:保證安裝的每一個App都是經過蘋果認證允許的。

三、其他方式安裝APP

在實際工作當中,我們還有一些其他的方式把APP安裝到手機上:

開發App時可以直接把開發中的應用安裝進手機調試;

In-House企業內部分發,可以直接安裝企業證書籤名後的App;

AD-Hoc相當於企業分發的限制版,限制安裝設備數量,較少用。

蘋果對這幾種方式安裝的控制過程就變得複雜了,即要保證APP的安裝時經過蘋果認證的,又要控制APP不能被隨便安裝到其他設備上,以及一些其他的權限,為了達到這樣的目的,蘋果採用的流程大致是這個樣子

基本流程:

iOS證書籤名原理分析,簽名過程,重簽名原理


1、在Mac上生成一對公私鑰,這裡稱公鑰M,私鑰M。

2、蘋果自己有固定的一對公私鑰,跟上面AppStore例子一樣,私鑰在蘋果後臺,公鑰內置在每個iOS設備上,這裡稱為公鑰A,私鑰A。

3、把公鑰M上傳到蘋果後臺,用蘋果後臺裡的私鑰A去簽名公鑰M。得到一份數據包含了公鑰M以及其簽名(也就是公鑰的HASH值),把這份數據稱為證書。

4、在開發時,編譯完一個App後,用本地的私鑰M對這個App進行簽名,同時把第三步得到的證書一起打包進App裡,安裝到手機。

5、在安裝時,iOS系統取得證書,通過系統內置的公鑰A,去驗證證書的數字簽名是否正確。

驗證證書確保公鑰M是蘋果認證過的,再用公鑰M去驗證App的簽名,這裡就間接驗證了這個App的安裝行為是否經過蘋果官方允許。(這裡只驗證安裝行為,不驗證App是否被改動,因為開發階段App內容總是不斷變化的,蘋果不需要管)。

最終流程:

上述流程只解決了上面第一個需求,也就是需要經過蘋果允許才可以安裝,還未解決第二個避免被濫用的問題。怎麼解決呢?蘋果加了兩個限制,一是限制在蘋果後臺註冊過的設備才可以安裝;二是限制簽名只能針對某一個具體的App。

那麼它到底是怎麼添加這兩個限制的呢?在上述第三步,蘋果用私鑰A簽名我們的本地公鑰M時,實際上除了簽名本地公鑰M外,還可以加上無限多數據,這些數據都可以保證是經過蘋果官方認證的,不會有被篡改的可能。

iOS證書籤名原理分析,簽名過程,重簽名原理


可以把允許安裝的設備ID列表和App對應的AppID等數據,都在第三步這裡跟公鑰M一起組成證書,再用蘋果私鑰A對這個證書籤名。在最後第5步驗證時就可以拿到設備ID列表,判斷當前設備是否符合要求。根據數字簽名的原理,只要數字簽名通過驗證,第5步這裡的設備IDs/AppID/公鑰M就都是經過蘋果認證的,無法被修改,蘋果就可以限制可安裝的設備和APP,避免濫用。

到這裡這個證書已經變得很複雜了,有很多額外信息,實際上除了設備ID/AppID,還有其他信息也需要在這裡用蘋果簽名,像App裡iCloud、push、後臺運行 等權限蘋果都想控制,蘋果把這些權限開關統稱為Entitlements,它也需要通過簽名去授權。

實際上一個證書本來就有規定的格式規範,上面我們把各種額外的信息塞入證書裡是不合適的,於是蘋果另外搞了一個東西,叫Provisioning Profile,一個Provisioning Profile裡就包含了證書以及上述提到的所有額外信息,以及所有信息的簽名。

所以,就成這樣了:

在 Mac 上生成一對公私鑰,這裡稱為公鑰M,私鑰M。

蘋果自己有固定的一對公私鑰,跟上面 AppStore 例子一樣,私鑰在蘋果後臺,公鑰在每個iOS設備上。這裡稱為公鑰A,私鑰A。A:Apple

把公鑰M傳到蘋果後臺,用蘋果後臺裡的私鑰A去簽名公鑰M。得到一份數據包含了公鑰M以及其簽名,把這份數據稱為證書。

在蘋果後臺申請AppID,配置好設備ID列表和APP可使用的權限,再加上第3步的證書,組成的數據用私鑰A簽名,把數據和簽名一起組成一個Provisioning Profile文件,下載到本地Mac開發機。

在開發時,編譯完一個APP後,用本地的私鑰M對這個APP進行簽名,同時把第4步得到的Provisioning Profile文件打包進APP裡,文件名為 embedded.mobileprovision,把APP安裝到手機上。

在安裝時,iOS系統取得證書,通過系統內置的公鑰A,去驗證 embedded.mobileprovision的數字簽名是否正確,裡面的證書籤名也會再驗一遍。

確保了embedded.mobileprovision裡的數據都是蘋果授權以後,就可以取出裡面的數據,做各種驗證,包括用公鑰M驗證APP簽名,驗證設備ID是否在ID列表上,AppID是否對應得上,權限開關是否跟APP裡的Entitlements對應等。

開發者證書從簽名到認證最終蘋果採用的流程大致是這樣,還有一些細節像證書有效期/證書類型等就不細說了。

上面的步驟對應到我們平常具體的操作和概念是這樣的:

第1步對應的是keychain裡的“從證書頒發機構請求證書”,這裡就本地生成了一對公私鑰,保存的CertificateSigningRequest就是公鑰,私鑰保存在本地電腦裡。

第2步蘋果自己處理,我們不用管。

第3步對應把CertificateSigningRequest傳到蘋果後臺生成證書,並下載到本地。這時本地有兩個證書,一個是第1步生成的,一個是這裡下載回來的,keychain會把這兩個證書關聯起來,因為它們的公私鑰是對應的,在Xcode選擇下載回來的證書的時,實際上會找到keychain裡面對應的私鑰去簽名。這裡私鑰只有生成它的這臺Mac才有,如果別的Mac也要編譯簽名這個App,把私鑰導出給其他Mac使用,在keychain裡面導出私鑰,就會存成.p12文件,其他Mac打開後就導入私鑰。

第4步都是在蘋果網站上操作,配置AppID、權限、設備等,最後下載 Provisioning Profile文件。

第5步Xcode會通過第3步下載回來的證書(存著本地公鑰),在本地找到對應的私鑰(第1步生成的),用本地私鑰去簽名App,並把Provisioning Profile文件命名為embedded.mobileprovision一起打包進去。這裡對App的簽名數據保存分為兩部分,Mach-O可執行文件會把簽名直接寫入這個文件裡,其他資源文件則會保存在_CodeSignature目錄下。

第6、7步的打包和驗證都是 Xcode 和 iOS 系統自動做的事。

四、總結

幾個概念:

證書:內容是公鑰或私鑰,由其他機構對其簽名組成的數據包。

Entitlements:包含了App權限開關列表。

CertificateSigningRequest:本地公鑰。

.p12:本地私鑰,可以導入到其他電腦。

Provisioning Profile:包含了 證書/Entitlements 等數據,並由蘋果後臺私鑰簽名的數據包。

其他發佈方式

前面以開發包為例子說了簽名和驗證的流程,另外兩種方式In-House企業簽名和AD-Hoc流程也是差不多的,只是企業簽名不限制安裝的設備數,另外需要用戶在iOS系統設置上手動點擊信任這個企業才能通過驗證。

而AppStore的簽名驗證方式有些不一樣,前面我們說到最簡單的簽名方式,蘋果在後臺直接用私鑰簽名App就可以了,實際上蘋果確實是這樣做的,如果去下載一個AppStore的安裝包,會發現它裡面是沒有embedded.mobileprovision文件的,也就是它安裝和啟動的流程是不依賴這個文件,驗證流程也就跟上述幾種類型不一樣了。

因為上傳到AppStore的包蘋果會重新對內容加密,原來的本地私鑰簽名就沒有用了,需要重新簽名,從AppStore下載的包蘋果也並不打算控制它的有效期,不需要內置一個embedded.mobileprovision去做校驗,直接在蘋果用後臺的私鑰重新簽名,iOS安裝時用本地公鑰驗證App簽名就可以了。

那為什麼發佈AppStore的包還是要跟開發版一樣搞各種證書和Provisioning Profile,因為蘋果想做統一管理,Provisioning Profile裡包含一些權限控制,AppID 的檢驗等,蘋果不想在上傳AppStore 包時重新用另一種協議做一遍這些驗證,就不如統一把這部分放在 Provisioning Profile裡,上傳AppStore時只要用同樣的流程驗證這個 Provisioning Profile是否合法就可以了。

所以 App 上傳到AppStore後,就跟你的 證書 / Provisioning Profile 都沒有關係了,無論他們是否過期或被廢除,都不會影響AppStore 上的安裝包。

以上就是整個簽名的大致分析。


iOS簽名簡潔過程

第一步:從KeyChain生成 CertificateSigningRequest.certSigningRequest。

得到 本地文件CertificateSigningRequest.certSigningRequest包含用戶信息,公鑰。

得到 Access|Keys中一對Public/Private Key ,公鑰/私鑰。

第二步申請證書:

通過CSR文件的公鑰生成證書,包含開發者信息,公鑰信息,使用蘋果私鑰加密。下載到本地使用蘋果公鑰解密,得到KeyChain中的證書文件,

使用蘋果私鑰加密,包含AppId,證書,功能授權列表,設備列表等信息。

第四步 App打包生成:

私鑰簽名

第五步 App安裝驗證:

設備使用CA證書(WWDRCA.cer)的公鑰解密Provisioning Profile得到app 公鑰和app內容摘要,驗證Provisioning Profile的合法性。

使用app公鑰解密app來判斷App的合法性,使用app內容摘要判斷app是否被篡改。


重簽名

重簽名的解釋:

當在Xcode進行archive或者通過腳本打包ipa的時候,通常到最後一步,要對包有一個簽名過程,對簽名起到關鍵作用的是配置好證書和描述文件。也就是一套證書,描述文件最終簽名好一個對應的ipa。

而所謂的重簽名的概念就是,可以把一個已經存在的ipa重新配置一套證書和描述文件,再簽名生成一個新的ipa包。

ios重新簽名的核心原理是使用 codesign 命令,當然也許完成一些額外的操作。

大致流程

1、解壓ipa


iOS證書籤名原理分析,簽名過程,重簽名原理

2、刪除舊的簽名

iOS證書籤名原理分析,簽名過程,重簽名原理

3、複製新的描述文件


iOS證書籤名原理分析,簽名過程,重簽名原理

4、用新的證書籤名

iOS證書籤名原理分析,簽名過程,重簽名原理

5、壓縮成ipa


iOS證書籤名原理分析,簽名過程,重簽名原理

在這個過程中,最重要是這個 entitlements.plist文件的問題。

entitlements.plist是一個比較重要的文件,涉及到app的權限及簽名相關問題。

那麼,如何得到這個文件呢?我們可以通過這條命令

iOS證書籤名原理分析,簽名過程,重簽名原理

獲取到這個文件的內容,大致格式如下:

iOS證書籤名原理分析,簽名過程,重簽名原理

注意:這裡我們我麼需要把紅色的地方替換成新的簽名文件的bundleid和teamid.

當然,有的朋友可能會問,有沒有更簡單的操作呢?

實際上是有的。

著名的自動化工具fastlane,就封裝了一個resign的工具,專門可以用來對app進行重簽名的。具體可看:https://weidaoliu.com

使用方法也很簡單, 一行命令即可。


iOS證書籤名原理分析,簽名過程,重簽名原理




分享到:


相關文章: