Skip to content

日志加密 ​

PX4 v1.13

系统日志记录器 可用于创建加密日志,这些日志在分析之前可以手动解密。

默认的加密算法是 XChaCha20,默认的封装算法是 RSA2048-OAEP。

WARNING

在 PX4 固件版本中,日志加密默认是未启用的。 若要使用该功能,你需要构建启用了此功能的固件,然后将其上传到飞行控制器上(请参阅以下说明)。

TIP

在 PX4 主版本(v1.16+)中,日志加密功能已得到改进,生成的单个加密日志文件中既包含加密的日志数据,也包含可用于解密的加密对称密钥(前提是你能够解密该对称密钥)。

在早期版本中,加密的对称密钥存储在一个单独的文件中。 更多信息请参阅 日志加密(PX4 v1.15)。

ULog 加密的工作原理 ​

INFO

所使用的加密算法在 SDLOG_ALGORITHM 中设置。 在撰写本文时,仅支持 XChaCha20 算法(可以选择 AES,但尚未实现)。

如果将来支持其他算法,其过程很可能与本文档中记录的相同。

每个新 ULog 的加密过程如下:

  1. 生成一个 XChaCha20 对称密钥,并使用 RSA2048 公钥对其进行加密。 这个经过封装(加密)的密钥会存储在 SD 卡上,位于一个后缀为 .ulge(“ulog encrypted”,即加密的 ULog)的文件开头。
  2. 捕获日志时,ULog 数据会使用解封装后的对称密钥进行加密,加密后的数据会立即追加到 .ulge 文件的末尾,紧跟在封装后的密钥数据之后。

飞行结束后,可以在 SD 卡上找到包含封装后的对称密钥和加密日志数据的 .ulge 文件。

为了解析日志文件,用户必须首先解密封装后的对称密钥,然后才能使用该密钥来解密日志。 只有当用户拥有用于封装该对称密钥的公钥所对应的 RSA 私钥时,才能解密封装后的对称密钥文件。

下面的 下载和解密日志文件 部分将更详细地介绍这个过程。

文件结构 ​

加密的 .ulge 文件包含以下部分:

plain
-------------------------
| 头部                  |
-------------------------
| 封装后的对称密钥       |
-------------------------
| 加密的 ULog 数据       |
-------------------------

头部部分(22 字节)包含以下字段:

字节范围字段名称
0 到 6 字节文件魔法标识符
第 7 字节头部版本
8 到 15 字节时间戳
第 16 字节交换算法
第 17 字节交换密钥索引
18 到 19 字节密钥大小
20 到 21 字节随机数大小

头部部分以魔法字符串 "ULogEnc" 开头,用于标识这是一个加密的 ULog 文件。 对称密钥部分的文件偏移量为 22,日志数据部分的文件偏移量为 22 + 密钥大小 + 随机数大小(密钥大小 和 随机数大小 取自头部部分)。

支持日志加密的自定义 PX4 固件 ​

你需要构建包含自己的 RSA 公钥以及支持日志加密所需的加密 API 模块的自定义固件。 本节以 px4-fmu-v5 板为例,展示如何进行操作。

TIP

我们将在下面的 生成 RSA 公钥和私钥 部分中介绍如何生成自己的密钥。

INFO

PX4 构建中的模块是在配置文件中定义的,这些文件可以手动修改,也可以使用 menuconfig 工具进行修改。 更多信息请参阅:PX4 板卡配置(Kconfig)。

加密测试 Make 目标 ​

加密功能会占用大量的闪存空间,因此默认情况下,它并未包含在每个板卡的 PX4 make 目标中(例如 make px4-fmu-v5)。 添加对加密日志支持的最简单方法是定义一个自定义的 make 目标,该目标包含所需的模块以及你的 RSA 公钥。

WARNING

许多构建版本已接近其最大容量。 如果你遇到构建错误,提示已超出最大闪存容量,则需要在正在处理的 .px4board 文件或 default.px4board 文件中禁用其他功能。 请注意不要禁用你需要的功能。

例如,如果你发现 FMUv4 板卡上的内存不足,可以通过在 boards/px4/fmu-v4/default.px4board 中设置 CONFIG_MODULES_SIMULATION_SIMULATOR_SIH=n 来禁用 SIH 模式,这可能会释放足够的闪存空间以添加加密功能。

Pixhawk FMUv5 板卡 ​

FMUv5 板卡已经有一个自定义的 make 目标 px4-fmu-v5_cryptotest,你可以使用它来构建包含所需模块和 “测试” RSA 密钥的自定义固件。 启用上述 make 目标的配置文件是 boards/px4/fmu-v5 目录下的 cryptotest.px4board 文件。 该文件中的相关密钥如下:

plain
CONFIG_BOARD_CRYPTO=y
CONFIG_DRIVERS_STUB_KEYSTORE=y
CONFIG_DRIVERS_SW_CRYPTO=y
CONFIG_PUBLIC_KEY1="../../../Tools/test_keys/rsa2048.pub"

INFO

该文件还将 CONFIG_PUBLIC_KEY0 设置为名为 key0.pub 的密钥。 在当前的 PX4 实现中未使用该密钥,可以忽略。

Details

加密相关密钥概述

