星的天空的博客

种一颗树,最好的时间是十年前,其次是现在。

0%

iOS的ipa包重签名

日常开发中,我们需要一个Apple账号用于发布App到AppStore,一个企业账号用于内部发布测试及给客户演示。但是Apple限制Bundle Identifier是不能重复的。所以我们有时候需要使用企业证书对个人证书发布的ipa包进行重签名。(注:当然你也可以用于其他用途,但是有被Apple封杀的风险)

模拟数据

为了能对整个流程进行更好的说明,这里设置一些模拟数据

  • App 在AppStore的Bundle Identifier:com.test.AppStore
  • 企业证书的名称:iPhone Distribution: Shenzhen Test Technology Co., Ltd.
  • 企业证书对应的Prefix:828E9CDH56
  • 企业账号用于发布的Provisioning Profiles文件名:TestDistributionForEnterprise.mobileprovision
  • 企业账号用于发布的Provisioning Profiles对应的Bundle Identifiercom.test.enterprise

注:如果重签名后需要支持消息推送服务,需要把对应的Identifiers勾选Push Notifications服务

重签名流程

创建entitlements.plist授权文件

  • entitlements.plist文件内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?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>keychain-access-groups</key>
    <array>
    <string>828E9CDH56.*</string>
    </array>
    <key>get-task-allow</key>
    <false/>
    <key>application-identifier</key>
    <string>828E9CDH56.com.test.enterprise</string>
    <key>com.apple.developer.team-identifier</key>
    <string>828E9CDH56</string>
    <key>aps-environment</key>
    <string>production</string>
    </dict>
    </plist>
  • 图示如下:

ipa文件处理

  • 使用个人账号证书打包(和往常上传AppStore一样操作),导出ipa文件,文件名为test.ipa
  • test.ipa后缀改成zip并进行解压得到一个文件Payload
  • 删除Payload/test.app/_CodeSignature 以及 Payload/test.app/embedded.mobileprovision两个文件

替换证书配置文件(文件名为embedded,不能自定义)

1
cp TestDistributionForEnterprise.mobileprovision Payload/test.app/embedded.mobileprovision

重签名(certifierName为重签名证书文件名,有证书Prefix后缀需要加后缀,以钥匙串里的为准)

1
2
certifierName="iPhone Distribution: Shenzhen Test Technology Co., Ltd."
codesign -f -s $certifierName --entitlements entitlements.plist Payload/test.app

打包

1
zip -r resignTest.ipa Payload

这样就得到了一个新的文件resignTest.ipa,可以企业发布给任何人安装,同时Bundle Identifier依然是com.test.AppStore

注意:
1、如果不在Payload所在目录进行打包,如xxx/Payload,则会导致打包出来的安装包无法安装,原因不明。
2、如果之前有安装过对应App测试版本,会导致安装失败,可能是缓存导致的问题。

Extension支持

在iOS开发中,Extension越来越多,尤其是很多app添加了Today Extension,在重签名的时候需要对extension进行处理,如果有多个extension,那么每个extension都要做重签名处理。对extension进行重签名流程如下:

  • 找到PlugIns目录下对应的Extension文件
  • 与对app进行重签名一样,删除Extension里面的_CodeSignature目录,删除embedded.mobileprovision文件。
  • 使用codesign命令进行重签名,证书与主app一致。命令也一样,修改对应的entitlements.plist和指定目录即可。 例:codesign -f -s $certifierName --entitlements extension_entitlements.plist Payload/test.app/PlugIns/extension.appex

这里有两个注意事项:

  • 先对Extension进行签名,再对主app进行签名,不然会报错说codesign内容被修改之类的错误
  • 重签名的时候注意证书的传参,如果对证书名字中有空格又没有用””引起来,会导致找不到证书。
  • 如果报错This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed.,那么应该是安装了一个同样bundle id的app, 把它删掉重新安装就可以了。

企业发布

  • 按照常规的企业发布方式来即可

    注意:1、企业发布后出现在有些机型可以安装成功,有些机型安装失败,刚开始怀疑是打的包有问题,后来发现是由于用于安装的plist文件里面的display-image以及full-size-image链接有问题,修复后OK
    2、如果出现有的手机能安装, 有的手机不能安装, 那可能是.mobileprovision没有被正确替换导致的。

开源项目

我把整个流程用Python做了一个脚本,功能流程如下 打包ipa–>重签名–>上传服务器–>发送邮件点此可以下载

相关链接

代码签名探析