本文参考如下资料(建议阅读):
a). 公钥加密算法到底什么鬼
b). The ins and outs of code signing an iOS app
c). 代码签名探析
我们先从code signing的作用说起吧
1. 作用
code signing的最终作用就是保证我们在iOS上的应用从开发者机器上build出来后,到最终安装到用户的iOS设备上,不会被篡改。
至于权限控制,也是基于code signing来保证的。
2. 怎么做到的
下文的内容需要我们对公钥加密算法有所了解,这在参考资料a中有述。
1). 如何签名
根据参考资料b中的签名技能,对app中的binary、script以及其他资源一一进行签名(计算每个文件的摘要,然后将摘要使用私钥加密),然后把签名过的文件放到一个CodeResources的plist文件中。(这个文件存放在_CodeSignature文件夹中),我们不妨看一个实例:
<?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>files</key>
<dict>
<key>AppIcon29x29@2x.png</key>
<data>
eanTrclP/4jBcw+pZZDeVPimJ7g=
</data>
<key>AppIcon29x29@2x~ipad.png</key>
<data>
eanTrclP/4jBcw+pZZDeVPimJ7g=
</data>
<key>AppIcon40x40@2x.png</key>
<data>
xEo0NvwYxXdtywn3iD8yDaF6V1A=
</data>
<key>AppIcon40x40@2x~ipad.png</key>
<data>
xEo0NvwYxXdtywn3iD8yDaF6V1A=
</data>
<key>AppIcon60x60@2x.png</key>
<data>
rMa2+pGtRq8pN4LRcp+dCn5Kai8=
</data>
<key>Base.lproj/Main.storyboardc/BYZ-38-t0r-view-8bC-Xf-vdC.nib</key>
<dict>
<key>hash</key>
<data>
t/7wowkj3how49ccMtcw+bat3sQ=
</data>
<key>optional</key>
<true/>
</dict>
完整的太大了,我们截取一小段观摩。
可以看到key就是文件的名称,data就是文件的签名,由于这个签名无法被篡改,所以plist文件本身不加密也无所谓。
2). 用什么签名
通过前面的参考资料,我们可以了解实际上签名唯一需要的就只是私钥。但在iOS应用签名中,这还不够,我们还需要证书,app id,权限声明,iOS设备,而这些材料我们又可以打包到一种叫做Provision Profile的东西中去,我们在签名的时候(使用mac os x的codesign程式)也只能提供provision profile来工作。
一个Provision Profile的典型结构:
我们来逐一解析各个材料的作用和获取途径(下述内容包含一些臆断的部分,我会用红字标出,因为Apple实在是太封闭了,有些东西我还没没法了解到)。
a). 私钥:实际上私钥和公钥总是成对工作的,缺失其中任何一个之后另一个也是废物一个。在生成证书的时候自然而然会生成密钥对(而且系统会自动关联它们),所以我们放到证书中具体讲述。
b). 证书:为什么需要证书?在前面参考资料中我们了解到,证书实际上是一种身份验证的东西,可想而知这个东西实际上只是iOS系统单方面需要,我们签名实际上并不会用到。证书分为Development/Production(Development/Production对程序的影响本文不予讨论),这在证书中可以看到:
当app安装到iOS上时,iOS系统将取用provision profile中的DeveloperCertificates中的证书来结合CodeResource对app中的文件进行签名验证(证书中的公钥可以解密签名,具体请看参考资料中的『公钥加密算法到底什么鬼』),以确保app中的文件没有被篡改过。
通过参考资料我们了解到生成一个证书文件需要提交一个CSR文件到Apple,然后Apple生成证书给我们,而生成CSR文件的时候就需要我们有密钥对,所以生成证书的时候我们要么会用一个已存在的密钥对,要么就会生成一个新的密钥对。
c). app id:app id用于唯一标识一个应用,一个app在生成的时候会有这个属性,而provision profile中的application-identifier也必须与这个相匹配,值得注意的是匹配并不代表相等,比较贴切的比喻是大于,例如provision profile中的app id如果是*,那将可用于给任何一个app进行签名。但当我们需要用到一些比较特殊的服务的时候就需要provision profile中的app id和app中的app id相等了,比如Apple Push Notification Service。
d). 权限声明:provision profile中的Entitlements和app中的权限声明必须要匹配。
c). iOS设备:ProvisionedDevices包含了使用Development证书或者Ad-hoc证书发行app时可以运行app的设备列表。