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_KEY0CONFIG_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 的文件位置。 生成的私钥应妥善保存,并在需要解密日志文件时使用。