创建Apple设备描述文件并签名

Apple开发者上大会宣布可以在macOS11.0和iOS14以上的设备上设置DoH和DoT,但是只支持用设备描述文件的方式来进行配置,这两天好奇了一下,这篇文章记录一下关于设备描述文件的资料以及给配置文件的签名的方法。

创建设备描述文件

所谓设备描述文件就是一个xml格式的文档,里面记录了各个配置项的值,具体内容参照下面的官方文档即可。

文件所需的Payload UUID可以使用uuidgen生成,相同id的描述文件重复安装会覆盖。

描述文件的签名

将上一步骤的文件存储为.mobileconfig拓展名的文件就可以直接在设备上打开安装了,只不过这时候描述文件会显示为未验证或者不受信任,这让强迫症很难受,同时也没法确保文件在传输过程中不被篡改,所以我们要给文件加上电子签名。

首先要说明,这里苹果并不在意证书的用途,只验证证书信任链,所以对于我们没有注册成为开发者的人来说,可以用两种方法建立信任:一是使用Let's Encrypt等签发的域名证书,因为其根证书收到苹果信任,用这种方式签名的证书也会受到信任;二是建立自己的自签名根证书并导入设备,之后直接使用根证书签名或者使用根证书再签发证书建立自己的信任链。

考虑到Let's Encrypt的签发的证书有效期只有3个月,同时描述文件主要是用来给自己用或者是给组织内部使用,所以主要介绍使用自签名的方式建立信任,把借助SSL证书建立信任的方式放在最后。

这里还要说下,如果已经是苹果的开发者了,拥有苹果签发的开发者证书的话可以直接跳到最后"碎碎念"部分

使用自签名证书

这里我们按照三级结构Root CA --> Intermediate CA --> Leaf CA的方式来建立。

整个步骤使用macOS自带的"钥匙串访问"和App Store下载的"Apple Configurator 2"即可轻松完成,当然也可以选用openssl来创建。

  1. 首先在钥匙串中使用证书助理创建证书颁发机构选择创建根证书,然后再次创建证书颁发机构,这次选择创建中间证书并且选择使用刚刚创建的根证书签名,最后点击创建证书使用中级证书签名,创建叶子证书。
  2. 将自己的根证书标记为受信任,并导出,导出类型选择.cer即可。
  3. 完成后将描述文件用"Apple Configurator 2"打开,选择"文件->签名",选择上一步创建的叶子证书签名。
  4. 将步骤2导出的根证书在设备上打开,会自动创建包含证书的描述文件,选择安装就会将自己的根证书加入到受信任证书列表中了。
  5. 将签名后的描述文件发送给设备,在设备上打开,这时因为根证书收到信任,所以中间证书收到信任,所以叶子证书收到信任,如果签名校验没有错误的话就会显示描述文件受到信任了。

keychain

完成上面几个步骤后,对于个人来说我们可以把签名过的描述文件放到网上存储,用自己需要使用的设备访问下载,只要下载后的文件验证通过,就可以证明文件的确是自己的没有被篡改。对于组织来说可以把组织自己的Root CA预先配置在设备里面,只要描述文件签名验证通过就可以证明该文件确实为组织管理员所发布并且没有被篡改。

使用SSL证书进行签名

这里因为域名证书的用途里面不包含代码签名,所以就算导入到钥匙串中,证书也不会出现在上述工具的可用证书列表里,所以我们只能使用openssl来完成。

Let's Encrypt签发的证书为例,我们会得到fullchain.pemprivkey.pem两个文件,将他们scp到本地:

  • fullchain.pem包含了发给我们域名的叶子证书以及用于建立信任链的中级证书
  • privkey.pem则是我们证书的私钥,特别注意这里的私钥是没有密码保护的,要特别注意安全

主要步骤:

  1. fullchain.pem中的叶子证书和中间证书分开保存,前面的部分为叶子证书(server.crt),后面的为中间证书(ca.crt)
  2. 签名 openssl smime -sign -in unsigned.mobileconfig -out signed.mobileconfig -signer server.crt -inkey server.key -certfile ca.crt -outform der -nodetach

完成后就可以将描述文件发布到网上供人下载了,因为Let's Encrypt的根证书本身是受到设备系统信任的,就不需要再导入根证书了。

碎碎念

在苹果提供"Apple Configurator 2"工具之前,网上针对个人开发者证书的方法是:首先把个人开发者证书导出(.p12),然后用openssl拆分成证书和私钥,因为格式不对还要转换格式(cer->crt),然后再把Apple的中级证书下载下来合并到里面构建信任链最后再签名。

这个流程很繁琐,而且过程中先是把钥匙串中的私钥导出来,又把有密码保护的私钥直接暴露了出来,增加了安全风险,现在已经没有必要,对于有开发者证书的人来说直接按照"使用自签名证书"的步骤3选择自己的证书签名然后分发就可以了,节省时间同时也增加安全性。

关于如何把证书私钥导入到钥匙串

这几天仔细研究了一下钥匙串,感觉把私钥放到钥匙串保存应该比我自己靠谱不少。但是发现直接双击.pem格式的私钥会提示项目已损坏无法取回导入失败,试验来看似乎只接受.p12格式:

  1. 将证书和私钥匙放在一起,对于Let's Encrypt签发的来说把server.key粘贴到fullchain.pem后面就可以了 cat server.key >> fullchain.pem
  2. 使用openssl转换格式openssl pkcs12 -export -in fullchain.pem -out cer.p12

参考资料

  1. Mobileconfig SSL签名
  2. Over-the-air IPhone Setup Using a Signed .mobileconfig File

创建Apple设备描述文件并签名
https://blog.yrpang.com/posts/6894/
作者
yrPang
发布于
2020年11月15日
许可协议