日志加密
PX4 v1.13系统日志记录器 可用于创建加密日志,这些日志在分析之前可以手动解密。
默认的加密算法是 XChaCha20,默认的封装算法是 RSA2048-OAEP。
WARNING
在 PX4 固件版本中,日志加密默认是未启用的。 若要使用该功能,你需要构建启用了此功能的固件,然后将其上传到飞行控制器上(请参阅以下说明)。
TIP
在 PX4 主版本(v1.16+)中,日志加密功能已得到改进,生成的单个加密日志文件中既包含加密的日志数据,也包含可用于解密的加密对称密钥(前提是你能够解密该对称密钥)。
在早期版本中,加密的对称密钥存储在一个单独的文件中。 更多信息请参阅 日志加密(PX4 v1.15)。
ULog 加密的工作原理
INFO
所使用的加密算法在 SDLOG_ALGORITHM 中设置。 在撰写本文时,仅支持 XChaCha20
算法(可以选择 AES,但尚未实现)。
如果将来支持其他算法,其过程很可能与本文档中记录的相同。
每个新 ULog 的加密过程如下:
- 生成一个 XChaCha20 对称密钥,并使用 RSA2048 公钥对其进行加密。 这个经过封装(加密)的密钥会存储在 SD 卡上,位于一个后缀为
.ulge
(“ulog encrypted”,即加密的 ULog)的文件开头。 - 捕获日志时,ULog 数据会使用解封装后的对称密钥进行加密,加密后的数据会立即追加到
.ulge
文件的末尾,紧跟在封装后的密钥数据之后。
飞行结束后,可以在 SD 卡上找到包含封装后的对称密钥和加密日志数据的 .ulge
文件。
为了解析日志文件,用户必须首先解密封装后的对称密钥,然后才能使用该密钥来解密日志。 只有当用户拥有用于封装该对称密钥的公钥所对应的 RSA 私钥时,才能解密封装后的对称密钥文件。
下面的 下载和解密日志文件 部分将更详细地介绍这个过程。
文件结构
加密的 .ulge
文件包含以下部分:
-------------------------
| 头部 |
-------------------------
| 封装后的对称密钥 |
-------------------------
| 加密的 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
文件。 该文件中的相关密钥如下:
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 公钥和私钥)。
使用以下命令构建固件:
make px4-fmu-v5_cryptotest
其他飞控板
对于其他板卡,你首先需要将 cryptotest.px4board
文件复制到目标板卡目录的根目录下。 例如,对于 FMUv6 板卡,你需要将该文件复制到 /boards/px4/fmu-v6x 目录中。
然后,你需要添加一些在 FMUv5 默认配置中存在但在其他板卡中不存在的配置设置。 我们使用 menuconfig
工具来添加这些设置。
要使用 menuconfig
,你需要添加以下依赖项:
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
为例,因为它已经包含了我们想要复制的设置:
make px4_fmu-v5_cryptotest menuconfig
导航到 Crypto API
,并使用 Y 键选择它。
这将打开以下菜单。 启用以下设置:Blake2s 哈希算法
、熵池和强随机数生成器
以及 使用中断将定时随机性输入到熵池中
。
TIP
如果需要,其中一些选项可以进行调整。
启用加密设置后,退出 menuconfig
。 现在你可以进行构建和测试了。
下载和解密日志文件
加密日志文件可以使用 QGroundControl 的 日志下载 视图(分析工具 > 日志下载)进行下载,就像下载普通日志文件一样。
请注意,加密文件将以 .ulg
后缀下载,而不是 .ulge
。
解密 ULogs
在分析加密日志之前,你需要先对其进行解密。 在 Tools/decrypt_ulog.py
中有一个 Python 脚本可用于解密日志。
解密 .ulge
文件时,该脚本需要 3 个参数:
- 加密的日志文件。
- 一个空字符串
''
。 - 解密密钥(用于解封装对称密钥的 RSA2048
.pem
私钥)。
例如:
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
文件。 完整的命令行语法如下:
用法: 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:
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
然后,可以从这个私钥创建一个公钥:
# 将 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
的文件位置。 生成的私钥应妥善保存,并在需要解密日志文件时使用。