iOS如何保证App的安全

证书与密钥

我们从Apple Developer下载的证书,是CA(Certificate Authority)证书,证书中有公钥、有效期和认证机构信息(Apple Worldwide Developer Relations Certificate Authority)。

证书有两种,一种是iPhone Developer,一种是iPhone Distribution。前者用于App的测试开发,后者用于上传App到AppStore。

签名时通过命令行工具codesign来完成的,Xcode在构建完应用后会自动调用codesign对App进行签名(在Xcode > Build Settings > Signing 中设置求签名选项)。

签名可以对任何资源文件进行,在签名完成后,应用中会新建一个_CodeSignatue/CodeResources的文件,文件中存储了被签名的所有文件的签名。

# 签名
$ codesign -s '证书名称' XXX.app

# 重签名
$ codesign -f -s '证书名' XXX.app

# 获得app的签名情况
$ codesign -vv -d XXX.app

======
Executable=/Users/toto/Library/Developer/Xcode/DerivedData/Example-cfsbhbvmswdivqhekxfykvkpngkg/Build/Products/Debug-iphoneos/Example.app/Example
Identifier=ch.kollba.example
Format=bundle with Mach-O thin (arm64)
CodeDirectory v=20200 size=26663 flags=0x0(none) hashes=1324+5 location=embedded
Signature size=4336
Authority=iPhone Developer: Thomas Kollbach (7TPNXN7G6K)
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=29.09.2014 22:29:07
Info.plist entries=33
TeamIdentifier=DZM8538E3E
Sealed Resources version=2 rules=4 files=120
Internal requirements count=1 size=184
======

# 验证签名情况
$ codesign --verify XXX.app


授权机制(Entitlements)

授权机制决定了系统资源在什么情况下可以被应用使用。简单地说就是沙盒的配置表,上面记录的是权限控制。

授权机制的配置是以plist文件格式保存的,xcode会将这个文件作为 --entitlements参数的内容传给codesign。

<?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>application-identifier</key>
        <string>7TPNXN7G6K.ch.kollba.example</string>
        <key>aps-environment</key>
        <string>development</string>
        <key>com.apple.developer.team-identifier</key>
        <string>7TPNXN7G6K</string>
        <key>com.apple.developer.ubiquity-container-identifiers</key>
        <array>
                <string>7TPNXN7G6K.ch.kollba.example</string>
        </array>
        <key>com.apple.developer.ubiquity-kvstore-identifier</key>
        <string>7TPNXN7G6K.ch.kollba.example</string>
        <key>com.apple.security.application-groups</key>
        <array>
                <string>group.ch.kollba.example</string>
        </array>
        <key>get-task-allow</key>
        <true/>
</dict>
</plist>

可以在Xcode > Capabilities的选项中,设置需要开启的权限。当权限开启后,Xcode就会生成一段这样的XML,并生成一个.entitlements文件。

当构建App时,这个文件也会被codesign读取,作为应用授权的参考。这些授权都必须在Apple Developer相关联的App Id中开启,并包含在配置文件内。

可以用下面的形式查看App的签名信息中,包含了什么授权。

$ codesign -d --entitlements - XXX.app

配置文件(Provisioning Profiles)

配置文件将代码签名、沙盒和授权机制联系在一起。

配置文件中存放了系统用于判断App是否被允许运行,是否允许App在某个特定设备上运行等的信息。

配置文件可以让应用在开发设备上被运行和调试,也可以用于内部测试(Ad-Hoc)或者企业级App发布。Xcode会将项目设置的配置文件打包进应用内。

配置文件并不是一个plist,而是一个根据密码信息语法(Cryptographic Message Syntax)加密的文件。

可以用下面的命令来查看配置文件中的内容

$ security cms -D -i example.mobileprovision

参考资料

代码签名探析