最近遇到一個簽名的問題,藉機把iOS簽名相關知識點研究了一下。現總結以下:(研究過程當中參考了這位仁兄的博客。很全面,本文也有部分借鑑)html
非對稱加密ios
這個是簽名機制的算法基礎。所謂非對稱加密的是相對於對稱加密來講的。對稱加密是加密方和解密方約定一個相同的密鑰和加解密算法。只要獲取了這個密鑰,則能夠破譯加密內容。這種加密方法下,假如我要和3我的通訊,就須要和三我的分別約定好3個不一樣的密鑰,否則這三我的就沒辦法鑑別消息是由我本人加密的。git
而非對稱加密則是採用了一對密鑰(私鑰和公鑰)。經過公鑰加密的內容只能經過私鑰解密,而經過私鑰加密的內容也只能經過公鑰解密。通常公鑰是公開的,私鑰本身保存。經過這種加密方式,能夠鑑別加密內容是否由私鑰持有者進行加密,從而驗證對方身份。這種加密方法下:假如我要和3我的通訊,只須要這三我的知道個人公鑰便可。只要能經過個人公鑰解密便可認爲消息是由我進行加密。而3我的中任何一我的加密的內容,只能由我來解密。固然這種狀況下,我就沒辦法鑑定這三我的的真實身份了。github
摘要(Hash)算法
摘要技術也稱爲哈希技術,是將任意長度的數據一一映射到一個固定長度數據的技術,而且獲得的摘要數據是不可逆的。只要原始數據不同,則獲得的摘要也會不同;原始數據同樣,摘要當然也同樣。所以摘要技術能夠用來驗證數據是否被篡改。xcode
常見的摘要算法有SHA1(160bit),SHA256(256bit),SHA512(512bit)等等app
數字簽名工具
數字簽名其實就是摘要技術和非對稱加密的應用。當發送方要發送一段數據給別人時,爲了讓接受者能對接受到的數據進行驗證,確保數據沒有被篡改過。ui
1. 發送方會同時爲數據生成摘要,並用私鑰進行加密。加密
2. 接收方會同時受到數據和加過密的摘要,經過將加密摘要用公鑰進行解密
3. 接收方將數據也經過摘要算法進行摘要,和第2步中獲得的摘要進行對比,若是一致,能夠證實數據沒有被篡改過。不然即數據被篡改。
下圖描述了上面的場景
數字證書
上面說過非對稱加密機制裏公鑰是公開的,數字證書就是其公開形式。私鑰持有者將其我的(或組織)信息與公鑰信息提交給證書頒發機構,證書頒發機構用本身的私鑰將所提交的信息進行數字簽名,而後生成數字證書。這個證書就是私鑰持有者在認證機構的體系下身份標示。也是獲取其公鑰的途徑。這裏其實還有點隱藏起來的知識點,證書頒發機構用他的私鑰簽名,那如何驗證這個簽名呢?只有驗證了簽名才能驗證證書的真僞啊。祕密就藏在操做系統的授信證書庫中。
1. 要驗證證書的簽名,須要證書頒發機構的公鑰
2. 證書頒發機構的公鑰通常會內置在操做系統中,或者自行導入證書頒發機構證書(包含其公鑰)。
這樣一來,這個信任鏈條就完整了。
廣泛使用的數字證書格式是X.509格式,文件格式是.cer。還有一種包含了私鑰的證書.pfx(或.p12)。好比咱們在key chain中把包含私鑰的證書導出會生成.p12文件,就是包含私鑰的。這種通常用於本身將證書和私鑰移植到別的機器。
好,上面已經把iOS簽名機制的基礎知識進行鋪墊了。接下來看看iOS開發過程當中的簽名究竟是怎麼回事。
蘋果開發者數字證書
要簽名,必需要有私鑰,公鑰對。所以作iOS開發首先要去蘋果開發者中心去申請我的證書。申請方式是:
1. 經過Key Chain的Certificate Assistant產生一個CSR(Certificate Signing Request)文件。在生成CSR的時候須要填寫郵箱和Common Name.這就是你的我的信息。
2. 而後系統會產生一對密鑰對,私鑰保存在key chain中,公鑰寫入CSR文件。
3. 在蘋果開發者中心將CSR文件上傳,他會產生一個數字證書(蘋果在證書中會添加Team相關的信息)。這個證書就是你在蘋果認證體系中的我的身份了。在後續的簽名中也會用到該證書。當你下載並安裝該證書後,系統會自動將該證書的公鑰與系統中的私鑰配對。所以你再key chain中的證書列表中會看到證書關聯了一個私鑰。
證書的信息長這樣:
各類證書(App Store,Ad-Hoc,development)
Provisoning文件
有了證書後能夠用來簽名了,可是問題來了: 當咱們對app簽名的時候,總不能容許任意一個的開發者證書來簽名吧。所以蘋果的解決辦法是Provisioning文件,該文件中記錄了容許被用來簽名的證書列表。同時該文件還記錄了app的bundle id,容許運行的設備列表(ad-hoc發佈的時候有用),以及app可使用的蘋果的一些服務列表。在生成該文件時,蘋果會用本身的私鑰生成簽名。開發者須要在開發者中心生成該文件而後下載到本地。在打包app的時候該文件會一塊兒打包進ipa文件,在app運行的時候根據他對app進行合法性檢查。
XCode簽名配置
1. 在Target的配置界面General/Signing節點中,能夠選擇Automatically Manage Signing.勾選該選項後,XCode會去自動爲你產生證書,Profile文件,前提是你要在XCode中登陸你的開發者帳號(通常開發階段能夠選擇此種方式)
2. 在Signing(Debug)/Signing(Release)節點中,能夠選擇Provisioning文件,前面說過該文件裏面存儲了可用來簽名(簽名其實用的時證書中公鑰所對應的私鑰)的證書信息。所以選擇了Provisioning文件後,XCode會自動去key chain中尋找本地存在的證書和私鑰。(若是本地沒有對應的證書和私鑰,則會報錯)
若是本地有多個可用證書,可在BuildSetting配置 Tab裏面的Signing節點進行進一步選擇。
Framework簽名配置
項目中Framework Project是不須要設置簽名信息的,由於他會在引用它的主項目中進行簽名,固然也是用的主項目的簽名配置信息。
XCode簽名流程
XCode在簽名app時會:
1. 爲每一個文件生成摘要信息(這裏包括provisioning文件),而後用簽名證書對應的私鑰進行簽名
2. 將每一個文件對應的簽名信息存儲在app包的_CodeSignature\CodeResources文件內
3. 對於Framework,其本質其實也是一個包文件(和app同樣)。XCode會對他裏面的全部文件進行簽名而後簽名信息放在Framework包文件內的_CodeSignature\CodeResources文件內。
具體流程見下圖:
最後獲得的ipa文件內部是這個樣子的:
相關工具
上面XCode簽名流程中用到了兩個工具: codesign和zip
1. codesign是真正用來執行簽名工做的工具。它提供簽名,驗證簽名,顯示簽名信息等等功能。XCode在執行簽名的時候實際上是調用該工具。
2. zip是壓縮工具。用它能夠將app包文件進行壓縮。(ipa文件格式只是將壓縮文件改了個擴展名而已)
3. 同時XCode Command Line Tool中提供了一個PackageApplication的可執行程序,這個程序接收provisioning file和證書做爲參數,能夠對app進行替換provisiong file和重簽名(只對app包進行重簽名,內置的Framework不會重籤)。具體用法能夠
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/PackageApplication -man來查看。可是該工具在最新的XCode中已經被移除。推薦使用xcodebuild -exportArchive來生成ipa.
詳見https://developer.apple.com/library/content/technotes/tn2339/_index.html
蘋果設備App合法性驗證
當iOS設備安裝app時,會執行以下操做:
1. 解包ipa文件
2. 拿出provisioning file,經過內置的蘋果公鑰驗證provisioning file的合法性。(Provisioning file是被蘋果用私鑰簽過名的)
3. 根據provisioning file中的信息驗證app的合法性。確保provisoning file記錄的信息和app信息一致(好比bundle id)
4. 從provisioning file中得到簽名的證書
5. 經過蘋果公鑰(iOS系統內置)來驗證證書合法性(證書是被蘋果私鑰簽名的)
6. 經過證書中的公鑰來驗證每一個文件的摘要信息,確保每一個文件都沒有被篡改過。
重簽名工具
其實只要有了provisioning file,證書咱們能夠把一個ipa重簽名爲任何其餘名稱(provisioning file中定義)的app。只需將ipa解包,而後按照XCode的流程對app從新進行簽名便可。下面的工具便可實現。(經過這種途徑理論上能夠修改ipa的文件而後從新用新的bundle id安裝。這樣至關於hack了app。)
https://github.com/lbwxly/ios-app-signer