iOS證書簽名原理分析

在iOS真機(jī)調(diào)試和發(fā)布上線的時(shí)候,我們可能已經(jīng)習(xí)慣了配置各種證書、描述文件,等這一繁瑣的步驟。但是對(duì)于背后我們?yōu)槭裁匆渲眠@些東西,以及其背后的原理之前一直沒有做過分析研究,最近有空就簡單的研究了一下!

一、背景

我們都知道蘋果手機(jī)的正版APP只能去App Store下載,而其他系統(tǒng)的手機(jī)比如安卓手機(jī)的APP現(xiàn)在的途徑有很多,這些軟件是不需要簽名的。而蘋果為了控制每一個(gè)安裝在蘋果手機(jī)上的APP都是經(jīng)過蘋果官方認(rèn)證的,于是就采用了簽名機(jī)制。

通常我們所說的簽名就是數(shù)字簽名,它是基于非對(duì)稱加密算法實(shí)現(xiàn)的。對(duì)稱加密是通過同一份密鑰加密和解密數(shù)據(jù),而非對(duì)稱加密則有兩份密鑰,分別是公鑰和私鑰,用公鑰加密的數(shù)據(jù),要用私鑰才能解密;用私鑰加密的數(shù)據(jù),要用公鑰才能解密。這里的非對(duì)稱加密就是我們所熟知的RSA,要了解RSA背后的數(shù)學(xué)原理可以參考RSA算法原理(一)(二)

二、從App Store安裝APP

這個(gè)過程的簽名方式相對(duì)簡單一些。蘋果官方生成一對(duì)公私鑰,在蘋果手機(jī)里面內(nèi)置一個(gè)公鑰,私鑰由蘋果后臺(tái)保存,我們傳App上AppStore時(shí),蘋果后臺(tái)用私鑰對(duì)App數(shù)據(jù)值的MD5值進(jìn)行簽名,iOS系統(tǒng)下載這個(gè)App后,用公鑰驗(yàn)證這個(gè)簽名,若簽名正確,這個(gè)App肯定由蘋果后臺(tái)認(rèn)證的,并且沒有被修改過,也就達(dá)到了蘋果的需求:保證安裝的每一個(gè)App都是經(jīng)過蘋果認(rèn)證允許的。

三、其他方式安裝APP

在實(shí)際工作當(dāng)中,我們還有一些其他的方式把APP安裝到手機(jī)上:
開發(fā)App時(shí)可以直接把開發(fā)中的應(yīng)用安裝進(jìn)手機(jī)調(diào)試;
In-House企業(yè)內(nèi)部分發(fā),可以直接安裝企業(yè)證書簽名后的App;
AD-Hoc相當(dāng)于企業(yè)分發(fā)的限制版,限制安裝設(shè)備數(shù)量,較少用。

蘋果對(duì)這幾種方式安裝的控制過程就變得復(fù)雜了,即要保證APP的安裝時(shí)經(jīng)過蘋果認(rèn)證的,又要控制APP不能被隨便安裝到其他設(shè)備上,以及一些其他的權(quán)限,為了達(dá)到這樣的目的,蘋果采用的流程大致是這個(gè)樣子

基本流程:
屏幕快照 .png

1、在Mac上生成一對(duì)公私鑰,這里稱公鑰M,私鑰M。
2、蘋果自己有固定的一對(duì)公私鑰,跟上面AppStore例子一樣,私鑰在蘋果后臺(tái),公鑰內(nèi)置在每個(gè)iOS設(shè)備上,這里稱為公鑰A,私鑰A。
3、把公鑰M上傳到蘋果后臺(tái),用蘋果后臺(tái)里的私鑰A去簽名公鑰M。得到一份數(shù)據(jù)包含了公鑰M以及其簽名(也就是公鑰的HASH值),把這份數(shù)據(jù)稱為證書。
4、在開發(fā)時(shí),編譯完一個(gè)App后,用本地的私鑰M對(duì)這個(gè)App進(jìn)行簽名,同時(shí)把第三步得到的證書一起打包進(jìn)App里,安裝到手機(jī)。
5、在安裝時(shí),iOS系統(tǒng)取得證書,通過系統(tǒng)內(nèi)置的公鑰A,去驗(yàn)證證書的數(shù)字簽名是否正確。
驗(yàn)證證書確保公鑰M是蘋果認(rèn)證過的,再用公鑰M去驗(yàn)證App的簽名,這里就間接驗(yàn)證了這個(gè)App的安裝行為是否經(jīng)過蘋果官方允許。(這里只驗(yàn)證安裝行為,不驗(yàn)證App是否被改動(dòng),因?yàn)殚_發(fā)階段App內(nèi)容總是不斷變化的,蘋果不需要管)。

最終流程:

