最近被公司的构建系统折腾得比较闹心,于是研究了一下 ipa 打包和签名的过程,以方便日后跟他们撕逼。
首先说说什么是 ipa 包。ipa 包其实就是一个 zip 包。拿为例,先用 iTune 去 app store 下载一个,然后在我的应用->show in finder 里面找出来,copy 出来慢慢玩。
解压之后,如图所示
iTunes 开头的两个文件记录了购买者信息之类的东西,META-INF 里面是一些解压信息,Payload 里面则是一个.app 文件。Mac OSX 里面的 app 就是以.app的形式存在的。codesign 签名的对象就是这个 app 文件。那么我们用命令查看一下这个 app 的签名吧:
codesign -vv -d Payload/Hugo.app
结果如下:
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
我发现这里的 Authority全是苹果,没有一个是与开发者相关的。这里可以留意一下,对比一下用开发证书签名后的结果。
上面的 iTunes 信息有什么用呢?于是做了个实验:
重新打包一个 ipa,只打包 Payload,不打包 iTunes 信息。
zip -r juanshuIpaWithoutItunesInfo.ipa Payload
然后用重新打包的 ipa 进行安装,安装成功。说明上面的 iTunes信息并不影响安装。
把这个 ipa 发给另一个用户,然后用 itunes 打开安装,成功。也就是说,iOS 安装ipa 并不校验购买者信息,只要app 签名完整就可以了。
那么是否意味着我购买的 ipa 可以发给好友安装呢?其实不然。对于非越狱的手机,只能通过 iTunes 进行安装。对于免费的 app, iTunes 会直接安装,但对于收费的 app,会多一步授权验证,别人发给你的 ipa 包是无能通过这个授权的。我猜这个授权验证应该是通过查询你的帐号的购买记录,然后和 app 的 bundle id 进行比对,来判断你是否拥有这个 app.
也就是说,苹果是通过 iTunes 来防止收费 app 的分发,对于 iOS 系统本身来说,只要你的签名过关,就能安装成功。
iOS 的签名校验有几种情况:
1、从 app store 下载的ipa 包,比如上面的 app.签名方是 Apple iPhone OS Application Signing,只要是这个签名,就能安装。
2、用企业证书签名的内测 ipa。签名方是企业帐号(199美那种),需要把一个 embedded.mobileprovision文件打进 app 里面,该文件记录着发布者的信息。不限设备数量安装,但是打开 app 之前会询问用户是否信任该帐号。
3、用个人开发者证书签名的开发版 ipa。签名方是开发者帐号(99刀那种)。app 安装的时候会判断该设备是否在开发者的设备列表,如果在而且签名完整,则成功安装。
我是第三种。先从越狱市场上下载一个 ipa 下来看看,用 codesign --verify 查看一下签名信息:
invalid signature (code or signature have been modified)
签名无效,说明包被修改过。既然这样,我也来改了。首先去 member center 创建一个新的 appId,然后修改 app 包里面的 Info.plist,把 bundle identifier改成我自己创建那一个,然后
codesign -f -s "xxx" Payload/Oceanhorn.app
xxx 就是我的开发者帐号名称,在 keychain 里面可以看到。
如果app 需要一些授权的,比方说 universal link 之类,会创建一个 entitlement 文件,那么也需要签名。
比如 codesign -f -s $certifierName --entitlements entitlements.plist Payload/Oceanhorn.app
签名完,重新打包
zip -r newIpa.ipa Payload
然后查看一下签名信息:
这些的 Authority 变成我自己了。证书颁发机构也变成了开发者证书中心。
然后用 iTunes 打开,安装,成功。
有一些应用由于触犯天条,是不可以在 app store 上架的,比方说著名的 PSP 模拟器 PPSSPP,它们一般会在越狱市场上上架,不过是以一个 deb 包的形式。那这种又怎么安装到我们非越狱的手机上呢?
我们尝试解压一下 deb 包,发现有两个 gz 包,一个 binary 文件。把其中一个 data 的 gz 包再解压,有两个文件夹,其中一个 Application 文件夹有一个 app文件,没有签名。如法炮制,用自己的帐号帮它签上名,然后创建一个 Payload文件夹,放进去,zip 打个包,安装,成功。
对开发者而言,用自己的帐号重签名可以随便安装任何 ipa,那对于普通用户而言,签名意味着什么呢?
1、非越狱手机用户,如果有恶意开发者修改了微信,比如利用动态库依赖加了些后门,然后重签一次名,帮你装到手机上,那么。。。。呵呵。要防止也很简单,请确保每一个 APP 都是从 APP STORE 上下载的。
2、对于越狱手机用户,越狱的过程其实就是关闭签名校验的过程,所以什么李鬼都能混进来,自求多福吧。
最后,请珍惜那些愿意花钱买 app 的开发者,因为他们都是体面的人。