iOS App簽名的原理

iOS的簽名機(jī)制很復(fù)雜,各種證書,Provision Profile,entitlements,CertificateSigningRequest,p12,AppID,這篇文章從概念出發(fā),一步一步推出為什么會有這么對概念,希望能有助于理解iOS的App簽名的原理。

目的

在iOS出來之前,在主流操作系統(tǒng)(Mac,Windows,Linux)上開發(fā)和運(yùn)行軟件是不需要簽名的,軟件隨便從哪里下載都能運(yùn)行,導(dǎo)致平臺對第三方軟件很難控制,盜版盛行。蘋果希望解決這樣的問題,希望iOS平臺對第三方App有絕對控制權(quán),一定要保證每一個安裝到iOS上的App都是經(jīng)過蘋果官方允許的,怎么保證呢?就是通過簽名機(jī)制。

最簡單的實(shí)現(xiàn)

要實(shí)現(xiàn)這個需求很簡單,最直接的方式,蘋果官方生成一對公私鑰,私鑰由蘋果后臺保管,公鑰內(nèi)置到iOS設(shè)備里,在我們將App上傳到App Store上時(shí),蘋果后臺使用私鑰對App進(jìn)行簽名,iOS設(shè)備下載這個應(yīng)用后,用公鑰驗(yàn)證這個簽名,若簽名正確,則說明這個App是經(jīng)過蘋果后臺認(rèn)證的,并且沒有被修改過,這樣也就達(dá)到了蘋果的目的:保證iOS設(shè)備安裝的每一個APP都是經(jīng)過蘋果官方允許的。


image

如果我們的iOS設(shè)備安裝App只通過App Store這一種方式的話,那么問題到這里就已經(jīng)解決了,但是實(shí)際上除了從App Store上下載應(yīng)用,還可以以一下三種方式安裝一個APP:

  • 1.作為開發(fā)者,開發(fā)App時(shí)直接進(jìn)行真機(jī)調(diào)試。
  • 2.In-House 企業(yè)內(nèi)部分發(fā),可以直接安裝企業(yè)證書簽名后的App。
  • 3.AD-Hoc 相當(dāng)于是企業(yè)分發(fā)的限制版,限制安裝設(shè)備數(shù)量。
    蘋果要對這三種方式安裝的APP進(jìn)行孔子,就無法像上面這樣簡單了。

新的需求

我們先來看第一個,開發(fā)時(shí)安裝APP,它有兩個需求:

  • 1.安裝包不需要傳到蘋果服務(wù)器,可以直接安裝到手機(jī)上。
  • 2.蘋果必須對這個安裝過程有控制權(quán),包括:
    a.經(jīng)過蘋果允許才可以這樣安裝
    b.不能被濫用導(dǎo)致非開發(fā)App也能被安裝。

為了滿足這個需求,iOS簽名的復(fù)雜度也就開始增加了。

蘋果給出的方案是使用雙層簽名,有一點(diǎn)繞,流程大概是下圖這樣:


image

1.在我們開發(fā)使用的Mac上生成一對公鑰和私鑰,稱為公鑰,私鑰L。L:Local。

2.蘋果有固定的一對公鑰和私鑰,私鑰在自己后臺保存,公鑰內(nèi)置到了iOS設(shè)備里,稱為公鑰,私鑰A。A:Apple。

3.把公鑰L上傳到蘋果后臺,用蘋果后臺的私鑰A去簽名公鑰L。得到了一份數(shù)據(jù)包括公鑰L及其簽名,這份數(shù)據(jù)稱為證書。

4.在開發(fā)時(shí),編譯完一個APP后,用第一步生成的私鑰L去簽名這個App,同時(shí)把第三步得到的證書一起打包進(jìn)App里,安裝到手機(jī)上。

5.在安裝時(shí),iOS系統(tǒng)取得證書,通過系統(tǒng)內(nèi)置的公鑰A,去驗(yàn)證證書的數(shù)字簽名是否正確。

