包格式

简介

应用程序管理器使用一个非常简单的包格式:标准的 UNIX gzip 压缩的 TAR 归档。元数据作为普通文件嵌入,但使用保留的名称前缀 --PACKAGE-。尽管 USTAR 归档支持许多功能,但应用程序管理器仅支持具有相对路径的标准文件和目录(路径中使用 ../ 是不允许的)。除了所有者的 x 位之外的模式将被忽略。

这使得编写自定义打包程序以及自定义应用商店服务器后端变得非常容易,因为任何编程语言中的实用库都提供了 TAR 归档处理。

注意:目前 gzip 被硬编码,但由于压缩和解压缩是由 libarchive 来完成的,因此很容易用 bzip2 或 xz 压缩来替换。但在 Windows 上,这将导致引入额外的第三方依赖。

以下是包中的重要文件

文件描述
--PACKAGE-HEADER--正好有一个 YAML 文档,需要是该包中的第一个文件 - 有关格式描述,请参见下文。此文件用作格式选择器。
info.yaml应用程序的清单。打包工具需要确保此文件位于归档的前 10 个条目中。有关文件格式的文档,请参阅 清单定义
icon.png应用程序在应用商店中使用的图标。也可以将其用作设备启动器菜单中的应用程序图标:请参阅 info.yaml。打包工具需要确保此文件位于归档的前 10 个条目中。
--PACKAGE-FOOTER--一个或多个 YAML 文档,需要是包中的最后一个文件(例如,如果添加多个页脚,例如由应用商店服务器附加存储签名),可以将任意字符串附加到文件名中(例如 --PACKAGE-FOOTER--storesig)。这样可以更容易地调试包,因为您可以使用标准的 tar 命令行工具轻松提取它们。

简而言之,以下是包内不允许的内容

  • 不允许使用以 --PACKAGE- 开头的文件名
  • 不允许使用绝对路径
  • 不允许在相对路径中使用 ../
  • 不允许有符号链接、硬链接、设备文件、套接字等。
  • 除了所有者的 x 位之外的模式将被忽略。

校验和算法

所有包数据以及重要的元数据都受 SHA256 摘要的保护。此摘要有两个用途:它防止传输错误,并使用对此摘要的加密来进行包签名。

此摘要的实际计算如下

  • 对于每个不是 --PACKAGE-* 元数据文件的文件,将完整内容添加到摘要中。之后,还向摘要中添加以下 UTF-8 编码的字符串:"F/<文件大小(字节)>/<文件路径>"(例如,大小为 250 字节的文件 foo/test.qml 将生成 F/250/foo/test.qml
  • 对于每个目录,将以下 UTF-8 编码的字符串添加到摘要中:"D/0/<目录路径>"(例如,目录 foo/images 将生成 D/0/foo/images

将生成的摘要放入 --PACKAGE-FOOTER-- 中,作为 32 字节的十六进制编码字符串。

签名算法

当前支持的包格式有两种签名方式:一种是由开发者在上传到应用商店服务器之前生成的开发者签名;另一种是在客户端实际下载包之前由应用商店服务器生成的商店签名。

两种签名方式计算方式相同,并且以相同的方式附加到包的元数据中:使用二进制摘要作为输入创建分离的PKCS7签名。然后将这个PKCS7签名BASE64编码并存储在--PACKAGE-FOOTER-- 中——在 developerSignaturestoreSignature 字段中。

如果您想自己实现这个签名算法,请查看以下四种现有实现:

  • src/crypto-lib/signature_openssl.cpp 中的基于C++ OpenSSL的实现
  • src/crypto-lib/signature_win.cpp 中的基于C++ WinCrypt的实现(仅限Windows)
  • src/crypto-lib/signature_macos.cpp 中的基于C++ SecurityFramework的实现(仅限macOS)
  • 基于appstore-server参考实现的Python m2crypt

--PACKAGE-FOOTER----PACKAGE-HEADER-- 文件头部(第一个YAML文档)的字段如下

字段名称类型描述
formatVersionint必需。目前总是 2
formatTypestring必需。对于头部始终为 am-package-header,对于尾部始终为 am-package-footer

--PACKAGE-FOOTER----PACKAGE-HEADER-- 数据(第二个YAML文档)的字段如下

字段名称类型描述
idstring包的唯一ID。这必须与描述包的附带的 info.yaml 清单文件中的ID匹配。
iconstring必需。图标文件的名称。该文件必须位于与 info.yaml 相同的目录中,并且可以是Qt支持的任何图像格式。

注意:旧格式(5.14之前)将 formatVersion 头部字段设置为 1,并使用 applicationId 字段而不是 packageId

示例包

这是最小QML应用程序包的一个示例。实际的包可以通过将所有这些文件打包(使用 tar)创建:

tar cvzf qmlapp.appkg ./--PACKAGE-HEADER-- info.yaml icon.png main.qml ./--PACKAGE-FOOTER--
文件内容
--PACKAGE-HEADER--
%YAML 1.1
---
formatType: am-package-header
formatVersion: 2
---
packageId: com.pelagicore.minimal
diskSpaceUsed: 1000
info.yaml
%YAML 1.1
---
formatType: am-package
formatVersion: 1
---
id: 'com.pelagicore.minimal'
icon: 'icon.png'
name:
  en: 'Minimal App'
applications:
- id: com.pelagicore.minimalapp
  code: 'main.qml'
  runtime: 'qml'
icon.png标准png图像
main.qml您的QML应用程序
--PACKAGE-FOOTER--
%YAML 1.1
---
formatType: am-package-footer
formatVersion: 2
---
# SHA256 digest in 32 char hex representation
digest: '9df5635bb50e93846954c6377468c07835119e2835475ec90b3e9a9f7261cf27'

©2019 Luxoft瑞典AB。包括在内的文档贡献的版权属于其各自的所有者。本提供的文档是根据<.alibaba "http://www.gnu.org/licenses/fdl.html" >GNU自由文档许可版本1.3授权使用,由自由软件基金会发布。Qt和相应的标志是芬兰及其它国家/地区的Qt公司的商标。所有其他商标均为其各自所有者的财产。