iOS證書(shū)簽名原理分析

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

一、背景

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

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

二烁峭、從App Store安裝APP

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

三续担、其他方式安裝APP

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

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

基本流程:
屏幕快照 .png

1始衅、在Mac上生成一對(duì)公私鑰冷蚂,這里稱公鑰M,私鑰M汛闸。
2蝙茶、蘋(píng)果自己有固定的一對(duì)公私鑰,跟上面AppStore例子一樣诸老,私鑰在蘋(píng)果后臺(tái)隆夯,公鑰內(nèi)置在每個(gè)iOS設(shè)備上,這里稱為公鑰A别伏,私鑰A蹄衷。
3、把公鑰M上傳到蘋(píng)果后臺(tái)厘肮,用蘋(píng)果后臺(tái)里的私鑰A去簽名公鑰M愧口。得到一份數(shù)據(jù)包含了公鑰M以及其簽名(也就是公鑰的HASH值),把這份數(shù)據(jù)稱為證書(shū)类茂。
4耍属、在開(kāi)發(fā)時(shí),編譯完一個(gè)App后巩检,用本地的私鑰M對(duì)這個(gè)App進(jìn)行簽名厚骗,同時(shí)把第三步得到的證書(shū)一起打包進(jìn)App里,安裝到手機(jī)碴巾。
5溯捆、在安裝時(shí),iOS系統(tǒng)取得證書(shū)厦瓢,通過(guò)系統(tǒng)內(nèi)置的公鑰A提揍,去驗(yàn)證證書(shū)的數(shù)字簽名是否正確。
驗(yàn)證證書(shū)確保公鑰M是蘋(píng)果認(rèn)證過(guò)的煮仇,再用公鑰M去驗(yàn)證App的簽名劳跃,這里就間接驗(yàn)證了這個(gè)App的安裝行為是否經(jīng)過(guò)蘋(píng)果官方允許。(這里只驗(yàn)證安裝行為浙垫,不驗(yàn)證App是否被改動(dòng)刨仑,因?yàn)殚_(kāi)發(fā)階段App內(nèi)容總是不斷變化的,蘋(píng)果不需要管)夹姥。

最終流程:

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


屏幕快照 .png

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

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

所以,就成這樣了:
在 Mac 上生成一對(duì)公私鑰垒棋,這里稱為公鑰M卒煞,私鑰M。
蘋(píng)果自己有固定的一對(duì)公私鑰捕犬,跟上面 AppStore 例子一樣跷坝,私鑰在蘋(píng)果后臺(tái)酵镜,公鑰在每個(gè)iOS設(shè)備上。這里稱為公鑰A柴钻,私鑰A淮韭。A:Apple
把公鑰M傳到蘋(píng)果后臺(tái),用蘋(píng)果后臺(tái)里的私鑰A去簽名公鑰M贴届。得到一份數(shù)據(jù)包含了公鑰M以及其簽名靠粪,把這份數(shù)據(jù)稱為證書(shū)。
在蘋(píng)果后臺(tái)申請(qǐng)AppID毫蚓,配置好設(shè)備ID列表和APP可使用的權(quán)限占键,再加上第3步的證書(shū),組成的數(shù)據(jù)用私鑰A簽名元潘,把數(shù)據(jù)和簽名一起組成一個(gè)Provisioning Profile文件畔乙,下載到本地Mac開(kāi)發(fā)機(jī)。
在開(kāi)發(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)取得證書(shū)难述,通過(guò)系統(tǒng)內(nèi)置的公鑰A,去驗(yàn)證 embedded.mobileprovision的數(shù)字簽名是否正確吐句,里面的證書(shū)簽名也會(huì)再驗(yàn)一遍胁后。
確保了embedded.mobileprovision里的數(shù)據(jù)都是蘋(píng)果授權(quán)以后,就可以取出里面的數(shù)據(jù)嗦枢,做各種驗(yàn)證择同,包括用公鑰M驗(yàn)證APP簽名,驗(yàn)證設(shè)備ID是否在ID列表上净宵,AppID是否對(duì)應(yīng)得上敲才,權(quán)限開(kāi)關(guān)是否跟APP里的Entitlements對(duì)應(yīng)等。

開(kāi)發(fā)者證書(shū)從簽名到認(rèn)證最終蘋(píng)果采用的流程大致是這樣择葡,還有一些細(xì)節(jié)像證書(shū)有效期/證書(shū)類(lèi)型等就不細(xì)說(shuō)了紧武。

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

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

四汗菜、總結(jié)

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

其他發(fā)布方式

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

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匾浪,隨后出現(xiàn)的幾起案子畜吊,更是在濱河造成了極大的恐慌,老刑警劉巖户矢,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玲献,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)捌年,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)瓢娜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人礼预,你說(shuō)我怎么就攤上這事眠砾。” “怎么了托酸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵褒颈,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我励堡,道長(zhǎng)谷丸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任应结,我火速辦了婚禮刨疼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鹅龄。我一直安慰自己揩慕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布扮休。 她就那樣靜靜地躺著迎卤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪玷坠。 梳的紋絲不亂的頭發(fā)上蜗搔,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音侨糟,去河邊找鬼。 笑死瘩燥,一個(gè)胖子當(dāng)著我的面吹牛秕重,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厉膀,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溶耘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了服鹅?” 一聲冷哼從身側(cè)響起凳兵,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎企软,沒(méi)想到半個(gè)月后庐扫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年形庭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铅辞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡萨醒,死狀恐怖斟珊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情富纸,我是刑警寧澤囤踩,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站晓褪,受9級(jí)特大地震影響堵漱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辞州,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一怔锌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧变过,春花似錦埃元、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至崭孤,卻和暖如春类嗤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辨宠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工遗锣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嗤形。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓精偿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赋兵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笔咽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355