自动化流程完成 打包 IPA 到 上传 AppStore 之 iOS IPA签名

 

自动化流程完成 打包 IPA 到 上传 AppStore 需要哪几部呢?

 

第一步: 证书生成、导入

第二步: App 创建、填写相关信息,上传相关文件

第三步: 自动化打包 IPA

第四步: 自动化重签名

第五步: 自动化上传 App Store

 

本篇文章目前实现

第一步的部分 证书导入 (主要解决导入过程 可能会弹出需要手动输入证书密码的问题) 

第四步的部分 自动化重签名 (重签名踩坑)

 

自动安装证书和描述文件

#解锁 钥匙串

security unlock-keychain -p 电脑密码 $HOME/Library/Keychains/login.keychain

# 导入 证书

security import xxxxxxxx.p12 -k $HOME/Library/Keychains/login.keychain -P $p12Pwd -T /usr/bin/codesign

 #拷贝 描述文件   $HOME/Library/MobileDevice/"Provisioning Profiles"/  电脑都所有描述文件都放在这个路径下

cp xxxxxxxxxx.mobileprovision $HOME/Library/MobileDevice/"Provisioning Profiles"/$bundleid.mobileprovision

 

解除 弹出UI 框 需要输入密码才能正常签名ipa包

在 macOS 10.12.5 之后,提供了 security set-key-partition-list 命令,用于设置 key 到 “partition list” 中。作为 ACL(Access Control Lists)的补充,根据应用签名,对访问进行权限控制。

可以通过 man security 进行查看

security set-key-partition-list -S apple-tool:,apple: -s -k 电脑密码 ~/Library/Keychains/login.keychain-db

解释一下其中几个参数:

  • -S:提供的访问权限,多个 key 用逗号分隔。苹果的工具可以用 apple-tool:,apple:,如 codesign 就可以设置这两个 key。
  • -s:指定用于 codesign 的 private key。
  • -k:修改 partition list 需要提供钥匙串密码。

所以以上的命令作用为:给 login.keychain 中用于 codesign 的 private key,写入苹果产品的权限。

注意:set-key-partition-lis 对 key 的操作是重写,不是追加。

参考自这里 : http://saitjr.com/ios/security-set-partition-list.html 感谢作者

这种方式 仅验证了 对于 脚本导入的 证书才有效

也就是通过命令  security import xxxxxxxx.p12  这种方式导入的证书  如果是双击证书导入的 还是会弹出UI框 输入密码才能签名

我估计是 -S apple-tool:,apple: 这部分参数的问题  因为这两种方式区别在于导入证书的用户变了 导致权限变了

 

#自动出包 或者App 破解 重新打包 都需要用到重签名。

重签名分 三步

解压原有ipa后

一、 替换 app 中的 profile 文件

二、 获取 你使用签名 证书的 名字  类似 "iPhone Distribution: XXXXXXXX. (*****)"

三、 签名   同时  使用 -o 参数修改 签名的app  -i 参数修改 bundleid 类似这样

# ipacert="iPhone Distribution: XXXXXXXX. (*****)"        0x20200 代表xcode
# ipacert 你可以通过这样获取
# security cms -D -i $uploadpath/embedded.mobileprovision  > plistfile
# TeamIdentifier=`/usr/libexec/PlistBuddy -c 'Print :TeamIdentifier:0' plistfile`
# TeamName=`/usr/libexec/PlistBuddy -c 'Print :TeamName' plistfile`
# certname="iPhone Distribution: ${TeamName} (${TeamIdentifier})"

# 然后签名
# codesign -f -o 0x20200 -i $bundleId -s "$ipacert" xxxxxx.mobileprovision --entitlements t_entitlements.plist xxxx.app

将 xxxx.app 放入一个 Payload 文件夹内  然后压缩成 xxxx.ipa 就可以了

 

#重签名  根据描述文件 导出证书相关信息

security cms -D -i xxxxx.mobileprovision > t_entitlements_full.plist

#通过PlistBuddy  从中拿出重签名需要的部分 

/usr/libexec/PlistBuddy -x -c 'Print:Entitlements' t_entitlements_full.plist > t_entitlements.plist

#同样的解锁钥匙串

 security unlock-keychain -p 你的电脑密码 $HOME/Library/Keychains/login.keychain

#然后进行签名  

# codesign -fs "$ipacert"  xxxxx.mobileprovision --entitlements t_entitlements.plist xxxx.app

以上是针对 没有Framework等情况  如果 xxx.app 中存在 Frameworks 文件夹, 里面的 Framework  需要单独签名, 而且需要先签名 里面的Framework 再签外面的App 流程反了会导致签名无效,这就相当于 你在对App做了签名以后 又重新修改了里面的内容

