iOS的簽名機制很復雜戈毒,各種證書,Provision Profile议经,entitlements斧账,CertificateSigningRequest,p12煞肾,AppID咧织,這篇文章從概念出發(fā),一步一步推出為什么會有這么對概念籍救,希望能有助于理解iOS的App簽名的原理习绢。
目的
在iOS出來之前,在主流操作系統(tǒng)(Mac蝙昙,Windows闪萄,Linux)上開發(fā)和運行軟件是不需要簽名的,軟件隨便從哪里下載都能運行耸黑,導致平臺對第三方軟件很難控制桃煎,盜版盛行。蘋果希望解決這樣的問題大刊,希望iOS平臺對第三方App有絕對控制權为迈,一定要保證每一個安裝到iOS上的App都是經(jīng)過蘋果官方允許的三椿,怎么保證呢?就是通過簽名機制葫辐。
最簡單的實現(xiàn)
要實現(xiàn)這個需求很簡單搜锰,最直接的方式,蘋果官方生成一對公私鑰耿战,私鑰由蘋果后臺保管蛋叼,公鑰內置到iOS設備里,在我們將App上傳到App Store上時剂陡,蘋果后臺使用私鑰對App進行簽名狈涮,iOS設備下載這個應用后,用公鑰驗證這個簽名鸭栖,若簽名正確歌馍,則說明這個App是經(jīng)過蘋果后臺認證的,并且沒有被修改過晕鹊,這樣也就達到了蘋果的目的:保證iOS設備安裝的每一個APP都是經(jīng)過蘋果官方允許的松却。
如果我們的iOS設備安裝App只通過App Store這一種方式的話,那么問題到這里就已經(jīng)解決了溅话,但是實際上除了從App Store上下載應用晓锻,還可以以一下三種方式安裝一個APP:
- 1.作為開發(fā)者,開發(fā)App時直接進行真機調試飞几。
- 2.In-House 企業(yè)內部分發(fā)砚哆,可以直接安裝企業(yè)證書簽名后的App。
- 3.AD-Hoc 相當于是企業(yè)分發(fā)的限制版屑墨,限制安裝設備數(shù)量窟社。
蘋果要對這三種方式安裝的APP進行孔子,就無法像上面這樣簡單了绪钥。
新的需求
我們先來看第一個灿里,開發(fā)時安裝APP,它有兩個需求:
- 1.安裝包不需要傳到蘋果服務器程腹,可以直接安裝到手機上匣吊。
- 2.蘋果必須對這個安裝過程有控制權,包括:
a.經(jīng)過蘋果允許才可以這樣安裝
b.不能被濫用導致非開發(fā)App也能被安裝寸潦。
為了滿足這個需求色鸳,iOS簽名的復雜度也就開始增加了。
蘋果給出的方案是使用雙層簽名见转,有一點繞命雀,流程大概是下圖這樣:
1.在我們開發(fā)使用的Mac上生成一對公鑰和私鑰,稱為公鑰斩箫,私鑰L吏砂。L:Local撵儿。
2.蘋果有固定的一對公鑰和私鑰,私鑰在自己后臺保存狐血,公鑰內置到了iOS設備里淀歇,稱為公鑰,私鑰A匈织。A:Apple浪默。
3.把公鑰L上傳到蘋果后臺,用蘋果后臺的私鑰A去簽名公鑰L缀匕。得到了一份數(shù)據(jù)包括公鑰L及其簽名纳决,這份數(shù)據(jù)稱為證書。
4.在開發(fā)時乡小,編譯完一個APP后岳链,用第一步生成的私鑰L去簽名這個App,同時把第三步得到的證書一起打包進App里劲件,安裝到手機上。
5.在安裝時约急,iOS系統(tǒng)取得證書零远,通過系統(tǒng)內置的公鑰A,去驗證證書的數(shù)字簽名是否正確厌蔽。
6.驗證證書后確保了公鑰L是蘋果認證的牵辣,再用公鑰L去驗證App的簽名,這樣就間接驗證了這個App安裝行為是否經(jīng)過蘋果允許奴饮。
加點東西
上述流程只解決了上面的第一個需求纬向,也就是需要經(jīng)過蘋果的允許才可以安裝,還未解決第二個避免被濫用的問題戴卜。怎么解決呢逾条?蘋果加了兩個限制,一個是限制在蘋果后天注冊過的設備才可以安裝投剥,二是限制簽名只能針對某個具體的App师脂。
在上述的第三步中,蘋果用私鑰A去簽名我們本地公鑰L時江锨,實際上除了簽名公鑰L吃警,還可以加上很多數(shù)據(jù),這些數(shù)據(jù)都可以保證是經(jīng)過蘋果官方認證的啄育,不會有被篡改的可能酌心,那么我們就可以把AppID和設備ID添加進去:
把允許安裝的設備ID和APP對應的AppID等數(shù)據(jù),都在第三步這里和公鑰L一起挑豌,被私鑰A簽名安券,一起組成證書墩崩。在第五步驗證時就可以拿到設備ID列表,判斷當前設備是否符合要求完疫。
最終流程
到這里這個證書已經(jīng)變得很復雜了泰鸡,有很多額外的信息,實際上除了設備ID壳鹤,AppID盛龄,還有其他信息也需要用蘋果簽名,像App里面的iCloud芳誓,后天運行等蘋果都想控制余舶,蘋果把這些權限開關統(tǒng)稱為entitlements,它也需要通過簽名去授權锹淌。
但是一個證書本來就有規(guī)范的格式匿值,我們把這些雜七雜八的額外信息賽入證書是不合適的,因此蘋果另外搞了一個東西叫Provisioning Profile赂摆,一個Provisioning Profile里面就包含了證書以及上述提到的所有額外信息挟憔,以及所有信息的簽名。
所以最終流程就變成了這樣:
1.在你的Mac上生成一對公鑰和私鑰烟号,稱為公鑰L和私鑰L绊谭。
2.蘋果自己有一對固定的公鑰和私鑰,私鑰在蘋果后臺汪拥,公鑰內置在iOS設備中达传,分別稱為私鑰A和公鑰A。
3.把公鑰L傳到蘋果后天迫筑,用蘋果后天的私鑰A去簽名公鑰L宪赶,得到一份數(shù)據(jù)包括公鑰L和簽名,這份數(shù)據(jù)稱為證書脯燃。
4.在蘋果后臺申請好AppID搂妻,配置好設備ID列表,App權限開關辕棚,再加上第三步的證書叽讳,組成的數(shù)據(jù)用蘋果后天的私鑰A簽名,把數(shù)據(jù)和簽名一起組成一個Provisioning Profile文件坟募,下載到本地Mac岛蚤。
5.在開發(fā)時,編譯完一個App后懈糯,用本地的私鑰L對這個App進行簽名涤妒,同時把第四步生成的Provisionning Profile一起打包進App里,文件名為embeded.mobileprovision赚哗,把App安裝到手機她紫。
6.在安裝時硅堆,就可以使用iOS設備里內置的公鑰A來驗證Provisioning Profile的數(shù)字簽名是否正確。
7.如果數(shù)字簽名沒有問題贿讹,那么就能確保設備ID渐逃,AppID,entitlements民褂,和App都是經(jīng)過蘋果認證的茄菊,可以安裝到iOS設備上。
上面的步驟對應我們平時具體操作和概念是這樣的:
1.第一步對應的是從keychain里“從這證書頒發(fā)機構請求證書”赊堪,這樣就在本地生成了一對公私鑰面殖,保存的額CertificateSigningRequest就是公鑰,公鑰保存在本地電腦里哭廉。
2.第二步蘋果處理脊僚,不用管。
3.第三步把CertificateSigningRequest上傳到蘋果后天遵绰,生成證書辽幌,并下載到本地。
4.第四步是在蘋果網(wǎng)站操作的椿访,配置AppID乌企,設備ID,權限等赎离,生成Provisioning Profile文件,并下載Provisioning Profile文件到本地端辱。
5.xcode通過第三步下載下來的證書梁剔,去找對應的本地私鑰,用本地私鑰去簽名App舞蔽,并把Provisioning Profile文件一起打包進去荣病,安裝進iOS設備。
總結一些概念:
1.證書:內容是公鑰或者私鑰渗柿,由其它機構對其簽名組成的數(shù)據(jù)包个盆。
2.entitlements:包含了App權限開關列表,AppID朵栖,設備ID等颊亮。
3.CertificateSigningRequest:本地公鑰。
4.p12:本地私鑰陨溅。
5.Provisioning Profile:包含證書终惑,entitlements等數(shù)據(jù),并由蘋果后臺私鑰簽名的數(shù)據(jù)包门扇。
我們平時的操作
按照上面的流程雹有,那么對于開發(fā)人員來說偿渡,應該是我們每次新建一個項目也就是有一個新的AppID時,都應該去申請一對本地公私鑰霸奕,上傳公鑰到蘋果后臺溜宽,然后下載證書,但是實際上我們并沒有這么做质帅,好像很少需要去keychain請求本地公私鑰适揉,這是為什么呢?
這里的原因就是iOS Team Provisioning Profile临梗。
iOS Team Provisioning Profile是第一次使用xcode添加設備時涡扼,xcode自動生成的,它包含了xcode生成的一個Wildcard AppID(匹配所有應用程序盟庞,賬戶里面的所有device吃沪,所有Development Certificates),因此team中的所有成員都可以使用這個iOS Team Provisioning Profile在team的所有設備上調試所有的應用程序什猖,并且當有新設別添加進來時票彪,xcode會更新這個文件。
如此一來不狮,只要我們有一對本地公私鑰降铸,并且通過這個本地的公鑰上傳給蘋果獲取了證書,那么以后我們運行任何App摇零,在任何iOS設備上運行推掸,都可以使用這個本地私鑰和證書,而沒有必要每次去創(chuàng)建新的公私鑰和獲取證書驻仅。
下面我從我的項目中找出一個iOS Team Provisioning Profile谅畅,我們可以一起來看一下它的結構:
第一個是AppID,這里的AppID是我當前應用的AppID噪服。
第二個是證書毡泻,這就是選擇了我本地的一個證書,是上面的流程中上傳本地的公鑰得到的證書粘优。
第三個是team仇味,這個是我在項目中選擇的,這個team決定了我用哪個證書雹顺。
第五個是entitlements丹墨,就是一系列的權限開關。
通過這個iOS Team Provisioning Profile的結構我們就能明白嬉愧,iOS Team Provisioning Profile中保存著很多分證書带到,很多AppID,很多設備ID,entitlements揽惹。當我們需要在一個指定的iOS設備上運行一個指定的App時被饿,iOS Team Provisioning Profile就會得到這個AppID和這個設備ID以及它對應entitlements,組成這個特定的Provisioning Profile搪搏,打包進APP里面狭握。這樣就不需要我們每次去申請證書,生成Provisioning Profile文件了疯溺,非常方便论颅。
注:這篇文章主要是把大牛的文章摘抄了一遍,由于大牛寫的太好了囱嫩,讓我茅塞頓開恃疯,于是想重新寫一次加深理解,也方便以后查閱墨闲。
大牛博客:
iOS App 簽名的原理
關于 Certificate今妄、Provisioning Profile、App ID 的介紹及其之間的關系