相比于Android系统,iOS对下载到设备中的软件有比较严格的限制;绝大多数人,只会从AppStore下载App,这也杜绝了很多安全隐患;但是对于iOS开发者来说,需要搞明白很多事情(如:iOS App的签名原理),甚至需要做一些小动作(如重签名)来达到自己(友好的)目的。
摘要算法:把一个任意长度的字节串映射 为一定长度的十六进制的数字串;这个数字串称为哈希值。常见有:MD5、SHA1、SHA256、SHA512等
对称加密:加密和解密使用相同密钥,常见有:DES算法、3DES算法和AES算法等;
非对称加密:加密和解密使用不同密钥的加密算法,用公钥加密的数据,要用私钥才能解密,用私钥加密的数据,要用公钥才能解密;常用加密算法有:RSA、Elgamal、背包算法等;
数字签名(digital signature):
数字证书(digital certificate):
名称 | 作用 |
---|---|
证书(cer) | 内容是公钥或私钥,由其他机构对其签名组成的数据包。 |
Entitlements | 包含了 App 权限开关列表 |
CertificateSigningRequest | 本地公钥 |
p12 | 本地私钥,可以导入到其他电脑。 |
Provisioning Profile | 包含了 证书 / Entitlements 等数据,并由苹果后台私钥签名的数据包。 |
iOS设备上App的渠道粗分有AppStore渠道和非AppStore渠道,非AppStore包有:Testflight内测包、In-House 企业内部分发包、Ad-Hoc(相当于企业分发的限制版,限制安装设备梳理)和Xcode调试安装;(越狱包不在此范围)。
AppleStore中渠道包签名验证
非AppleStore渠道包的签名验证需要使用双重签名机制,保证不被滥用。
Mac 上执行钥匙串访问 -> 证书助理 -> 从证书颁发机构请求证书...,就会在Mac本地生成了一对公私钥,导出的 CSR 文件(CertificateSigningRequest.certSigningRequest
)就是 Mac 公;
将CSR 文件上传到苹果后台,苹果用Apple私钥对其签名,并生成一份包含Mac公钥信息 和 苹果签名信息的开发/发布证书cer;
当我们将cer下载并安装到Mac后,keychain会把CertificateSigningRequest和cer证书关联起来。在钥匙串中找到该证书,可以导出Mac私钥(.p12
文件)
在苹果后台需要配置AppID、可用设备IDs(企业证书不需要) 和 Entitlements(App 权限开关列表),对这些额外信息 和 cer证书使用Apple私钥签名,最后苹果将证书 + 额外信息 + 签名组成一个Provisioning Profile文件(后缀mobileprovision),可下载到Mac上。
Provisioning Profile文件又被成为描述文件,安装好后,存放在~/Library/MobileDevice/Provisioning Profiles路径下 复制代码
在Mac上编译完一个App后,Mac先用Mac私钥对App签名,并将Provisioning Profile文件也打包到App中,文件名为embedded.mobileprovision。
iOS系统安装App时,苹果通过内置在手机中的Apple公钥验证embedded.mobileprovision中的签名是否正确,接着验证证书中的签名是否正确。
在确保embedded.mobileprovision里的数据都是苹果授权以后,就从里面取出数据,做后续各种验证,包括
如果别的 Mac 也要编译后签名这个 App,就必须要获取申请生成cer证书那个Mac机器上的私钥;这个比较简单,只需要在那台机器的钥匙串中找到cer证书,然后右键导出Mac私钥(.p12
文件);
简单来说,要在别人设备上成功编译成功并将App安装到设备中,需要cer证书导出的**.p12文件和Provisioning Profile文件**(描述文件)
ProvisionsAllDevices
记录。ipa
内的证书和描述文件;查看ipa包是否加壳,只有未加壳的包才可以重签名。
otool -l app_name.app/app_name | grep crypt # 输出cryptid为0代表已经砸壳,即解密,为1或者2表示以第1类或者第2类加密方案加密。 复制代码
查看本地证书列表并记录下要用来签名的证书名,例如”iPhone Distribution: XXXXX (XXX)”
security find-identity -v -p codesigning # 输出有效的证书列表 复制代码
创建一个和App同名的工程,从上步得到有效证书列表中,选择一个,编译后生成新App;将这个新App里embedded.mobileprovision
文件取出替换iap包中的文件。
删除ipa包内部不能被重签名的插件(PlugIns文件夹 和 Watch文件夹)
将ipa包内的所有Framework中Mach-O文件重签名(Frameworks目录下有Framework)
# 命令参考 codesign -fs [证书名称] [要签名的文件] #如果没有权限,执行chmod +x app_name.app/app_name 给Mach-O文件添加可执行权限 #Frameworks文件夹里面的.framework本质还是文件夹,真正要重签的是.framework里面的MachO可执行文件 复制代码
将ipa包内info.plist的BundleId
修修改为新App对应的的BundleId
。
用命令查看embedded.mobileprovision
文件,找到其中的entitlements字段,并且复制entitlements字段和其中的内容。
security cms -D -i 「embedded文件路径」 复制代码
新建entitlements.plist文件,将复制内容拷贝到文件中,然后将entitlements.plist复制到ipa的同级目录下。
对App进行重签名,并压缩成新的ipa包
# 重签名 $ codesign -fs "iPhone Distribution: XXXXX (XXX)" --no-strict --entitlements=entitlements.plist // --no-strict 不严谨的 // --entitlements=entitlements.plist权限所在文件是entitlements.plist codesign -fs 签名证书 --no-strict --entitlements=entitlements.plist app_name.app # 压缩ipa包 $ zip -r 「输出的文件名(.ipa)」 Payload/ 复制代码
将ipa包安装到手机,若能同时存在两个应用且能正常运行则表示重签名成功。