xcode 的一套 簽名 證書機(jī)制,從一開始的彈框fix issure ,到xcode8 以后 Automatically manage signing,蘋果在試圖讓這一套簽名 證書機(jī)制變得透明化.本文來講講這背后的原理.
blog.gocy.tech/2017/04/24/iOS-Signing/
準(zhǔn)備工作
首先我們應(yīng)該了解,什么是簽名(signature) 什么是證書 (certificate)
簽名
在數(shù)據(jù)傳輸?shù)倪^程中,我們最關(guān)心的就是兩件事:可靠性和數(shù)據(jù)完整性。我們可不想打開身份不明的開發(fā)者的程序,或是打開已經(jīng)損壞/被修改過的程序。為校驗(yàn)數(shù)據(jù)包的完整性,數(shù)據(jù)發(fā)送端通常會利用MD5 算法來將需要發(fā)送的信息進(jìn)行“摘要”,而后發(fā)送端利用私鑰將摘要加密,得到簽名,連同數(shù)據(jù)包一起發(fā)送給接受方,接受方收到數(shù)據(jù)包和簽名后,接受方利用公鑰解密簽名,拿到發(fā)送方的 MD5 數(shù)據(jù),再對數(shù)據(jù)包進(jìn)行 MD5 操作并與發(fā)送方 MD5 進(jìn)行對比,以驗(yàn)證數(shù)據(jù)完整性。上述的過程,摘要的加、解密步驟,驗(yàn)證了數(shù)據(jù)發(fā)送方的身份,而兩次 MD5 操作驗(yàn)證了數(shù)據(jù)完整性。
一般僅對md5加密是為了減少加密解密的時間.

證書
上述簽名過程看起來已經(jīng)足夠安全了,接受方通過發(fā)送方公鑰對簽名進(jìn)行解密,就能夠驗(yàn)證數(shù)據(jù)包發(fā)送者的身份。但這都是建立在我們手中的公鑰是正確的前提下的,一旦我們的公鑰被替換,我們便無法解開對應(yīng)發(fā)送方的簽名,但更危險的是,偽造公鑰的第三方,可以發(fā)送數(shù)據(jù)給我們,而我們拿著“假”的公鑰,能正確解開其簽名,從而誤以為該數(shù)據(jù)源于我們所信任的發(fā)送方。那么如何確保公鑰的安全性呢?一個很自然的想法就是為公鑰進(jìn)行加密。
通常的做法是,我們找到一個可信任的數(shù)字證書認(rèn)證機(jī)構(gòu)(Certificate Authrotiy,簡稱 CA),將我們自己的公鑰交給 CA,隨后該機(jī)構(gòu)運(yùn)用上述簽名類似流程,用 CA 私鑰加密我們的公鑰,然后暴露一個 CA 公鑰供使用者驗(yàn)解密。這個被 CA 私鑰所加密的我們自己的密鑰(當(dāng)然還有一些像有效期、用戶信息等其它內(nèi)容)一般被稱為證書。但這里也引入了另一個問題:解密證書所需要的公鑰,同樣存在被冒充的風(fēng)險,如何規(guī)避這其中的風(fēng)險呢?這里我并沒有查到詳細(xì)的資料,我想,這里公鑰的正確性,便是由這些具有公信力的 CA 所保證的,而平時我們自己做業(yè)務(wù),在網(wǎng)絡(luò)安全方面,是難以達(dá)到這樣的安全標(biāo)準(zhǔn)的。
小結(jié)
有了上面的知識儲備 ,我們可以很容易地了解到,想在網(wǎng)絡(luò)上安全的傳輸數(shù)據(jù),我們一般需要兩對公私鑰,業(yè)務(wù)服務(wù)器的公私鑰和CA的公私鑰.下面我們來看看蘋果是如何執(zhí)行這一流程的.
ios的簽名證書機(jī)制
接下來我們看看 iOS 上的簽名機(jī)制,下文只討論 AppStore 以及本地 build 這兩種情況.
為什么需要
相信大家入門程序員的時候,大多都是在 VC 或 VS 上打 C/C++ 入門的,那時候一切都很簡單,code-build-link-run,并沒有什么認(rèn)證過程,而由于蘋果對其生態(tài)圈管理嚴(yán)格,任何在 iOS 上跑的程序都需要經(jīng)過蘋果的“同意”。所以,不論是 AppStore,還是 Xcode 本地 build 的項(xiàng)目,蘋果都需要驗(yàn)證這個應(yīng)用的身份。
AppStore
從 AppStore 下載的應(yīng)用驗(yàn)證流程非常簡單,Apple 用私鑰簽名 App 后,iOS 設(shè)備下載簽名和 App,利用 Apple 公鑰驗(yàn)證簽名并安裝。由于 iOS 設(shè)備內(nèi)置 Apple 公鑰,而數(shù)據(jù)包直接由蘋果服務(wù)器下載,因此此處的安全是有保障的,同時,簽名驗(yàn)證能通過,證明該安裝包是從蘋果服務(wù)器下載的,也就滿足了蘋果對 App 安裝的控制。

