iOS包重签名技术知识

4,371 阅读7分钟

1、简介

利用Xcode的命令 securitycodesign 重签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(不重签的话,就删除无法签名的插件文件: FrameworkPlugIns 文件夹、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),如若转载,请注来源