6.驗(yàn)證證書后確保了公鑰L是蘋果認(rèn)證的,再用公鑰L去驗(yàn)證App的簽名,這樣就間接驗(yàn)證了這個App安裝行為是否經(jīng)過蘋果允許。

加點(diǎn)東西

上述流程只解決了上面的第一個需求,也就是需要經(jīng)過蘋果的允許才可以安裝,還未解決第二個避免被濫用的問題。怎么解決呢?蘋果加了兩個限制,一個是限制在蘋果后天注冊過的設(shè)備才可以安裝,二是限制簽名只能針對某個具體的App。

在上述的第三步中,蘋果用私鑰A去簽名我們本地公鑰L時(shí),實(shí)際上除了簽名公鑰L,還可以加上很多數(shù)據(jù),這些數(shù)據(jù)都可以保證是經(jīng)過蘋果官方認(rèn)證的,不會有被篡改的可能,那么我們就可以把AppID和設(shè)備ID添加進(jìn)去:


image

把允許安裝的設(shè)備ID和APP對應(yīng)的AppID等數(shù)據(jù),都在第三步這里和公鑰L一起,被私鑰A簽名,一起組成證書。在第五步驗(yàn)證時(shí)就可以拿到設(shè)備ID列表,判斷當(dāng)前設(shè)備是否符合要求。

最終流程

到這里這個證書已經(jīng)變得很復(fù)雜了,有很多額外的信息,實(shí)際上除了設(shè)備ID,AppID,還有其他信息也需要用蘋果簽名,像App里面的iCloud,后天運(yùn)行等蘋果都想控制,蘋果把這些權(quán)限開關(guān)統(tǒng)稱為entitlements,它也需要通過簽名去授權(quán)。

但是一個證書本來就有規(guī)范的格式,我們把這些雜七雜八的額外信息賽入證書是不合適的,因此蘋果另外搞了一個東西叫Provisioning Profile,一個Provisioning Profile里面就包含了證書以及上述提到的所有額外信息,以及所有信息的簽名。

所以最終流程就變成了這樣:
image

1.在你的Mac上生成一對公鑰和私鑰,稱為公鑰L和私鑰L。

2.蘋果自己有一對固定的公鑰和私鑰,私鑰在蘋果后臺,公鑰內(nèi)置在iOS設(shè)備中,分別稱為私鑰A和公鑰A。

3.把公鑰L傳到蘋果后天,用蘋果后天的私鑰A去簽名公鑰L,得到一份數(shù)據(jù)包括公鑰L和簽名,這份數(shù)據(jù)稱為證書。

4.在蘋果后臺申請好AppID,配置好設(shè)備ID列表,App權(quán)限開關(guān),再加上第三步的證書,組成的數(shù)據(jù)用蘋果后天的私鑰A簽名,把數(shù)據(jù)和簽名一起組成一個Provisioning Profile文件,下載到本地Mac。

5.在開發(fā)時(shí),編譯完一個App后,用本地的私鑰L對這個App進(jìn)行簽名,同時(shí)把第四步生成的Provisionning Profile一起打包進(jìn)App里,文件名為embeded.mobileprovision,把App安裝到手機(jī)。

6.在安裝時(shí),就可以使用iOS設(shè)備里內(nèi)置的公鑰A來驗(yàn)證Provisioning Profile的數(shù)字簽名是否正確。

7.如果數(shù)字簽名沒有問題,那么就能確保設(shè)備ID,AppID,entitlements,和App都是經(jīng)過蘋果認(rèn)證的,可以安裝到iOS設(shè)備上。

上面的步驟對應(yīng)我們平時(shí)具體操作和概念是這樣的:

1.第一步對應(yīng)的是從keychain里“從這證書頒發(fā)機(jī)構(gòu)請求證書”,這樣就在本地生成了一對公私鑰,保存的額CertificateSigningRequest就是公鑰,公鑰保存在本地電腦里。

