1、简介
利用Xcode的命令 security
和 codesign
重签ipa文件。重签名与Xcode里用build打包时进行的签名操作是一个原理,具体来说,先了解一下iOS相关的证书类型。
证书类型:
证书类型 | 使用场景 |
---|---|
开发(Development)证书和描述文件 | 用于开发测试,在Xcode中打包后,可在真机环境调试、安装 |
发布(Distribution)证书和描述文件 | 用于提交Appstore,在Xcode中打包后,可使用Xcode、Application Loader提交到Appstore审核发布 |
证书作用:
证书 | 文件后缀 | 文件类型 | 作用 |
---|---|---|---|
Provisioning Profile | .mobileprovision | 描述文件 | Provisioning Profiles文件(配置文件), 作用是绑定设备UDID,所以在申请开发描述文件之前,先添加调试的设备。双击时打开Xcode安装在电脑上的描述文件,用命令行可以查看安装的描述文件,可以过滤掉过期的描述文件。 |
Signing Certificate | .cer/.p12 | 证书文件 | 有开发和发布的证书,可以在钥匙串查看安装的可用的证书,过期时间等。p12是一个加密的文件,只要知道其密码,就可以供给所有的 Mac 设备使用,是这个应用的唯一标识证书和开发者,用于对应 bundleID 的应用开发和打包测试。 |
注:
- 描述文件保存在 macOS 路径:
~/Library/MobileDevice/Provisioning\ Profiles/
- 查看安装的证书使用命令:
security find-identity -p codesigning -v
如果是团队开发,一般会生成p12证书提供给组员使用,这样更加好管理证书。
证书名字 | 用途 |
---|---|
adhocXXX.mobileprovision | 描述文件。用于生成 adhoc 包时,描述可以安装ipa包的设备UDID和证书关系。(包含推送、apple pay等权限声明内容) |
devXXX.mobileprovision | 描述文件。用于生成 dev 包时,描述可以安装ipa包的设备UDID和证书关系。(包含推送、apple pay等权限声明内容) |
devXXXPushXXX.p12 | 推送证书。用于 dev 包推送时,认证和关联 应用bundleID 的证书关系。 |
devXXX.p12 | 开发证书。用于打包App时,生成 dev 的 ipa 包需要的开发者信息。 |
disXXX.mobileprovision | 描述文件。用于生成 dis 包时,描述应用bundleID与证书的关系。(包含推送、apple pay等权限声明内容) |
disXXXPushXXX.p12 | 推送证书。用于 dis(或adhoc) 包推送时,认证和关联 应用bundleID 的证书关系。 |
disXXX.p12 | 发布证书。用于打包App时,生成 dis (或adhoc) 的 ipa 包需要的开发者信息。 |
注:
- 如果需要添加新的设备UDID,其实只需要更新 .mobileprovision 描述文件就可以;
- 如果证书超过了有效期,.p12 和 .mobileprovision 文件需要重新生成,如果 revoke 生成新的证书,旧的证书和证书对应的ipa包不能再安装在设备上。
关于证书类型说明:
用途 | dev | adhoc | dis | 企业证书 |
---|---|---|---|---|
能否用于送审 | 不能 | 能 | 能 | 不能 |
不越狱且不添加到证书的设备能否安装 | 不能 | 不能 | 不能 | 能 |
不越狱但添加到证书的设备能否安装 | 能 | 能 | 不能 | 能 |
越狱设备能否安装 | 能 | 能 | 能 | 能 |
能否用于沙盒储值测试 | 能 | 能 | 不能 | 不能 |
越狱设备(模拟器)能否用于沙盒储值测试 | 不能 | 不能 | 不能 | 不能 |
能否用于送审 TestFlight | 不能 | 不能 | 能 | 不能 |
不越狱能否打开应用的“Documents、Library、tmp”目录 | 能 | 不能 | 不能 | 不能 |
越狱设备能否打开应用的“Documents、Library、tmp”目录 | 能 | 能 | 能 | 能 |
添加设备UDID到证书:
iPhone手机轻松获取UDID的六种方式 - 简书
2、重签名流程
1.添加p12证书
# Import items into a keychain.
$ security import inputfile [-k keychain] [-t type] [-f format] [-w] [-P passphrase] [options...]
$ security import /Users/htc/Desktop/distest.p12 -P '123456'
2.解压ipa包
$ unzip yourApp.ipa
查找 .app目录,删除系统临时文件
$ rm -rf ./Payload/yourAppName.app/.DS_Store
3.修改内容
修改Payload/yourName.app中的icon图标、Info.plist文件的信息等,如有需要也可以更改比如版本号,应用名称等。
4.删除之前的签名 _CodeSignature
$ rm -rf ./Payload/yourAppName.app/_CodeSignature
5.用包里的描述文件生成entitlements.plist
文件
查看描述文件内容的命令:
$ security cms -D -i "xxx.mobileprovision"
上面命令会输出内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppIDName</key>
<string>iLeetCode</string>
<key>ApplicationIdentifierPrefix</key>
<array>
<string>28PV6G96R7</string>
</array>
<key>CreationDate</key>
<date>2019-10-01T12:57:15Z</date>
<key>Platform</key>
<array>
<string>iOS</string>
</array>
<key>IsXcodeManaged</key>
<true/>
<key>DeveloperCertificates</key>
<array>
<data></data>
</array>
<key>Entitlements</key>
<dict>
<key>application-identifier</key>
<string>28PV6G96R7.com.iHTCboy.iLeetCoder</string>
<key>keychain-access-groups</key>
<array>
<string>28PV6G96R7.*</string>
</array>
<key>get-task-allow</key>
<true/>
<key>com.apple.developer.team-identifier</key>
<string>28PV6G96R7</string>
<key>aps-environment</key>
<string>development</string>
</dict>
<key>ExpirationDate</key>
<date>2020-09-30T12:57:15Z</date>
<key>Name</key>
<string>iOS Team Provisioning Profile: com.iHTCboy.iLeetCoder</string>
<key>ProvisionedDevices</key>
<array>
<string>c286167280be0083fd23e59aaa805e1f3fbdwsd0</string>
</array>
<key>TeamIdentifier</key>
<array>
<string>28PV6G96R7</string>
</array>
<key>TeamName</key>
<string>he tiancong</string>
<key>TimeToLive</key>
<integer>365</integer>
<key>UUID</key>
<string>9f1fb7b7-2549-4fc6-8893-344f4ddb3580</string>
<key>Version</key>
<integer>1</integer>
</dict>
</plist>%
可以用管道命令 >
保存成 plist 文件:
$ security cms -D -i embedded.mobileprovision > entitlement_full.plist
如果只保留 Entitlements
属性内容,则可以使用PlistBuddy
命令,我们重签只需要 Entitlements 属性:
$ /usr/libexec/PlistBuddy -x -c \'Print:Entitlements\' entitlement_full.plist > entitlement.plist
注:本步骤的 Entitlements 属性内容非常重要,不能多字段,或者字段设置true或false错误,都会导致异常情况,否则重签是有效,但导致ipa包安装失败~
6.替换描述文件
把新的描述文件复制替换到解压后的目录中,这个需要看自己需要,旧包的描述权限与新证书的权限,是需要那些,上一步骤中 Entitlements
就是在重签时还可以在指定。
$ cp ./embedded.mobileprovision ./Payload/yourAppName.app/embedded.mobileprovision
如果需要查看系统中已经保存的描述文件:~/Library/MobileDevice/Provisioning\ Profiles/
7.给 MachO 文件添加执行权限
解压ipa文件时,app里面的 MachO 文件可能没有执行权限,导致重签的包安装时提示失败。
chmod +x ./Payload/yourAppName.app/yourAppName
注,如果Python脚本有对应的库可以查看 MachO,如果是 Shell 脚本,可以利用 Info.plist 文件中已经有 MachO 对应的文件名,可以通过下面命令读取:
MachO_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
当然,一般路径下app的名字与 MachO 一样 Payload/yourAppName.app/yourAppName
。具体方式大家自行选择~
8.获取证书内容
这一步需要读取钥匙串中的开发者证书,可以用以下命令查看下有哪些证书:
$ security find-identity -p codesigning -v
上面命令输出:
1) A80A1543C48DBCB85F4F185B2D38E7A25E5A48E5 "iPhone Developer: ihtcboy@htc.com (8RRC787ZH2)"
2) D7A8D149DCCFB882BEDFA68913B50623D38C8C49 "iPhone Distribution: Guangzhou HTC Internet Technology Co.,LTD"
3) 900EC6AC6961B824BBAED3303E036A2F5421935A "iPhone Developer: iHTCboy (2HT78BY87T)"
...
...
注意,下面的重签命令,需要使用上面的 "iPhone Developer: ihtcboy@htc.com (8RRC787ZH2)" 参数
9.重新签名
先重签名framework和dylib(不重签的话,就删除无法签名的插件文件: Framework
、PlugIns
文件夹、Watch
文件夹)
# sign
codesign -s identity [-fv*] [-o flags] [-r reqs] [-i ident] path ...
# verify
codesign -v [-v*] [-R=<req string>|-R <req file path>] path|[+]pid ...
# display contents
codesign -d [options] path ...
# display hosting paths
codesign -h pid ...
$ /usr/bin/codesign --force --sign "iPhone Distribution:xxxxx" /Payload/XX.app/Frameworks/xxx.framework
再签名.app:
$ /usr/bin/codesign -f -s "iPhone Distribution:xxxxx" --entitlements entitlements.plist ./Desktop/Payload/yourAppName.app
注意:签名app需要添加参数 --entitlements entitlements.plist
重签成功后提示:
./Payload/yourAppName.app: replacing existing signature.
10.压缩Payload 生成最终 .ipa 文件
用 zip
文件压缩生成最终的重签后的ipa文件
$ zip -ry ABC.ipa Payload
11.验证签名有效性(可选)
macOS 10.11 后,codesign
命令增加了验证签名正确性,当然验证签名信息在真机上进行安装可安装就说明可以用。
验证签名正确性:
$ codesign -v Payload/XX.app
查看app的签名信息:
$ codesign -vv -d Payload/XX.app
12.删除安装的p12证书(可选)
如果是公共设备环境,可能执行删除命令,删除步骤1中导入的证书。
$ security delete-certificate -c "iPhone Distribution: Guangzhou HTC Internet Technology Co.,LTD"
13.其它可能使用到的命令(可选)
检查一下是否安装了AppleWWDRCA.cer:
security find-certificate -c "Apple Worldwide Developer Relations Certification Authority"
查看 app 的 entitlements:
codesign --entitlements :- -d Payload/yourAppName.app
3、总结
关于 iOS 重签名流程就这样简单和清晰的列出来了,但是有非常多的知识点可以深入,需要大家自行实践,还有很多坑点,这里只是简单提一下,深入的命令使用和证书知识、证书安全、命令的注意事项等,需要大家实践见真知!
参考
- HanProjectCoder/ResignForiOS: ipa resign
- fastlane/sigh at master · fastlane/fastlane
- cjsliuj/Scalpel: A MacOS app with resign, dylib link injection/delete, ipa metadata edit.
- Scalpel的实现:一款集动态库注入与删除、IPA重签名、IPA元数据修改为一体的MacOS App
- cfgutil man page
- shell - install .p12 or .cer in console macos - Stack Overflow
- reSignature/TFSignature.py at master · hongbaoshi/reSignature
- iOS开发中的应用打包方式及重签名的一些总结 - 简书
- iOS代码签名与重签名 · 0x5e的博客
- DanTheMan827/ios-app-signer: This is an app for OS X that can (re)sign apps and bundle them into ipa files that are ready to be installed on an iOS device.
- iOS App Signer - Instructions
- iPhone手机轻松获取UDID的六种方式 - 简书
- About Code Signing
- ios - Re-signing an IPA that contains a Framework - Stack Overflow
- “User interaction is not allowed” trying to sign an OSX app using codesign
- 如有疑问,欢迎在评论区一起讨论!
- 如有不正确的地方,欢迎指导!
注:本文首发于 iHTCboy's blog,如若转载,请注来源