参数名称描述
CONFIG_BOARD_CRYPTO在固件中包含加密模块。
= y:启用日志加密。
= n:禁用日志加密。
CONFIG_DRIVERS_SW_CRYPTO包含 PX4 加密后端库(由上述库使用)。
= y:启用
= n:禁用
CONFIG_DRIVERS_STUB_KEYSTORE包含 PX4 存根密钥存储驱动程序。
= y:启用
= n:禁用
CONFIG_PUBLIC_KEY0密钥存储索引 0 的公钥位置。
CONFIG_PUBLIC_KEY1密钥存储索引 1 的公钥位置。
= {密钥 1 的路径}
CONFIG_PUBLIC_KEY2密钥存储索引 2 的公钥位置。
= {密钥 2 的路径}
CONFIG_PUBLIC_KEY3密钥存储索引 3 的公钥位置。
= {密钥 3 的路径}

存根密钥存储是一种密钥存储实现,最多可以存储四个密钥。 这些密钥的初始值在由 CONFIG_PUBLIC_KEY0 到 CONFIG_PUBLIC_KEY3 定义的位置设置。 这些密钥可用于不同的加密目的,具体由参数决定。

用于加密存储在 .ulge 文件开头的对称密钥的公钥(即 “交换密钥”),是通过 SDLOG_EXCH_KEY 作为密钥存储的索引值来指定的。 默认值为 1,它映射到 CONFIG_PUBLIC_KEY1 中定义的密钥。

“日志记录密钥” 是未加密的对称密钥。 这是通过 SDLOG_KEY 作为密钥存储的索引值来指定的,默认值为 2。 请注意,每个日志都会生成新的对称密钥,CONFIG_PUBLIC_KEY2 中指定的任何值都会被覆盖。

只要你的密钥不被其他任何东西使用,你可以为它们选择不同的存储位置。

CONFIG_PUBLIC_KEY1 中的密钥是用于在 .ulge 文件开头封装对称密钥的公钥(默认情况下:请参阅 SDLOG_EXCH_KEY)。 你可以使用 rsa2048.pub 密钥进行测试,或者将其替换为你自己的公钥文件路径(请参阅 生成 RSA 公钥和私钥)。

使用以下命令构建固件:

sh
make px4-fmu-v5_cryptotest

其他飞控板 ​

对于其他板卡,你首先需要将 cryptotest.px4board 文件复制到目标板卡目录的根目录下。 例如,对于 FMUv6 板卡,你需要将该文件复制到 /boards/px4/fmu-v6x 目录中。

然后,你需要添加一些在 FMUv5 默认配置中存在但在其他板卡中不存在的配置设置。 我们使用 menuconfig 工具来添加这些设置。

要使用 menuconfig,你需要添加以下依赖项:

sh
sudo apt-get install libncurses-dev flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf

现在,在 PX4 中,运行用于构建目标板卡的常规 make 命令,但在命令末尾添加 “menuconfig”。 这里我们以 px4_fmu-v5_cryptotest 为例,因为它已经包含了我们想要复制的设置:

sh
make px4_fmu-v5_cryptotest menuconfig

导航到 Crypto API,并使用 Y 键选择它。

Menuconfig Crypto API 主菜单选项

这将打开以下菜单。 启用以下设置:Blake2s 哈希算法、熵池和强随机数生成器 以及 使用中断将定时随机性输入到熵池中。

Menuconfig 加密选项设置

TIP

如果需要,其中一些选项可以进行调整。

启用加密设置后,退出 menuconfig。 现在你可以进行构建和测试了。

下载和解密日志文件 ​

加密日志文件可以使用 QGroundControl 的 日志下载 视图(分析工具 > 日志下载)进行下载,就像下载普通日志文件一样。

请注意,加密文件将以 .ulg 后缀下载,而不是 .ulge。

解密 ULogs ​

在分析加密日志之前,你需要先对其进行解密。 在 Tools/decrypt_ulog.py 中有一个 Python 脚本可用于解密日志。

解密 .ulge 文件时,该脚本需要 3 个参数:

  1. 加密的日志文件。
  2. 一个空字符串 ''。
  3. 解密密钥(用于解封装对称密钥的 RSA2048 .pem 私钥)。

例如:

sh
python3 decrypt_ulog.py \
/home/john/Downloads/log_24_2024-10-6-23-39-50.ulg '' \
new_keys/private_key.pem

解密成功后,将创建一个后缀为 .ulog 的解密日志文件。

INFO

该脚本可用于 .ulge 日志文件,以及 PX4 v1.15 日志加密 中使用的 .ulgc/.ulgk 文件。 完整的命令行语法如下:

sh
用法: decrypt_ulog.py [-h] [ulog_file] [ulog_key] [rsa_key]

CLI 工具,用于解密 ULog 文件

位置参数:
  ulog_file   .ulge/.ulgc,加密的日志文件
  ulog_key    .ulgk,旧版加密密钥(对于 .ulge 文件,若忽略该参数请输入空字符串 '')
  rsa_key     .pem 格式的密钥,用于解密 ulog 密钥

可选参数:
  -h, --help  显示此帮助消息并退出

生成 RSA 公钥和私钥 ​

要生成 RSA2048 私钥和公钥,可以使用 OpenSSL:

sh
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048

然后,可以从这个私钥创建一个公钥:

sh
# 将 private_key.pem 转换为 DER 文件
openssl rsa -pubout -in private_key.pem -outform DER -out public_key.der
# 从 DER 文件生成十六进制格式的公钥,并用逗号分隔
xxd -p public_key.der | tr -d '\n' | sed 's/\(..\)/0x\1, /g' > public_key.pub

要使用这个密钥,你需要修改 .px4board 文件,将 CONFIG_PUBLIC_KEY1 指向 public_key.pub 的文件位置。 生成的私钥应妥善保存,并在需要解密日志文件时使用。