iOS包重签名技术知识

6,439 阅读7分钟

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 重签名流程就这样简单和清晰的列出来了,但是有非常多的知识点可以深入,需要大家自行实践,还有很多坑点,这里只是简单提一下,深入的命令使用和证书知识、证书安全、命令的注意事项等,需要大家实践见真知!

参考


  • 如有疑问,欢迎在评论区一起讨论!
  • 如有不正确的地方,欢迎指导!

> 注:本文首发于 [iHTCboy's blog](https://iHTCboy.com),如若转载,请注来源