上述流程只解決了上面第一個(gè)需求,也就是需要經(jīng)過蘋果允許才可以安裝,還未解決第二個(gè)避免被濫用的問題。怎么解決呢?蘋果加了兩個(gè)限制,一是限制在蘋果后臺(tái)注冊(cè)過的設(shè)備才可以安裝;二是限制簽名只能針對(duì)某一個(gè)具體的App。
那么它到底是怎么添加這兩個(gè)限制的呢?在上述第三步,蘋果用私鑰A簽名我們的本地公鑰M時(shí),實(shí)際上除了簽名本地公鑰M外,還可以加上無限多數(shù)據(jù),這些數(shù)據(jù)都可以保證是經(jīng)過蘋果官方認(rèn)證的,不會(huì)有被篡改的可能。


屏幕快照 .png

可以把允許安裝的設(shè)備ID列表和App對(duì)應(yīng)的AppID等數(shù)據(jù),都在第三步這里跟公鑰M一起組成證書,再用蘋果私鑰A對(duì)這個(gè)證書簽名。在最后第5步驗(yàn)證時(shí)就可以拿到設(shè)備ID列表,判斷當(dāng)前設(shè)備是否符合要求。根據(jù)數(shù)字簽名的原理,只要數(shù)字簽名通過驗(yàn)證,第5步這里的設(shè)備IDs/AppID/公鑰M就都是經(jīng)過蘋果認(rèn)證的,無法被修改,蘋果就可以限制可安裝的設(shè)備和APP,避免濫用。

到這里這個(gè)證書已經(jīng)變得很復(fù)雜了,有很多額外信息,實(shí)際上除了設(shè)備ID/AppID,還有其他信息也需要在這里用蘋果簽名,像App里iCloud、push、后臺(tái)運(yùn)行 等權(quán)限蘋果都想控制,蘋果把這些權(quán)限開關(guān)統(tǒng)稱為Entitlements,它也需要通過簽名去授權(quán)。
實(shí)際上一個(gè)證書本來就有規(guī)定的格式規(guī)范,上面我們把各種額外的信息塞入證書里是不合適的,于是蘋果另外搞了一個(gè)東西,叫Provisioning Profile,一個(gè)Provisioning Profile里就包含了證書以及上述提到的所有額外信息,以及所有信息的簽名。

所以,就成這樣了:
在 Mac 上生成一對(duì)公私鑰,這里稱為公鑰M,私鑰M。
蘋果自己有固定的一對(duì)公私鑰,跟上面 AppStore 例子一樣,私鑰在蘋果后臺(tái),公鑰在每個(gè)iOS設(shè)備上。這里稱為公鑰A,私鑰A。A:Apple
把公鑰M傳到蘋果后臺(tái),用蘋果后臺(tái)里的私鑰A去簽名公鑰M。得到一份數(shù)據(jù)包含了公鑰M以及其簽名,把這份數(shù)據(jù)稱為證書。
在蘋果后臺(tái)申請(qǐng)AppID,配置好設(shè)備ID列表和APP可使用的權(quán)限,再加上第3步的證書,組成的數(shù)據(jù)用私鑰A簽名,把數(shù)據(jù)和簽名一起組成一個(gè)Provisioning Profile文件,下載到本地Mac開發(fā)機(jī)。
在開發(fā)時(shí),編譯完一個(gè)APP后,用本地的私鑰M對(duì)這個(gè)APP進(jìn)行簽名,同時(shí)把第4步得到的Provisioning Profile文件打包進(jìn)APP里,文件名為 embedded.mobileprovision,把APP安裝到手機(jī)上。
在安裝時(shí),iOS系統(tǒng)取得證書,通過系統(tǒng)內(nèi)置的公鑰A,去驗(yàn)證 embedded.mobileprovision的數(shù)字簽名是否正確,里面的證書簽名也會(huì)再驗(yàn)一遍。
確保了embedded.mobileprovision里的數(shù)據(jù)都是蘋果授權(quán)以后,就可以取出里面的數(shù)據(jù),做各種驗(yàn)證,包括用公鑰M驗(yàn)證APP簽名,驗(yàn)證設(shè)備ID是否在ID列表上,AppID是否對(duì)應(yīng)得上,權(quán)限開關(guān)是否跟APP里的Entitlements對(duì)應(yīng)等。

開發(fā)者證書從簽名到認(rèn)證最終蘋果采用的流程大致是這樣,還有一些細(xì)節(jié)像證書有效期/證書類型等就不細(xì)說了。

上面的步驟對(duì)應(yīng)到我們平常具體的操作和概念是這樣的:

