作者:crazyball

一. 前语

对于 iOS 开发者来说,重签名技术应该说是比较熟悉的,而且重签名的完结脚本网上已经有很多,完结逻辑上根本也差不多,其间不乏像 iOS App Signer 这样优异的重签名东西。

可是,由于不同的业务场景下,不同证书和不同包体的重签名意图都不相同,很难一个东西满意一切开发者的需求。目前团队的测验流程是对游戏包重签名后,再装置到测验设备上进行测验,在日常的重签打包工作下,发现部分游戏包在重签名后存在一些问题(装置不上,某些权限功用不能用等),而用 Xcode 进行 Archive 操作后在 Xcode Organizer 中导出的包体不会出现异常。所以选用 Xcode 的 xcodebuild 指令的 -exportArchive 指令来进行重签名,发现重签名的成功率和包体稳定性提高了很多。

二. iOS 签名机制

在了解重签名之前,咱们先来了解一下 ipa 包的签名机制

教你实现一个 iOS 重签名工具

  1. 开发者 Mac 系统中生成一对非对称加密算法的公私钥 M,将公钥和开发者信息生成 CSR 文件给到苹果服务器
  2. 苹果有自己的公私钥 K,其间公钥 K 存在每一台的 iPhone 设备上,私钥 K 则保存在苹果服务器。依据 CSR 内容运用私钥 K 进行签名并生成证书,一起也依据在开发者后台填写的信息(Bundle ID,权限等)和证书生成描绘文件(mobileprovision)
  3. 在开发者设备上打包时,会把描绘文件一并打包到 ipa 中,并运用私钥 M 对包的内容进行签名
  4. 在装置到设备上时,会进行两次验证:
    1. 运用设备上的公钥 K 校验 ipa 包内的证书文件(证书是经过苹果私钥 K 签名),校验证书是否有用
    2. 上一步证书校验经过后,会拿出证书内的公钥 M 来校验 ipa 包(ipa 包是经过开发者私钥 M签名),校验 ipa 包是否可装置

苹果经过以上的双重验证机制,来确保在开发阶段 App 的装置行为的合法性。当将 App 提交到 App Store 后,苹果会对 App 从头加密签名,装置时就只需验证苹果的签名。

三. 重签名脚本

重签名的流程大致能够分红以下 5 个过程,下面列出其间的要害指令:

#!/bin/sh
set -e

# 这儿只列出重签名脚本的大致流程
# 根本能够分为以下 5 个过程

# 1. 解压游戏包,删去包内无用内容(.DS_Store,__MACOSX等),如需求,修正Info.plist参数和图标等资源
unzip "ipa途径" -d "方针途径"
find -d "解压后的途径" -name .DS_Store -o -name __MACOSX | xargs rm -rf

# 2. 对需求重签的内容并重签名
find -d "包体途径" \
-name "*.app" -o \
-name "*.appex" -o \
-name "*.framework" \
-o -name "*.dylib" \
| xargs -I {} /usr/bin/codesign --continue -f -s "证书称号" {}

# 3. 找出 appex 里边的 bundle id
find -d "包体途径" -name "*.appex" \
| xargs -I {} /usr/libexec/PlistBuddy -c "Print :'CFBundleIdentifier'" {}/Info.plist

# 4. 修正 xcarchive 模板信息
#    仿制 .app 文件到 xcarchive 的 Products/Applications 目录下
#    修正 xcarchive 内的 Info.plist 和 ExportOptions.plist 包名,证书称号,描绘文件称号等信息

# 5. 导出ipa包
xcodebuild -exportArchive \
-archivePath "xcarchive途径" \
-exportOptionsPlist "ExportOptions.plist途径" \
-exportPath "导出途径"

1. 解压 ipa 并修正包内容

  • 删去包体内无用文件(.DS_Store,__MACOSX 等系统文件)

  • 读取并修正 Info.plist 参数(Bundle ID,版别号,运用称号等信息)

  • 如需求,可修正包内 icon 等资源文件

2. codesign 指令重签名

这一步与其他的重签脚本有点不相同,以 iOS App Signer 的逻辑为例,需求先将 mobileprovision 仿制到包内改名为 embedded.mobileprovision,并从中提取 Entitlements 相关参数作为 codesign 的参数来重签的。

现在的流程是:不需求手动去替换包内的 embedded.mobileprovision 文件,由于后续的 xcodebuild -exportArchive 指令履行时会主动完结替换,所以 codesign 指令也是不需求 --entitlements 参数的。

3. 读取 appex 的 Bundle ID

appex 是什么?appex 其实便是 Plugins 目录下的内容,是 App 的插件(Extension),像 VPN、告诉等功用的包就需求插件来完结。一个 appex 其实能够理解为一个小型 App(仅仅需求依赖 App 才干运行),所以假如有开发过 Extension 功用的同学就会知道,Appex 也是会有独立的证书、描绘文件和 Info.plist。所以这一步需求读取一切 Appex 的 Bundle ID,由于后续的签名需求用到。

4. 修正 xcarchive 内容

依据最终一步的 xcodebuild -exportArchive 指令,咱们需求传一个 xcarchive 途径和 ExportOptions.plist 途径。( xcarchive 便是咱们在 Xcode -> Product -> Archive 的产品。)

xcarchive 途径下的内容:

教你实现一个 iOS 重签名工具

  • BCSymbolMaps:符号文件 ,Xcode 对 BitCode 符号表进行混淆(Symbol Hiding)后生成的对照表,和 dSYM 文件会一一对应。
  • dSYMs:存储此次编译的符号表(debug symbols),用来符号化解析崩溃库房。
  • Info.plist:xcarchive 的信息
  • Products:存储此次编译生成的的 App 包(.app)。
  • SCMBlueprint:假如 Xcode 打开了版别管理(Preferences -> Source Control -> Enable Source Control),SCMBlueprint 文件夹会存储此次编译的版别操控信息,包含运用的 git 版别、库房、分支等。
  • SwiftSupport:假如你在 Target 的 Build Settings 中打开了 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES,此次编译运用的 Swift 版别对应的规范库文件(.dylib)会被放到这个文件夹中。

首要,咱们需求替修正目录下 Info.plist 的参数,并且把 Products/Applications 下的 app 文件替换为需求重签名的 App。

教你实现一个 iOS 重签名工具

另一个 ExportOptions.plist 文件是咱们导出 ipa 包的所需求参数,也是运用 Xcode 导出 ipa 包时的产品之一。

教你实现一个 iOS 重签名工具

ExportOptions.plist 文件内容需求修正以下字段:

教你实现一个 iOS 重签名工具

5. 重签名并导出 ipa

最终,只需求把 xcarchive 目录和 ExportOptions.plis 的内容修正成需求重签名包的内容,就能够运用 xcodebuild -exportArchive 指令来重签名和导出包体。

四、总结

其完结在网上已经有非常多优异 iOS 重签名脚本,根本能满意大多数开发者运用。可是假如期望确保重试的成功率,与 Xcode 打包相同精确的话,运用 xcodebuild -exportArchive 构建 ipa 包显然是目前最优的解决方案。

以上便是咱们内部现在运用的重签脚本的完结思路,为了方便大家了解具体的完结思路,小编也依据这个逻辑写了一个 Mac 版的重签东西,方便学习一起也能直接运用。最终,欢迎大家来运用和提出主张~~

  • 37iOS/Easy-Signer: iOS App 的 Mac 重签名东西

五、参考

  • DanTheMan827/ios-app-signer
  • iOS运用安全3 — APP重签名 –
  • iOS主动化打包之重签名导出不同证书ipa探究 – 简书