xcode 的一套 簽名 證書(shū)機(jī)制,從一開(kāi)始的彈框fix issure ,到xcode8 以后 Automatically manage signing,蘋(píng)果在試圖讓這一套簽名 證書(shū)機(jī)制變得透明化.本文來(lái)講講這背后的原理.
blog.gocy.tech/2017/04/24/iOS-Signing/
準(zhǔn)備工作
首先我們應(yīng)該了解,什么是簽名(signature) 什么是證書(shū) (certificate)
簽名
在數(shù)據(jù)傳輸?shù)倪^(guò)程中榔至,我們最關(guān)心的就是兩件事:可靠性和數(shù)據(jù)完整性。我們可不想打開(kāi)身份不明的開(kāi)發(fā)者的程序欺劳,或是打開(kāi)已經(jīng)損壞/被修改過(guò)的程序。為校驗(yàn)數(shù)據(jù)包的完整性铅鲤,數(shù)據(jù)發(fā)送端通常會(huì)利用MD5 算法來(lái)將需要發(fā)送的信息進(jìn)行“摘要”划提,而后發(fā)送端利用私鑰將摘要加密,得到簽名邢享,連同數(shù)據(jù)包一起發(fā)送給接受方鹏往,接受方收到數(shù)據(jù)包和簽名后,接受方利用公鑰解密簽名骇塘,拿到發(fā)送方的 MD5 數(shù)據(jù)伊履,再對(duì)數(shù)據(jù)包進(jìn)行 MD5 操作并與發(fā)送方 MD5 進(jìn)行對(duì)比,以驗(yàn)證數(shù)據(jù)完整性款违。上述的過(guò)程唐瀑,摘要的加、解密步驟插爹,驗(yàn)證了數(shù)據(jù)發(fā)送方的身份哄辣,而兩次 MD5 操作驗(yàn)證了數(shù)據(jù)完整性。
一般僅對(duì)md5加密是為了減少加密解密的時(shí)間.
證書(shū)
上述簽名過(guò)程看起來(lái)已經(jīng)足夠安全了赠尾,接受方通過(guò)發(fā)送方公鑰對(duì)簽名進(jìn)行解密力穗,就能夠驗(yàn)證數(shù)據(jù)包發(fā)送者的身份。但這都是建立在我們手中的公鑰是正確的前提下的气嫁,一旦我們的公鑰被替換当窗,我們便無(wú)法解開(kāi)對(duì)應(yīng)發(fā)送方的簽名,但更危險(xiǎn)的是寸宵,偽造公鑰的第三方崖面,可以發(fā)送數(shù)據(jù)給我們,而我們拿著“假”的公鑰邓馒,能正確解開(kāi)其簽名嘶朱,從而誤以為該數(shù)據(jù)源于我們所信任的發(fā)送方。那么如何確保公鑰的安全性呢光酣?一個(gè)很自然的想法就是為公鑰進(jìn)行加密疏遏。
通常的做法是,我們找到一個(gè)可信任的數(shù)字證書(shū)認(rèn)證機(jī)構(gòu)(Certificate Authrotiy,簡(jiǎn)稱(chēng) CA)财异,將我們自己的公鑰交給 CA,隨后該機(jī)構(gòu)運(yùn)用上述簽名類(lèi)似流程戳寸,用 CA 私鑰加密我們的公鑰,然后暴露一個(gè) CA 公鑰供使用者驗(yàn)解密袖瞻。這個(gè)被 CA 私鑰所加密的我們自己的密鑰(當(dāng)然還有一些像有效期、用戶(hù)信息等其它內(nèi)容)一般被稱(chēng)為證書(shū)拆吆。但這里也引入了另一個(gè)問(wèn)題:解密證書(shū)所需要的公鑰聋迎,同樣存在被冒充的風(fēng)險(xiǎn)枣耀,如何規(guī)避這其中的風(fēng)險(xiǎn)呢?這里我并沒(méi)有查到詳細(xì)的資料捞奕,我想牺堰,這里公鑰的正確性,便是由這些具有公信力的 CA 所保證的颅围,而平時(shí)我們自己做業(yè)務(wù),在網(wǎng)絡(luò)安全方面扒俯,是難以達(dá)到這樣的安全標(biāo)準(zhǔn)的一疯。
小結(jié)
有了上面的知識(shí)儲(chǔ)備 ,我們可以很容易地了解到,想在網(wǎng)絡(luò)上安全的傳輸數(shù)據(jù),我們一般需要兩對(duì)公私鑰,業(yè)務(wù)服務(wù)器的公私鑰和CA的公私鑰.下面我們來(lái)看看蘋(píng)果是如何執(zhí)行這一流程的.
ios的簽名證書(shū)機(jī)制
接下來(lái)我們看看 iOS 上的簽名機(jī)制,下文只討論 AppStore 以及本地 build 這兩種情況.
為什么需要
相信大家入門(mén)程序員的時(shí)候掌猛,大多都是在 VC 或 VS 上打 C/C++ 入門(mén)的,那時(shí)候一切都很簡(jiǎn)單荔茬,code-build-link-run竹海,并沒(méi)有什么認(rèn)證過(guò)程,而由于蘋(píng)果對(duì)其生態(tài)圈管理嚴(yán)格孔飒,任何在 iOS 上跑的程序都需要經(jīng)過(guò)蘋(píng)果的“同意”。所以桂对,不論是 AppStore鸠匀,還是 Xcode 本地 build 的項(xiàng)目,蘋(píng)果都需要驗(yàn)證這個(gè)應(yīng)用的身份宅此。
AppStore
從 AppStore 下載的應(yīng)用驗(yàn)證流程非常簡(jiǎn)單爬范,Apple 用私鑰簽名 App 后,iOS 設(shè)備下載簽名和 App,利用 Apple 公鑰驗(yàn)證簽名并安裝痢法。由于 iOS 設(shè)備內(nèi)置 Apple 公鑰,而數(shù)據(jù)包直接由蘋(píng)果服務(wù)器下載蘸炸,因此此處的安全是有保障的竣况,同時(shí)获洲,簽名驗(yàn)證能通過(guò)淹禾,證明該安裝包是從蘋(píng)果服務(wù)器下載的茴扁,也就滿(mǎn)足了蘋(píng)果對(duì) App 安裝的控制峭火。
Xcode build
從 AppStore 分發(fā)應(yīng)用的過(guò)程是非常簡(jiǎn)單的,但在日常開(kāi)發(fā)中纺且,上述的驗(yàn)證過(guò)程是不能被接受的稍浆,我們不可能每次 build 都將應(yīng)用打包上傳猜嘱,經(jīng)過(guò)蘋(píng)果的加密后再下載運(yùn)行恐仑。于是蘋(píng)果想出了這么一套認(rèn)證體系裳仆。
從 AppStore 下載應(yīng)用時(shí),iOS 設(shè)備會(huì)用 Apple 公鑰驗(yàn)證應(yīng)用安裝包歧斟,以確保該應(yīng)用來(lái)源于 Apple 服務(wù)器静袖。而在本地調(diào)試模式下,設(shè)備會(huì)把對(duì) App 的驗(yàn)證队橙,改為對(duì)開(kāi)發(fā)者的驗(yàn)證.
此處的開(kāi)發(fā)者賬號(hào)捐康,就是在 Apple Developer Center 中所申請(qǐng)的開(kāi)發(fā)者賬號(hào),一旦信任之后贮匕,每次 build 的時(shí)候花枫,iOS 設(shè)備就將驗(yàn)證該開(kāi)發(fā)者身份,而不是驗(yàn)證你 build 的 App敦锌。如此一來(lái)佳簸,便省去了應(yīng)用包上傳、下載的過(guò)程伶丐。我們知道疯特,驗(yàn)證 App 是通過(guò)簽名機(jī)制,來(lái)確定安裝包來(lái)源的录别,而此處的驗(yàn)證開(kāi)發(fā)者身份,又是怎樣的機(jī)制呢葫男?
驗(yàn)證開(kāi)發(fā)者
這里面主要是做兩件事:
1.iOS 設(shè)備用 Apple 公鑰解密證書(shū)崔列,所拿到的本地證書(shū),必定是經(jīng)過(guò) Apple 服務(wù)器簽名的盈咳,也就是說(shuō)边翼,這里保證了開(kāi)發(fā)者是經(jīng)過(guò)蘋(píng)果認(rèn)證的。
2.上一步拿到的公鑰丈积,用于解密 App 簽名债鸡,若解密成功且驗(yàn)證通過(guò),證明該 App 確實(shí)是由該開(kāi)發(fā)者構(gòu)建的,也就保證了 App 的安全性
流程圖如下:
上述的流程唯一問(wèn)題是莫秆,這個(gè)密鑰是在本地生成的悔详,如果更換了電腦,本地的密鑰對(duì)就會(huì)改變缝驳。這時(shí)候归苍,你需要將舊 mac 上的證書(shū)導(dǎo)出,并安裝到新的電腦上夏伊。導(dǎo)出p12文件,拷貝到另一臺(tái)電腦.
一一對(duì)應(yīng)
我們能在 mac 的鑰匙串訪問(wèn)中找到本地的密鑰證書(shū)吻氧,但其它的東西似乎就不是那么地可見(jiàn)了咏连,對(duì)于一般的開(kāi)發(fā)者來(lái)說(shuō)祟滴,我們更熟悉的概念應(yīng)該是 Provisioning Profile歌溉,Xcode 8.3 提供了很友好的可視化界面來(lái)讓我們查看 Provisioning Profile 里面的東西。
我們可以看到埠偿,Provisioning Profile 中包含了開(kāi)發(fā)組名冠蒋、組內(nèi)設(shè)備乾胶、應(yīng)用 Capabilities 配置等等,這些都是決定應(yīng)用行為的一些信息斩郎。我們還注意到喻频,Provisioning Profile 中包含了一個(gè) Certificates,這個(gè)證書(shū)就是我們?cè)谏厦嬲f(shuō)的本地公鑰證書(shū)锻煌。其實(shí)在 Xcode 構(gòu)建安裝 App 時(shí)姻蚓,我們不是直接將本地證書(shū)裝入 iOS 設(shè)備中,而是將 Provisioninng Profile 裝入設(shè)備中捂龄。如果我們開(kāi)啟了 Automatically manage signing加叁,Provisioning Profile 的生成和下載都是由 Xcode 自動(dòng)完成的,但其實(shí)刀脏,Provisioning Profile 的創(chuàng)建過(guò)程超凳,和本地密鑰證書(shū)的過(guò)程極其相似耀态。如果你是付費(fèi)開(kāi)發(fā)者暂雹,或是加入了企業(yè)開(kāi)發(fā) team杭跪,你就能在證書(shū)管理看到所有的 Provisioning Profile,每個(gè) Provisioning Profile 與 teamId 和 bundleId 唯一對(duì)應(yīng)系奉。類(lèi)似的姑廉,你也需要將它下載到本地,只不過(guò)這一步很多時(shí)候 Xcode 替我們完成了.
由于 Provisioning Profile 在 Apple 后臺(tái)生成萌踱,很自然的号阿,它也會(huì)被 Apple 私鑰加密,而它的作用主要有兩點(diǎn):
校驗(yàn) App 的各項(xiàng)參數(shù)(如 Capabilities园担,后臺(tái)獲取枯夜、通用鏈接等配置)是否與蘋(píng)果后臺(tái)定義的一致卤档。
其中包含的 Certificates程剥,也就是本地證書(shū),用于校驗(yàn)開(kāi)發(fā)者身份舔腾。
所以搂擦,我們可以將上一部分的圖進(jìn)行一些細(xì)化:
總結(jié)
至此瀑踢,我們大致了解了 AppStore 以及 Xcode 本地構(gòu)建時(shí)才避,iOS 所使用的身份驗(yàn)證機(jī)制了氨距。整套驗(yàn)證流程其實(shí)就是對(duì)非對(duì)稱(chēng)加密的封裝和應(yīng)用,只是蘋(píng)果為驗(yàn)證項(xiàng)目信息楞遏,又不想與“證書(shū)”這一專(zhuān)有名詞混淆首昔,加入了一個(gè) Provisioning Profile 的概念。如果你熟悉簽名预鬓、證書(shū)的概念撬陵,那么其實(shí)理解這一套驗(yàn)證機(jī)制也就并不困難了。