第1步對(duì)應(yīng)的是keychain里的“從證書頒發(fā)機(jī)構(gòu)請(qǐng)求證書”,這里就本地生成了一對(duì)公私鑰,保存的CertificateSigningRequest就是公鑰,私鑰保存在本地電腦里。
第2步蘋果自己處理,我們不用管。
第3步對(duì)應(yīng)把CertificateSigningRequest傳到蘋果后臺(tái)生成證書,并下載到本地。這時(shí)本地有兩個(gè)證書,一個(gè)是第1步生成的,一個(gè)是這里下載回來的,keychain會(huì)把這兩個(gè)證書關(guān)聯(lián)起來,因?yàn)樗鼈兊墓借€是對(duì)應(yīng)的,在Xcode選擇下載回來的證書的時(shí),實(shí)際上會(huì)找到keychain里面對(duì)應(yīng)的私鑰去簽名。這里私鑰只有生成它的這臺(tái)Mac才有,如果別的Mac也要編譯簽名這個(gè)App,把私鑰導(dǎo)出給其他Mac使用,在keychain里面導(dǎo)出私鑰,就會(huì)存成.p12文件,其他Mac打開后就導(dǎo)入私鑰。
第4步都是在蘋果網(wǎng)站上操作,配置AppID、權(quán)限、設(shè)備等,最后下載 Provisioning Profile文件。
第5步Xcode會(huì)通過第3步下載回來的證書(存著本地公鑰),在本地找到對(duì)應(yīng)的私鑰(第1步生成的),用本地私鑰去簽名App,并把Provisioning Profile文件命名為embedded.mobileprovision一起打包進(jìn)去。這里對(duì)App的簽名數(shù)據(jù)保存分為兩部分,Mach-O可執(zhí)行文件會(huì)把簽名直接寫入這個(gè)文件里,其他資源文件則會(huì)保存在_CodeSignature目錄下。
第6、7步的打包和驗(yàn)證都是 Xcode 和 iOS 系統(tǒng)自動(dòng)做的事。

四、總結(jié)

幾個(gè)概念:
證書:內(nèi)容是公鑰或私鑰,由其他機(jī)構(gòu)對(duì)其簽名組成的數(shù)據(jù)包。
Entitlements:包含了App權(quán)限開關(guān)列表。
CertificateSigningRequest:本地公鑰。
.p12:本地私鑰,可以導(dǎo)入到其他電腦。
Provisioning Profile:包含了 證書/Entitlements 等數(shù)據(jù),并由蘋果后臺(tái)私鑰簽名的數(shù)據(jù)包。

其他發(fā)布方式

前面以開發(fā)包為例子說了簽名和驗(yàn)證的流程,另外兩種方式In-House企業(yè)簽名和AD-Hoc流程也是差不多的,只是企業(yè)簽名不限制安裝的設(shè)備數(shù),另外需要用戶在iOS系統(tǒng)設(shè)置上手動(dòng)點(diǎn)擊信任這個(gè)企業(yè)才能通過驗(yàn)證。
而AppStore的簽名驗(yàn)證方式有些不一樣,前面我們說到最簡單的簽名方式,蘋果在后臺(tái)直接用私鑰簽名App就可以了,實(shí)際上蘋果確實(shí)是這樣做的,如果去下載一個(gè)AppStore的安裝包,會(huì)發(fā)現(xiàn)它里面是沒有embedded.mobileprovision文件的,也就是它安裝和啟動(dòng)的流程是不依賴這個(gè)文件,驗(yàn)證流程也就跟上述幾種類型不一樣了。

因?yàn)樯蟼鞯紸ppStore的包蘋果會(huì)重新對(duì)內(nèi)容加密,原來的本地私鑰簽名就沒有用了,需要重新簽名,從AppStore下載的包蘋果也并不打算控制它的有效期,不需要內(nèi)置一個(gè)embedded.mobileprovision去做校驗(yàn),直接在蘋果用后臺(tái)的私鑰重新簽名,iOS安裝時(shí)用本地公鑰驗(yàn)證App簽名就可以了。

那為什么發(fā)布AppStore的包還是要跟開發(fā)版一樣搞各種證書和Provisioning Profile,因?yàn)樘O果想做統(tǒng)一管理,Provisioning Profile里包含一些權(quán)限控制,AppID 的檢驗(yàn)等,蘋果不想在上傳AppStore 包時(shí)重新用另一種協(xié)議做一遍這些驗(yàn)證,就不如統(tǒng)一把這部分放在 Provisioning Profile里,上傳AppStore時(shí)只要用同樣的流程驗(yàn)證這個(gè) Provisioning Profile是否合法就可以了。

所以 App 上傳到AppStore后,就跟你的 證書 / Provisioning Profile 都沒有關(guān)系了,無論他們是否過期或被廢除,都不會(huì)影響AppStore 上的安裝包。

以上就是整個(gè)簽名的大致分析,歡迎大家留言及交流!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容