最近被公司的構(gòu)建系統(tǒng)折騰得比較鬧心,于是研究了一下 ipa 打包和簽名的過程,以方便日后跟他們撕逼。
首先說說什么是 ipa 包。ipa 包其實(shí)就是一個 zip 包。拿簡書為例,先用 iTune 去 app store 下載一個簡書,然后在我的應(yīng)用->show in finder 里面找出來,copy 出來慢慢玩。
解壓之后,如圖所示

iTunes 開頭的兩個文件記錄了購買者信息之類的東西,META-INF 里面是一些解壓信息,Payload 里面則是一個.app 文件。Mac OSX 里面的 app 就是以.app的形式存在的。codesign 簽名的對象就是這個 app 文件。那么我們用命令查看一下這個 app 的簽名吧:
codesign -vv -d Payload/Hugo.app
結(jié)果如下:
Identifier=com.jianshu.Hugo
Format=app bundle with Mach-O universal (armv7 arm64)
CodeDirectory v=20200 size=46700 flags=0x0(none) hashes=2326+5 location=embedded
Signature size=3487
Authority=Apple iPhone OS Application Signing
Authority=Apple iPhone Certification Authority
Authority=Apple Root CA
Info.plist entries=41
TeamIdentifier=KS7QAPBMXA
Sealed Resources version=2 rules=14 files=1161
Internal requirements count=1 size=96
我發(fā)現(xiàn)這里的 Authority全是蘋果,沒有一個是與開發(fā)者相關(guān)的。這里可以留意一下,對比一下用開發(fā)證書簽名后的結(jié)果。
上面的 iTunes 信息有什么用呢?于是做了個實(shí)驗(yàn):
重新打包一個 ipa,只打包 Payload,不打包 iTunes 信息。
zip -r juanshuIpaWithoutItunesInfo.ipa Payload
然后用重新打包的 ipa 進(jìn)行安裝,安裝成功。說明上面的 iTunes信息并不影響安裝。
把這個 ipa 發(fā)給另一個用戶,然后用 itunes 打開安裝,成功。也就是說,iOS 安裝ipa 并不校驗(yàn)購買者信息,只要app 簽名完整就可以了。
那么是否意味著我購買的 ipa 可以發(fā)給好友安裝呢?其實(shí)不然。對于非越獄的手機(jī),只能通過 iTunes 進(jìn)行安裝。對于免費(fèi)的 app, iTunes 會直接安裝,但對于收費(fèi)的 app,會多一步授權(quán)驗(yàn)證,別人發(fā)給你的 ipa 包是無能通過這個授權(quán)的。我猜這個授權(quán)驗(yàn)證應(yīng)該是通過查詢你的帳號的購買記錄,然后和 app 的 bundle id 進(jìn)行比對,來判斷你是否擁有這個 app.

也就是說,蘋果是通過 iTunes 來防止收費(fèi) app 的分發(fā),對于 iOS 系統(tǒng)本身來說,只要你的簽名過關(guān),就能安裝成功。
iOS 的簽名校驗(yàn)有幾種情況:
1、從 app store 下載的ipa 包,比如上面的簡書 app.簽名方是 Apple iPhone OS Application Signing,只要是這個簽名,就能安裝。
2、用企業(yè)證書簽名的內(nèi)測 ipa。簽名方是企業(yè)帳號(199美那種),需要把一個 embedded.mobileprovision文件打進(jìn) app 里面,該文件記錄著發(fā)布者的信息。不限設(shè)備數(shù)量安裝,但是打開 app 之前會詢問用戶是否信任該帳號。
3、用個人開發(fā)者證書簽名的開發(fā)版 ipa。簽名方是開發(fā)者帳號(99刀那種)。app 安裝的時(shí)候會判斷該設(shè)備是否在開發(fā)者的設(shè)備列表,如果在而且簽名完整,則成功安裝。
我是第三種。先從越獄市場上下載一個 ipa 下來看看,用 codesign --verify 查看一下簽名信息:
invalid signature (code or signature have been modified)
簽名無效,說明包被修改過。既然這樣,我也來改了。首先去 member center 創(chuàng)建一個新的 appId,然后修改 app 包里面的 Info.plist,把 bundle identifier改成我自己創(chuàng)建那一個,然后
codesign -f -s "xxx" Payload/Oceanhorn.app
xxx 就是我的開發(fā)者帳號名稱,在 keychain 里面可以看到。
如果app 需要一些授權(quán)的,比方說 universal link 之類,會創(chuàng)建一個 entitlement 文件,那么也需要簽名。
比如 codesign -f -s $certifierName? --entitlements entitlements.plist Payload/Oceanhorn.app
簽名完,重新打包?
zip -r newIpa.ipa Payload
然后查看一下簽名信息:

這些的 Authority 變成我自己了。證書頒發(fā)機(jī)構(gòu)也變成了開發(fā)者證書中心。
然后用 iTunes 打開,安裝,成功。
有一些應(yīng)用由于觸犯天條,是不可以在 app store 上架的,比方說著名的 PSP 模擬器 PPSSPP,它們一般會在越獄市場上上架,不過是以一個 deb 包的形式。那這種又怎么安裝到我們非越獄的手機(jī)上呢?
我們嘗試解壓一下 deb 包,發(fā)現(xiàn)有兩個 gz 包,一個 binary 文件。把其中一個 data 的 gz 包再解壓,有兩個文件夾,其中一個 Application 文件夾有一個 app文件,沒有簽名。如法炮制,用自己的帳號幫它簽上名,然后創(chuàng)建一個 Payload文件夾,放進(jìn)去,zip 打個包,安裝,成功。

對開發(fā)者而言,用自己的帳號重簽名可以隨便安裝任何 ipa,那對于普通用戶而言,簽名意味著什么呢?
1、非越獄手機(jī)用戶,如果有惡意開發(fā)者修改了微信,比如利用動態(tài)庫依賴加了些后門,然后重簽一次名,幫你裝到手機(jī)上,那么。。。。呵呵。要防止也很簡單,請確保每一個 APP 都是從 APP STORE 上下載的。
2、對于越獄手機(jī)用戶,越獄的過程其實(shí)就是關(guān)閉簽名校驗(yàn)的過程,所以什么李鬼都能混進(jìn)來,自求多福吧。
最后,請珍惜那些愿意花錢買 app 的開發(fā)者,因?yàn)樗麄兌际求w面的人。