Xcode build
從 AppStore 分發(fā)應(yīng)用的過程是非常簡單的,但在日常開發(fā)中,上述的驗(yàn)證過程是不能被接受的,我們不可能每次 build 都將應(yīng)用打包上傳,經(jīng)過蘋果的加密后再下載運(yùn)行。于是蘋果想出了這么一套認(rèn)證體系。
從 AppStore 下載應(yīng)用時,iOS 設(shè)備會用 Apple 公鑰驗(yàn)證應(yīng)用安裝包,以確保該應(yīng)用來源于 Apple 服務(wù)器。而在本地調(diào)試模式下,設(shè)備會把對 App 的驗(yàn)證,改為對開發(fā)者的驗(yàn)證.

此處的開發(fā)者賬號,就是在 Apple Developer Center 中所申請的開發(fā)者賬號,一旦信任之后,每次 build 的時候,iOS 設(shè)備就將驗(yàn)證該開發(fā)者身份,而不是驗(yàn)證你 build 的 App。如此一來,便省去了應(yīng)用包上傳、下載的過程。我們知道,驗(yàn)證 App 是通過簽名機(jī)制,來確定安裝包來源的,而此處的驗(yàn)證開發(fā)者身份,又是怎樣的機(jī)制呢?
驗(yàn)證開發(fā)者
這里面主要是做兩件事:
1.iOS 設(shè)備用 Apple 公鑰解密證書,所拿到的本地證書,必定是經(jīng)過 Apple 服務(wù)器簽名的,也就是說,這里保證了開發(fā)者是經(jīng)過蘋果認(rèn)證的。
2.上一步拿到的公鑰,用于解密 App 簽名,若解密成功且驗(yàn)證通過,證明該 App 確實(shí)是由該開發(fā)者構(gòu)建的,也就保證了 App 的安全性
流程圖如下:

上述的流程唯一問題是,這個密鑰是在本地生成的,如果更換了電腦,本地的密鑰對就會改變。這時候,你需要將舊 mac 上的證書導(dǎo)出,并安裝到新的電腦上。導(dǎo)出p12文件,拷貝到另一臺電腦.
一一對應(yīng)
我們能在 mac 的鑰匙串訪問中找到本地的密鑰證書,但其它的東西似乎就不是那么地可見了,對于一般的開發(fā)者來說,我們更熟悉的概念應(yīng)該是 Provisioning Profile,Xcode 8.3 提供了很友好的可視化界面來讓我們查看 Provisioning Profile 里面的東西。


我們可以看到,Provisioning Profile 中包含了開發(fā)組名、組內(nèi)設(shè)備、應(yīng)用 Capabilities 配置等等,這些都是決定應(yīng)用行為的一些信息。我們還注意到,Provisioning Profile 中包含了一個 Certificates,這個證書就是我們在上面說的本地公鑰證書。其實(shí)在 Xcode 構(gòu)建安裝 App 時,我們不是直接將本地證書裝入 iOS 設(shè)備中,而是將 Provisioninng Profile 裝入設(shè)備中。如果我們開啟了 Automatically manage signing,Provisioning Profile 的生成和下載都是由 Xcode 自動完成的,但其實(shí),Provisioning Profile 的創(chuàng)建過程,和本地密鑰證書的過程極其相似。如果你是付費(fèi)開發(fā)者,或是加入了企業(yè)開發(fā) team,你就能在證書管理看到所有的 Provisioning Profile,每個 Provisioning Profile 與 teamId 和 bundleId 唯一對應(yīng)。類似的,你也需要將它下載到本地,只不過這一步很多時候 Xcode 替我們完成了.

由于 Provisioning Profile 在 Apple 后臺生成,很自然的,它也會被 Apple 私鑰加密,而它的作用主要有兩點(diǎn):
校驗(yàn) App 的各項(xiàng)參數(shù)(如 Capabilities,后臺獲取、通用鏈接等配置)是否與蘋果后臺定義的一致。
其中包含的 Certificates,也就是本地證書,用于校驗(yàn)開發(fā)者身份。
所以,我們可以將上一部分的圖進(jìn)行一些細(xì)化:

總結(jié)
至此,我們大致了解了 AppStore 以及 Xcode 本地構(gòu)建時,iOS 所使用的身份驗(yàn)證機(jī)制了。整套驗(yàn)證流程其實(shí)就是對非對稱加密的封裝和應(yīng)用,只是蘋果為驗(yàn)證項(xiàng)目信息,又不想與“證書”這一專有名詞混淆,加入了一個 Provisioning Profile 的概念。如果你熟悉簽名、證書的概念,那么其實(shí)理解這一套驗(yàn)證機(jī)制也就并不困難了。