2.第二步蘋果處理,不用管。

3.第三步把CertificateSigningRequest上傳到蘋果后天,生成證書,并下載到本地。

4.第四步是在蘋果網(wǎng)站操作的,配置AppID,設(shè)備ID,權(quán)限等,生成Provisioning Profile文件,并下載Provisioning Profile文件到本地。

5.xcode通過第三步下載下來的證書,去找對應(yīng)的本地私鑰,用本地私鑰去簽名App,并把Provisioning Profile文件一起打包進(jìn)去,安裝進(jìn)iOS設(shè)備。

總結(jié)一些概念:
1.證書:內(nèi)容是公鑰或者私鑰,由其它機(jī)構(gòu)對其簽名組成的數(shù)據(jù)包。

2.entitlements:包含了App權(quán)限開關(guān)列表,AppID,設(shè)備ID等。

3.CertificateSigningRequest:本地公鑰。

4.p12:本地私鑰。

5.Provisioning Profile:包含證書,entitlements等數(shù)據(jù),并由蘋果后臺私鑰簽名的數(shù)據(jù)包。

我們平時(shí)的操作

按照上面的流程,那么對于開發(fā)人員來說,應(yīng)該是我們每次新建一個項(xiàng)目也就是有一個新的AppID時(shí),都應(yīng)該去申請一對本地公私鑰,上傳公鑰到蘋果后臺,然后下載證書,但是實(shí)際上我們并沒有這么做,好像很少需要去keychain請求本地公私鑰,這是為什么呢?

這里的原因就是iOS Team Provisioning Profile
iOS Team Provisioning Profile是第一次使用xcode添加設(shè)備時(shí),xcode自動生成的,它包含了xcode生成的一個Wildcard AppID(匹配所有應(yīng)用程序,賬戶里面的所有device,所有Development Certificates),因此team中的所有成員都可以使用這個iOS Team Provisioning Profile在team的所有設(shè)備上調(diào)試所有的應(yīng)用程序,并且當(dāng)有新設(shè)別添加進(jìn)來時(shí),xcode會更新這個文件。

image

如此一來,只要我們有一對本地公私鑰,并且通過這個本地的公鑰上傳給蘋果獲取了證書,那么以后我們運(yùn)行任何App,在任何iOS設(shè)備上運(yùn)行,都可以使用這個本地私鑰和證書,而沒有必要每次去創(chuàng)建新的公私鑰和獲取證書。

下面我從我的項(xiàng)目中找出一個iOS Team Provisioning Profile,我們可以一起來看一下它的結(jié)構(gòu):

BDB36D96-7D68-4D73-B925-82C73D4EEF26.png

第一個是AppID,這里的AppID是我當(dāng)前應(yīng)用的AppID。
第二個是證書,這就是選擇了我本地的一個證書,是上面的流程中上傳本地的公鑰得到的證書。
第三個是team,這個是我在項(xiàng)目中選擇的,這個team決定了我用哪個證書。
第五個是entitlements,就是一系列的權(quán)限開關(guān)。

通過這個iOS Team Provisioning Profile的結(jié)構(gòu)我們就能明白,iOS Team Provisioning Profile中保存著很多分證書,很多AppID,很多設(shè)備ID,entitlements。當(dāng)我們需要在一個指定的iOS設(shè)備上運(yùn)行一個指定的App時(shí),iOS Team Provisioning Profile就會得到這個AppID和這個設(shè)備ID以及它對應(yīng)entitlements,組成這個特定的Provisioning Profile,打包進(jìn)APP里面。這樣就不需要我們每次去申請證書,生成Provisioning Profile文件了,非常方便。

注:這篇文章主要是把大牛的文章摘抄了一遍,由于大牛寫的太好了,讓我茅塞頓開,于是想重新寫一次加深理解,也方便以后查閱。
大牛博客:
iOS App 簽名的原理
關(guān)于 Certificate、Provisioning Profile、App ID 的介紹及其之間的關(guān)系

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容