私自安裝的程序為何不能運行?XX 助手下載的應(yīng)用為何頻頻閃退栓辜?codesign failed 究竟是何人所為?missing private key 又是怎么回事?流氓公司集體從良的背后又隱藏著什么嚣镜?這一切的背后,是 XX 還是 XXX 橘蜜。菊匿。。计福〉Γ咳咳,編不下去了(??????)??象颖,反正只要明白本文是講 iOS 的簽名機制就對了佩厚。
但是在講解簽名機制之前,我們需要搞清楚它為什么會存在说订?蘋果為什么要花費這么大的精力來建立簽名機制可款?這需要我們從蘋果公司的角度來思考下面的問題:
用戶下載應(yīng)用的過程中被黑客攻擊了,程序遭到了篡改克蚂,用戶的個人隱私遭到泄漏闺鲸,財產(chǎn)也遭受損失,怎么辦埃叭?
開發(fā)者嘔心瀝血開發(fā)出了一款應(yīng)用摸恍,結(jié)果發(fā)布之后盜版橫行,盜版商發(fā)了一筆大財赤屋,開發(fā)者卻餓死家中立镶,怎么辦?
流氓應(yīng)用遍地跑类早,互相喚醒媚媒,全家桶安裝,無底限收集用戶隱私涩僻,卸都卸不掉缭召,用戶苦不堪言,怎么辦逆日??
......
以上都是很現(xiàn)實的問題嵌巷,所以蘋果公司為了避免發(fā)生這些情況,就必須做到對 app 的安裝具有絕對的控制權(quán)室抽,也就是只有被蘋果認可的應(yīng)用才可以安裝到用戶的手機上搪哪,而 iOS 的簽名機制就是為了這一目的建立的(同時還有 App Store 以及應(yīng)用審核機制)。這些機制帶來了非常多的好處坪圾,包括確保應(yīng)用不被篡改晓折、盜版應(yīng)用無法運行惑朦、流氓廠商面臨要么下架要么從良的選擇等等,這不僅使蘋果的應(yīng)用生態(tài)能夠健康可持續(xù)的發(fā)展漓概,也保證了用戶以及開發(fā)者的利益行嗤。
非對稱加密算法
非對稱加密算法是 iOS 簽名機制的基礎(chǔ),它使用兩份密鑰(公鑰垛耳、私鑰)來對信息進行加密以及解密:對外公開的密鑰為公鑰栅屏,簽名方自己持有的密鑰為私鑰,通過私鑰加密的內(nèi)容只能用公鑰解密堂鲜,而通過公鑰加密的內(nèi)容也只有私鑰能夠解密栈雳。由于通過公鑰反推私鑰的難度非常大,理論上只要密鑰的位數(shù)足夠長缔莲,反推基本是不可能的哥纫,所以非對稱加密算法是被廣泛使用的安全性非常高的加密算法。
常用的非對稱加密算法有 RSA痴奏、ECC蛀骇、Diffie-Hellman 等,以下幾篇文章是介紹 RSA 算法的读拆,感興趣的同學可以了解下:RSA原理與實例擅憔、RSA算法原理(一)、RSA算法原理(二)檐晕。
Hash 算法
由于非對稱加密算法對明文的長度有要求暑诸,即不能超過密鑰的長度,所以在使用非對稱加密算法之前辟灰,會使用 Hash 算法對明文進行處理个榕。
任意長度的明文在經(jīng)過 Hash 算法處理后,都會得到一串長度固定的 Hash 值芥喇,并且整個過程是不可逆的西采,因此 Hash 算法常被用來處理關(guān)鍵數(shù)據(jù)。常見的 Hash 算法有:MD5继控、SHA-1械馆、SHA-2 等。
App Store
那么簽名機制是如何保證用戶下載的應(yīng)用是被蘋果認證的呢湿诊?在 iOS 設(shè)備上狱杰,App Store 是用戶下載應(yīng)用的唯一渠道,蘋果公司建立這一渠道的目的就是為了獲得應(yīng)用生態(tài)的控制權(quán)厅须。開發(fā)者在上傳應(yīng)用后,蘋果公司會對應(yīng)用進行非常嚴格的審核食棕,只有通過審核才可以進入 App Store 展示給用戶朗和。審核通過后错沽,蘋果公司會按照下圖所示的步驟生成應(yīng)用的簽名:
首先使用 Hash 算法對 App 數(shù)據(jù)進行處理,得到摘要
接下來會使用 Apple 私鑰對摘要進行加密眶拉,得到簽名
用戶在 App Store 上購買應(yīng)用后千埃,簽名會和 App 一起下載到用戶的手機上,接下來用戶的 iOS 設(shè)備會進行如下處理:
使用相同的 Hash 算法對下載到用戶手機的 App 進行處理忆植,得到摘要1
使用 Apple 公鑰對簽名進行解密放可,得到摘要2(Apple 公鑰是事先內(nèi)置在 iOS 設(shè)備中的)
判斷摘要1和摘要2是否相等,如果相等朝刊,那么認證成功耀里,App 可以安裝,否則認證失敗拾氓,App 無法安裝
開發(fā)者視角
上述認證流程可以滿足一個普通用戶的需求冯挎,但卻無法滿足開發(fā)者。因為開發(fā)者在開發(fā)應(yīng)用的過程中會無數(shù)次的在手機上調(diào)試 app咙鞍,如果每次安裝應(yīng)用時都要上傳到蘋果那邊簽名房官,然后再下載,這是無法接受的续滋,所以蘋果又為開發(fā)者建立了獨特的本地簽名的流程翰守。
開發(fā)者會在自己的電腦上生成用于簽名認證的公鑰和私鑰,以后安裝 app 到手機上時會在本地進行認證疲酌,而無需將 app 上傳到蘋果的服務(wù)器上簽名潦俺。但是蘋果也必須要維護自己控制 app 安裝的權(quán)利,那么蘋果會怎么做呢徐勃?答案就是使用數(shù)字證書事示。
數(shù)字證書
開發(fā)者通過 鑰匙串訪問->證書助理->從證書頒發(fā)機構(gòu)請求證書
生成 Certificate Signing Request 文件(CSR 文件),同時也在本地自動生成了相應(yīng)的公鑰和私鑰僻肖,在填好必要的信息后肖爵,開發(fā)者將 CSR 文件上傳給蘋果用于生成數(shù)字證書。
CSR 文件記錄了開發(fā)者的個人信息臀脏、公鑰劝堪、加密算法以及 Hash 算法等內(nèi)容,可以使用以下命令來查看文件內(nèi)容:
openssl asn1parse -i -in CertificateSigningRequest.certSigningRequest
蘋果收到 CSR 文件后揉稚,會使用自己的私鑰對開發(fā)者的公鑰進行簽名秒啦,最終生成一個數(shù)字證書(包含開發(fā)者賬號信息、公鑰以及相應(yīng)的簽名)返回給開發(fā)者搀玖,查看證書信息的命令如下:
openssl x509 -inform der -in ios_development.cer -noout -text
點擊安裝證書后余境,鑰匙串會自動將證書和相應(yīng)的私鑰對應(yīng)起來,同時你還需要在 Xcode 中將簽名證書設(shè)置為你剛剛安裝的證書。此后在編譯完 app 時芳来,系統(tǒng)會使用數(shù)字證書對應(yīng)的本地私鑰對 app 進行簽名含末,然后同數(shù)字證書一起安裝到手機上,接下來 iOS 設(shè)備會通過 Apple 公鑰來驗證數(shù)字證書是否有效即舌,驗證通過后會使用數(shù)字證書中的公鑰來驗證 app 是否有效佣盒,最終判斷 app 是否可以被安裝。
Provisioning Profile
僅有數(shù)字證書是不夠的顽聂,為了防止權(quán)限被濫用肥惭,開發(fā)者還需要在蘋果官網(wǎng)上注冊用于開發(fā)的設(shè)備,僅有注冊后的設(shè)備才被允許按照以上流程安裝 app紊搪。
個人開發(fā)者賬號可以注冊的設(shè)備是100臺蜜葱,Enterprise 賬號不限制數(shù)量,但是不能將應(yīng)用發(fā)布到 App Store 上嗦明,關(guān)于開發(fā)者賬號的種類以及區(qū)別可以參考 Choosing a Membership笼沥。
除此之外,蘋果還需要對 app 的權(quán)限進行控制娶牌,例如是否能夠使用 iCloud奔浅、Wallet、Maps 等诗良,蘋果將這些功能授權(quán)統(tǒng)稱為 Entitlements汹桦。開發(fā)者將上述權(quán)限配置完成后,需要從蘋果后臺下載并安裝相應(yīng)的 mobileprovision 文件鉴裹,該文件包含:
AppId舞骆,每個 app 都會有對應(yīng)的 mobileprovision 文件
功能授權(quán)列表
已注冊的設(shè)備列表
數(shù)字證書
蘋果簽名
沒錯,你沒看錯径荔,蘋果對你下載的 mobileprovision 文件也會簽名督禽,所以你是無法更改文件內(nèi)容的。因此你需要注意的是总处,如果你在 Xcode 中的 Capabilities 開啟了 app 的某項功能狈惫,那么你一定要去蘋果后臺更新 app 的權(quán)限,然后下載最新的 mobileprovision 安裝鹦马,否則會有詭異的事情發(fā)生胧谈。
當然,如果有需要的話荸频,你可以使用以下命令來查看 mobileprovision 文件內(nèi)容:
security cms -D -i embedded.mobileprovision
app 編譯完成之后菱肖,也會將 mobileprovision 文件打包到 app 中。
綜合上述信息旭从,最終流程是這樣的:
開發(fā)者在本地生成私鑰和公鑰稳强,然后將公鑰上傳給蘋果并獲取蘋果簽名的數(shù)字證書
開發(fā)者在蘋果后臺配置 AppId场仲,注冊開發(fā)設(shè)備,配置功能權(quán)限键袱,最后下載并安裝 mobileprovision 文件
開發(fā)者用本地私鑰簽名 app燎窘,并將 mobileprovision 文件隨 app 安裝進 iOS 設(shè)備
iOS 設(shè)備使用 Apple 公鑰驗證 mobileprovision 文件的簽名以及數(shù)字證書的簽名
使用數(shù)字證書包含的公鑰來驗證 app 的簽名
驗證安裝 app 的設(shè)備是否在設(shè)備列表中摹闽,AppId 是否一致蹄咖,Entitlements 和 app 中的權(quán)限是否對的上等等
其他發(fā)布流程
除了 App Store 以及開發(fā)者真機調(diào)試外,蘋果還設(shè)置了其他流程來發(fā)布應(yīng)用付鹿,包括 In-House 以及 Ad-Hoc澜汤。只有 Enterprise 賬號才可以進行 In-House 發(fā)布,其目的是為了在企業(yè)內(nèi)部使用 app舵匾,現(xiàn)在常見的 XX 助手就是使用 Enterprise 賬號來發(fā)布盜版應(yīng)用俊抵,對于這種濫用行為,蘋果只能一個個吊銷賬號坐梯,并沒有太好的辦法徽诲。而 Ad-Hoc 則是用于小范圍發(fā)布給用戶進行測試,限制的數(shù)量是100臺吵血,參與 Ad-Hoc 的設(shè)備必須要事先注冊谎替。關(guān)于發(fā)布流程可以參考這篇文章。
補充
你可能聽人說過 p12 文件蹋辅,那么這個是什么呢钱贯?p12 文件常用于 iOS 證書共享,你可以在鑰匙串中以 p12 格式導出你的本地私鑰侦另,配合數(shù)字證書秩命、 mobileprovision 文件共享給團隊中的其他成員,這樣其他人也可以用你的證書開發(fā)程序了褒傅。
這里再額外提一下弃锐,我們最終生成的 app 都是 ipa 格式,里面包含可執(zhí)行文件殿托、資源文件霹菊、第三方 Framework 等,可執(zhí)行文件的簽名會直接保存在可執(zhí)行文件里碌尔,其他文件的簽名會放在 _CodeSignature/CodeResources 中浇辜,而 Frameworks 內(nèi)部會包含自身的簽名信息。你還可以在 ipa 中找到 embedded.mobileprovision 文件唾戚,然而如果你是從 App Store 上下載的 app柳洋,那么是沒有 mobileprovision 文件的。
如果你想進一步了解蘋果簽名叹坦,你可以參考以下文檔:Code Signing Guide熊镣、App Distribution Guide、代碼簽名探析。