细谈证书与Provisioning Profile

简介: iOS程序员大多对证书和Provisioning Profile懵逼过吧,是时候整理一下思路了,把这个问题讲讲清楚。所有配置都在[https://developer.apple.com](https://developer.apple.com),大家都可以上去摸索一下。 ### 证书 打开`钥匙串访问`可以看到里面有`证书`和`我的证书`两项,其中`证书`包含系统安装的所有证书,`我的

iOS程序员大多对证书和Provisioning Profile懵逼过吧,是时候整理一下思路了,把这个问题讲讲清楚。所有配置都在https://developer.apple.com,大家都可以上去摸索一下。

证书

打开钥匙串访问可以看到里面有证书我的证书两项,其中证书包含系统安装的所有证书,我的证书则仅包含电脑上有私钥的证书。

screenshot.png

私钥是用来签名的,通过签名可以确保程序是没有被篡改的。其中私钥放在自己电脑上,公钥则放在苹果服务器上。

模拟器运行App是不需要签名的,真机调试和上传AppStore的包都需要签名,主程序和所有的动态库都要签名。

//模拟器也调用了codesign,但是没有选择证书。
CodeSign /Users/henshao/Library/Developer/Xcode/DerivedData/CloudConsoleApp-gszptqenpqtwraajgpawanvtjtny/Build/Products/Debug-iphonesimulator/CloudConsoleApp.app
    cd /Users/henshao/cloudconsole-iOS
    export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    
Signing Identity:     "-"

    /usr/bin/codesign --force --sign - --timestamp=none /Users/henshao/Library/Developer/Xcode/DerivedData/CloudConsoleApp-gszptqenpqtwraajgpawanvtjtny/Build/Products/Debug-iphonesimulator/CloudConsoleApp.app

//真机codesign选择了证书
CodeSign /Users/henshao/Library/Developer/Xcode/DerivedData/CloudConsoleApp-gszptqenpqtwraajgpawanvtjtny/Build/Products/Debug-iphoneos/CloudConsoleApp.app
    cd /Users/henshao/cloudconsole-iOS
    export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    
Signing Identity:     "iPhone Developer: 智杰 付 (WTLVCA9D68)"
Provisioning Profile: "iOS Team Provisioning Profile: com.aliyun.wstudio.amc.AliyunMobileAppDevelop"
                      (e6dc1bc1-140c-4003-b91b-817535a46ae4)

    /usr/bin/codesign --force --sign AB9AB462D723988FB08AF1265BE1B574DD273DCB --entitlements /Users/henshao/Library/Developer/Xcode/DerivedData/CloudConsoleApp-gszptqenpqtwraajgpawanvtjtny/Build/Intermediates/CloudConsoleApp.build/Debug-iphoneos/CloudConsoleApp.build/CloudConsoleApp.app.xcent --timestamp=none /Users/henshao/Library/Developer/Xcode/DerivedData/CloudConsoleApp-gszptqenpqtwraajgpawanvtjtny/Build/Products/Debug-iphoneos/CloudConsoleApp.app

解压开ipa可以发现,里面有一个_CodeSignature/CodeResources文件,这是一个XML文件,打开可以看到里面的内容。

<key>Frameworks/AFNetworking.framework/AFNetworking</key>
<dict>
    <key>hash</key>
    <data>
    gF72IVSBtCx2WdGfkervPKcCmZw=
    </data>
    <key>hash2</key>
    <data>
    kySS3fap6mMdMztbVQ0BPcQqGHwDKowHON1fHzQ6P4k=
    </data>
</dict>
<key>Frameworks/AFNetworking.framework/Info.plist</key>
<dict>
    <key>hash</key>
    <data>
    6AnKOHTiBpi15MSyr4X4yhapLxc=
    </data>
    <key>hash2</key>
    <data>
    D5xPZO6XisdE1hSvSAioGQv9RHryi33o8j6GwaNOOT4=
    </data>
</dict>
<key>Frameworks/AFNetworking.framework/_CodeSignature/CodeResources</key>
<dict>
    <key>hash</key>
    <data>
    +eORwOY/EikcBmsFZfD7QEDo3Qw=
    </data>
    <key>hash2</key>
    <data>
    bqs1RQcVX2sq7r0OewcocgvkivH0PSm6hgcqh/99iDI=
    </data>
</dict>

有趣的是动态库也会拥有自己有的_CodeSignature/CodeResources,但是里面的内容非常简单,只有Info.plist的,签名结果跟外面的是一样的。

<dict>
    <key>Info.plist</key>
    <data>
    6AnKOHTiBpi15MSyr4X4yhapLxc=
    </data>
</dict>

任何有效的证书都可以用来签名。所以这样不牢靠对不对?当年塞班时候,改签真的很容易,轻松安装各种程序。苹果要想的更加周到一些,比如下面要讲的Provisioning Profile。当然不遵守规则重签也是可以做到的,只是稍微增加了一些难度。

Provisioning Profile

解压开ipa文件,可以在Payload目录发现有一个embedded.mobileprovision文件。

[~/Downloads/CloudConsoleApp-Release/Payload]$ ll CloudConsoleApp.app/embedded.mobileprovision 
-rw-r--r-- 1 henshao staff 7.8K 10 21 03:01 CloudConsoleApp.app/embedded.mobileprovision

Provisioning Profile是一个很复杂的东西,包含了很多东西,可以在https://developer.apple.com里面试着生成一个Provisioning Profile,看看每个步骤都需要填些什么。Provisioning Profile包含了证书(公钥)、App ID、entitlements、device list等关乎App能否正常启动的所有信息。证书是给ipa签名的,在打包的时候起作用;而Provisioning Profile要打进ipa里面,在启动的时候起作用

//使用这个命令可以解开文件看看里面的内容
security cms -D -i embedded.mobileprovision

screenshot.png

screenshot.png

screenshot.png

找一些iOS重签名的文章:再谈 iOS 重签名,可以发现,重签名之前,要把自己的mobileprovision拷贝到ipa指定目录里面。

Team

Xcode为了简化配置,设计了一个team的概念。只要在https://developer.apple.com里面添加了Apple ID,然后该用户在Xcode里面登录一下。遇到签名的问题,直接fix issue就可以了。这个过程中把证书和Provisioning Profile相关的配置都做好了。

一个用户可能加入多个team,如何区分这个用户在不同team里面创建的App ID呢?为了解决这问题,苹果设计了Team IDTeam ID加上Bundle ID构成完整的App ID

screenshot.png

带通配符的App ID可以表示一类App,Provisioning Profile使用这种App ID可用于team里面所有的App。Xcode fix issue喜欢创建这种类型的Provisioning Profile。

screenshot.png

推送证书

推送服务器跟苹果APNs发消息,是需要认证的。苹果提供下面两种认证的方式。

//目前还没有听说谁在用这种方式
Token-based connection trust A provider using the HTTP/2-based API can use JSON web tokens (JWT) to validate the provider’s connection with APNs. In this scheme, the provider does not require a certificate-plus-private key to establish connection. Instead, you provision a public key to be retained by Apple, and a private key which you retain and protect. Your providers then use your private key to generate and sign JWT authentication tokens. Each of your push requests must include an authentication token.

//一般都用这种方式
Certificate-based connection trust A provider can, alternatively, employ a unique provider certificate and private cryptographic key. The provider certificate, provisioned by Apple when you establish your push service in your online developer account, identifies the topics supported by the provider. Each topic is the bundle ID associated with one of your apps.

screenshot.png

screenshot.png

因为我们使用的是Agoo推送平台,所以要把相关的证书放到Agoo平台上。但是Agoo有一个问题是每个AppKey只支持放一个证书,所以我们不能为com.aliyun.wstudio.amc.AliyunMobileAppcom.aliyun.wstudio.amc.AliyunMobileAppDevelop分别设置推送证书。

推送平台需要一个包含证书和私钥的p12文件,而只有当初生成推送证书的人才能正常导出p12文件。为了避免紧急情况下,找不到当事人,所以我们在App代码根目录下存放了一份p12文件,并且标明了过期时间,可确保万无一失。

$ tree CertificateExpireAt20170324 
CertificateExpireAt20170324
├── AliyunMobileApp-APNs-prod.p12
└── push.passwd

更多详细信息可以参看:Local and Remote Notifications Overview

推送测试

命令行

使用Houston给iOS APP推送信息,拿到证书和token就可以在命令行下面做一些自动化的推送工作。

图形化工具

Easy APNs Provider这款工具很不错,在Mac App Store可以下载到。证书直接用cer就好了。Houston需要把证书转换成pem格式才行。

Snip20161130_3.png

摩天轮上的配置

摩天轮打包时需要配置证书和Provisioning Profile。

screenshot.png

摩天轮同学有企业账号,所以可以制作企业证书打In-House的包。因为我们自己的账号已经注册了com.aliyun.wstudio.amc.AliyunMobileApp这个App ID,所以测试包不能再使用这个AppID了。为了解决这个问题,并且满足黑匣子的需要,摩天轮会自动设置Bundle ID为com.aliyun.wstudio.amc.AliyunMobileApp.xxx。仲宇会默默在开发者中心帮我们生成对应的Provision Profile,并且丢到摩天轮上。

好在现在有一个工具:fastlane,可以使用脚本来生成证书。摩天轮正在考虑通过fastlane来优化打包的体验。如果能做到在摩天轮上打企业包测试,还能打发布包,并且上传到AppStore,那就完美了。

AppStore的特殊性

App提交苹果审核之后,苹果会对App重签名。通过codesign可以看到mtl打出来的包都是我们自己证书签名的,而AppStore的包签名的证书都是苹果的。

//企业包
[~/Downloads/CloudConsoleApp-Release/Payload]$ codesign -vv -d CloudConsoleApp.app/
Executable=/Users/henshao/Downloads/CloudConsoleApp-Release/Payload/CloudConsoleApp.app/CloudConsoleApp
Identifier=com.aliyun.wstudio.amc.AliyunMobileApp
Format=app bundle with Mach-O universal (armv7 arm64)
CodeDirectory v=20200 size=193958 flags=0x0(none) hashes=6053+5 location=embedded
Signature size=4737
Authority=iPhone Distribution: Alibaba Cloud Computing Ltd. (QBMN2BBW3K)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=2016年10月21日 上午3:02:00
Info.plist entries=40
TeamIdentifier=QBMN2BBW3K
Sealed Resources version=2 rules=13 files=1451
Internal requirements count=1 size=220

//AppStore包
[~/wechat]$ codesign -vv -d WeChat.app/
Executable=/Users/henshao/wechat/WeChat.app/WeChat
Identifier=com.tencent.xin
Format=app bundle with Mach-O universal (armv7 arm64)
CodeDirectory v=20200 size=191179 flags=0x0(none) hashes=9550+5 location=embedded
Signature size=3487
Authority=Apple iPhone OS Application Signing
Authority=Apple iPhone Certification Authority
Authority=Apple Root CA
Info.plist entries=43
TeamIdentifier=88L2Q4487U
Sealed Resources version=2 rules=13 files=3005
Internal requirements count=1 size=96

参考文章

  1. 代码签名探析
  2. 关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系
  3. 苹果开发者账号那些事儿(三)
  4. 漫谈iOS程序的证书和签名机制
  5. 阮一峰的网络日志 博客上也有一些关于HTTPS、SSL、证书的科普文值得一看。
相关文章
|
监控 负载均衡 应用服务中间件
Passenger作用及原理梳理
我们在部署rails应用时,大多时候都使用Nginx+Passenger的方式部署,本文主要对此架构下 Passenger的作用及其工作原理进行梳理。 一、什么是Passenger? Phusion Passenger是一个开源的Web应用服务器,它能够处理HTTP请求,管理进程和资源、 系统监控以
848 0
|
Unix 编译器 Linux
CMake Install:深度解析与实践(一)
CMake Install:深度解析与实践
897 0
|
Java 开发工具
mac下解决intellij idea启动慢和debug卡死问题
mac下解决intellij idea启动慢和debug卡死问题
3617 0
mac下解决intellij idea启动慢和debug卡死问题
|
11月前
|
JavaScript 安全 Java
谈谈UDP、HTTP、SSL、TLS协议在java中的实际应用
下面我将详细介绍UDP、HTTP、SSL、TLS协议及其工作原理,并提供Java代码示例(由于Deno是一个基于Node.js的运行时,Java代码无法直接在Deno中运行,但可以通过理解Java示例来类比Deno中的实现)。
203 1
|
存储 关系型数据库 数据处理
在 Postgres 中使用创建临时表
【8月更文挑战第11天】
642 0
|
机器学习/深度学习 存储 人工智能
构建坚不可摧的系统安全防线:策略、实践与未来展望
系统安全是维护社会稳定、保障企业运营和个人隐私的重要基石。构建坚不可摧的系统安全防线需要从多个维度出发制定全面的安全策略并付诸实践。未来随着技术的不断进步和应用场景的不断拓展,系统安全将面临更多的挑战和机遇。只有不断创新和完善安全技术和策略才能应对日益复杂的安全威胁和挑战确保系统的安全和稳定运行。
|
JavaScript
WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载
WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载
226 1
|
iOS开发 开发者
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
|
存储 缓存 移动开发
别催更啦!手淘全链路性能优化下篇--容器极速之路
历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)我们重点介绍了手淘在性能优化中的一些实践和思路,主要集中在原生的代码的优化,这次,我们将继续分享在手淘容器化页面如 H5 及 Weex 相关的优化实践。
别催更啦!手淘全链路性能优化下篇--容器极速之路
|
Linux 数据安全/隐私保护 Android开发
哪家好用?四款国内外远程桌面软件横测:ToDesk、向日葵、TeamViewer、AnyDesk
远程桌面软件对于职场人来说并不陌生,可以说是必备的办公软件之一。在经历过新冠疫情后,大家对于远程办公的认识越来越深入,也就在这段期间,远程桌面软件大范围的应用起来,真正走进大众视野并融入我们的工作和生活。 为了方便远程办公协作,国内外出现了很多远程桌面软件,结合功能实用性和价格优势,我总结了目前主流的四款:ToDesk、向日葵、TeamViewer、AnyDesk,逐个测评下它们的功能和使用感受,用最直白的话告诉你实际的体验,帮助你找到最适合你的远控软件。