if [ -d ipa/Payload/xxxx.app/Frameworks ]; then
    for file in ipa/Payload/xxxx.app/Frameworks/*
    do 
        if test -d $file; then
            rm -rf $file/_CodeSignature
            codesign -f -o 0x20200 -s "$IpaCert"  embedded.mobileprovision $file
        fi
    done
fi
codesign -f -o 0x20200 -i $BundleId  -s "$IpaCert"  embedded.mobileprovision --entitlements t_entitlements.plist ipa/Payload/xxxx.app

 

20200710 更新

今天 部分 app 包签名的时候报  no identity found, 再三确认 证书已经安装 描述文件也没错。 执行

  codesign -fs "iPhone Distribution: Shanghai xxxxxxxxx, Ltd. (xxxxxx)" upload/embedded.mobileprovision --entitlements t_entitlements.plist ipa/Payload/Unity-iPhone.app

security find-identity -p codesigning|grep $teamId

 32) 46AC3DAA61B7265FBD37BF6994F5FFA85CF7F535 "iPhone Distribution: Shanghai xxxxxxxxx Co.,  Ltd. (xxxxxx)"

再三比对  没错啊? 一度怀疑科学!后面用 beyondcompare 发现 Ltd 前面多了个空格  于是添加了空格 继续签名

codesign -fs "iPhone Distribution: Shanghai xxxxxxxxx,  Ltd. (xxxxxx)" upload/embedded.mobileprovision --entitlements t_entitlements.plist ipa/Payload/Unity-iPhone.app
签名成功了 但是上传 Apple 返回
ERROR ITMS-90046: "Invalid Code Signing Entitlements. Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, 
value 'xxxxxx.com.xxxxx.oxzpabyt' for key 'application-identifier' in 'Payload/Unity-iPhone.app/Frameworks/xxxxxxx.framework/xxxxx' is not supported.
This value should be a string starting with your TEAMID, followed by a dot '.', followed by the bundle identifier.
"

但是我试了下 用xcode导出是能够正常上传的,比对两种方式产生的 IPA 包,发现只有时间和 签名不一样

验证签名的证书名字  teamid 都是一样的 这就很尴尬了  为毛呢?   没找到原因 而且难以复现!

 

 

 

要注意一个问题   签名是签的 xxxx.app,而不是xxxx.ipa。  如果是签名 xxxx.ipa 是会有问题的,因为这样你仅仅是对xxxx.ipa这个 文件进行了签名,而不是里面的内容。  这样签出来上传到后台,苹果会拒绝的。

一定要签名 xxxxx.app 文件 然后 放入Payload文件夹 然后把Payload文件夹重新压缩成 xxxx.ipa   如果你的App 中包含了很多 xxxxx.Framework 等文件 需要将Framework等文件单独签名

完成后 你可以通过以下命令查看签名的相关信息

codesign -d --entitlements - xxxx.app
查看这个app 签名 的所有相关配置

会得到类似的结果 entitlements :

application-identifier
7TPNXN7G6K.ch.kollba.example
aps-environment
development
com.apple.developer.team-identifier
7TPNXN7G6K
com.apple.developer.ubiquity-container-identifiers

7TPNXN7G6K.ch.kollba.example

com.apple.developer.ubiquity-kvstore-identifier
7TPNXN7G6K.ch.kollba.example
com.apple.security.application-groups

group.ch.kollba.example

get-task-allow

可以对比 输出的  application-identifier 等值 和 你签名的证书比较  是否签名成功

 

签名成功后,可以用codesign校验 签名是否有效, 需要 将game.ipa 解压出app 然后用以下命令

codesign --verify xxxx.app

如果什么都没输出 说明校验通过

这样就不用等上传苹果后台才知道签名是否成功了

 

同时你还可以通过以下命令查看 app的签名信息

# codesign -dvvv xxxx.app

查看当前 xcodebuild 使用xcode版本路径

xcode-select -p

修改 xcodebuild 使用xcode版本路径

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

 

我 遇到一个困扰我 几天的问题    

a sealed resource is missing or invalid

一直没找到问题在哪里 

我试了脚本打包出ipa 然后手动xcode签名 没有问题

也试了xcode打包ipa 然后xcode签名 都没有问题

然而 我通过脚本打包ipa  同时脚本签名的时候 就出现这个错误 无法上传 后台

找了种种方式 最后才找到问题

思路是这样的 我们需要了解苹果包的内容 

一个app包 里面包括 一个_CodeResource 文件夹 里面的文件记录了整个App包的内容和签名

我通过 文件对比发现我脚本打包出来的App包 和 xcode 打包同一个工程的App包 的_CodeSignature 下的 CodeResources 文件 发现一个隐藏文件的签名不一致

最终找到 并解决了这个问题 脚本签名的时候会 无法读取到它 但是xcode 会把它干掉   是__MacOS 文件夹里的隐藏文件

 

看到一篇讲 ios 签名讲的很棒的一个文章  http://www.cocoachina.com/articles/9949   它是整理自  https://objccn.io/issue-17-2/

以下内容节选自以上链接

六、资源文件签名

iOS 和 OS X 的应用和框架则是包含了它们所需要的资源在其中的。这些资源包括图片和不同的语言文件,资源中也包括很重要的应用组成部分例如 XIB/NIB 文件,存档文件(archives),甚至是证书文件。所以为一个程序包设置签名时,这个包中的所有资源文件也都会被设置签名。

为了达到为所有文件设置签名的目的,签名的过程中会在程序包(即Example.app)中新建一个叫做 _CodeSignatue/CodeResources 的文件,这个文件中存储了被签名的程序包中所有文件的签名。你可以自己去查看这个签名列表文件,它仅仅是一个 plist 格式文件。

这个列表文件中不光包含了文件和它们的签名的列表,还包含了一系列规则,这些规则决定了哪些资源文件应当被设置签名。伴随 OS X 10.10 DP 5 和 10.9.5 版本的发布,苹果改变了代码签名的格式,也改变了有关资源的规则。如果你使用10.9.5或者更高版本的 codesign 工具,在 CodeResources 文件中会有4个不同区域,其中的 rules 和 files 是为老版本准备的,而 files2 和 rules2 是为新的第二版的代码签名准备的。最主要的区别是在新版本中你无法再将某些资源文件排除在代码签名之外,在过去你是可以的,只要在被设置签名的程序包中添加一个名为 ResourceRules.plist 的文件,这个文件会规定哪些资源文件在检查代码签名是否完好时应该被忽略。但是在新版本的代码签名中,这种做法不再有效。所有的代码文件和资源文件都必须 设置签名,不再可以有例外。在新版本的代码签名规定中,一个程序包中的可执行程序包,例如扩展 (extension),是一个独立的需要设置签名的个体,在检查签名是否完整时应当被单独对待。

七、授权文件(entitlements)

在 iOS 上你的应用能做什么依然是沙盒限制的,这些限制大多情况下都由授权文件(entitlements)来决定。授权机制决定了哪些系统资源在什么情况下允许被一个应用使用,简单的说它就是一个沙盒的配置列表。

运行如下命令:

$ codesign -d --entitlements - Example.app

会得到类似的结果:

application-identifier
7TPNXN7G6K.ch.kollba.example
aps-environment
development
com.apple.developer.team-identifier
7TPNXN7G6K
com.apple.developer.ubiquity-container-identifiers
7TPNXN7G6K.ch.kollba.example
com.apple.developer.ubiquity-kvstore-identifier
7TPNXN7G6K.ch.kollba.example
com.apple.security.application-groups
group.ch.kollba.example
get-task-allow

在 Xcode 的 Capabilities 选项卡下选择一些选项之后,Xcode 就会生成这样一段 XML。 Xcode 会自动生成一个 .entitlements 文件,然后在需要的时候往里面添加条目。当构建整个应用时,这个文件也会提交给 codesign 作为应用所需要拥有哪些授权的参考。这些授权信息必须都在开发者中心的 App ID 中启用,并且包含在后文介绍的描述文件中。在构建应用时需要使用的授权文件可以在 Xcode build setting 中的 code signing entitlements中设置。

在新版本的 Xcode 6 之后,授权信息列表会以 Example.app.xcent 这样的名字的文件形式包含在应用包中。这么做或许是为了在出现配置错误时提供更加有用的错误信息。

八、描述文件(provisioning file)

在整个代码签名和沙盒机制中有一个组成部分将签名,授权和沙盒联系了起来,那就是描述文件 (provisioning profiles)。

OS X中保存目录

Xcode 将从开发者中心下载的全部配置文件都放在了这里:

~/Library/MobileDevice/Provisioning Profiles

描述文件并不是一个普通的plist文件,它是一个根据密码讯息语法 (Cryptographic Message Syntax) 加密的文件。

以XML格式查看该文件的命令:

$ security cms -D -i example.mobileprovision

描述文件主要包含以下内容:

· UUID

每一个配置文件都有它自己的 UUID 。Xcode 会用这个 UUID 来作为标识,记录你在 build settings 中选择了哪一个配置文件。

· ProvisionedDevices

记录所有可用于调试的设备ID。

· DeveloperCertificates

包含了可以为使用这个配置文件的应用签名的所有证书。所有的证书都是基于 Base64 编码符合 PEM (Privacy Enhanced Mail, RFC 1848) 格式的。

· Entitlements

有关前面讲到的配置文件的所有内容都会被保存在这里。

posted @ 2020-04-14 00:03  lesten  阅读(1267)  评论(0编辑  收藏  举报