ITADN
ANSSI-FR/MLA · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Build & test Cargo MLA Documentation MLA Cargo MLAR PyPI - Version

多层归档 (MLA)

ANSSI logo

法国网络安全局 (ANSSI)

badge_repo category_badge_internal openess_badge_B

本项目由 ANSSI 管理。如需了解更多信息,您可以访问专门介绍 ANSSI 开源战略的 页面(法语)。您还可以点击上方的徽章以了解其含义。

简介

MLA 是一种具有以下特性的归档文件格式:

  • 支持非对称密钥的传统与后量子加密混合(基于 X25519 与后量子 ML-KEM 1024 混合的 KEM,以及 AES256-GCM 的 HPKE)
  • 支持传统与后量子签名混合
  • 支持压缩(基于 rust-brotli)
  • 可流式创建归档:
    • 即使通过数据二极管也可以构建归档
    • 可以通过数据块添加条目,而无需预先知道最终大小
    • 条目块可以交错(可以先添加一个条目的开头,开始第二个条目,然后继续添加第一个条目的部分)
  • 架构无关且在一定程度上可移植(完全使用 Rust 编写)
  • 归档读取支持随机访问,即使经过压缩或加密。可以在归档中间访问某个条目,而无需从头开始读取
  • 如果归档被截断,可以在一定程度上恢复。提供两种模式:
    • 认证恢复(默认):仅检索经过认证(如同 AEAD,没有签名验证)的加密数据块
    • 非认证恢复:检索经过认证和未经认证的加密数据块。使用风险自负。
  • 可以说更不容易出现 bug,尤其是在解析不受信任的归档时(Rust 安全性)

仓库

本仓库包含:

  • mla: 实现 MLA 读取器和写入器的 Rust 库
  • mlar: 封装 mla 以执行常见操作(创建、列出、提取等)的 Rust CLI 工具
  • doc : 与 MLA 相关的文档(例如格式规范、加密)
  • bindings : 其他语言的绑定
  • samples : 测试资源
  • mla-fuzz: 用于模糊测试代码的 Rust crate
  • mla-fuzz-afl : 使用 AFL 对 mla 进行模糊测试的 Rust 工具
  • fuzz : OSS-Fuzz 目标和配置
  • .github: 持续集成需求

快速命令行用法

以下是一些使用 mlar 处理 MLA 格式归档的命令。

# Generate MLA key pairs.
mlar keygen sender
mlar keygen receiver

# Create an archive with some files.
mlar create -k sender.mlapriv -p receiver.mlapub -o my_archive.mla /boot/./grub/locale/en@quot.mo /etc/security/../issue ../file.txt

# List the content of the archive.
# Note that order may vary, root dir are stripped,
# paths are normalized and listing is encoded as described in
# `doc/src/ENTRY_NAME.md` (hence the percent in output).
# This outputs:
# ``
# etc/issue
# boot/grub/locale/en%40quot.mo
# file.txt
# ``
mlar list -k receiver.mlapriv -p sender.mlapub -i my_archive.mla

# Extract the content of the archive into a new directory.
# In this example, this creates two files:
# extracted_content/etc/issue and extracted_content/etc/os-release
mlar extract -k receiver.mlapriv -p sender.mlapub -i my_archive.mla -o extracted_content

# Display the content of a file in the archive
mlar cat -k receiver.mlapriv -p sender.mlapub -i my_archive.mla etc/os-release

# Convert the archive into a long-term format, primarily for archival purposes.
# Below operation also removes encryption and applies
# the highest (but slowest) compression level.
mlar convert -k receiver.mlapriv -p sender.mlapub -i my_archive.mla -o longterm.mla --unencrypted --unsigned -q 11

# Create an archive with multiple recipients and without signature nor compression
mlar create --unsigned --uncompressed -p archive.mlapub -p client1.mlapub -o my_archive.mla ...

# List an archive containing an entry with a name that cannot be interpreted as path.
# This outputs:
# `c%3a%2f%00%3b%e2%80%ae%0ac%0dd%1b%5b1%3b31ma%3cscript%3eevil%5c..%2f%d8%01%c2%85%e2%88%95`
# corresponding to an entry name containing: ASCII chars, c:, /, .., \,
# NUL, RTLO, newline, terminal escape sequence, carriage return,
# HTML, surrogate code unit, U+0085 weird newline, fake unicode slash.
# Please note that some of these characters may appear in a valid path.
mlar list -k samples/test_mlakey_archive_v2_receiver.mlapriv -p samples/test_mlakey_archive_v2_sender.mlapub -i samples/archive_weird.mla --raw-escaped-names

# Get its content.
# This displays:
# `' OR 1=1`
mlar cat -k samples/test_mlakey_archive_v2_receiver.mlapriv -p samples/test_mlakey_archive_v2_sender.mlapub -i samples/archive_weird.mla --raw-escaped-names c%3a%2f%00%3b%e2%80%ae%0ac%0dd%1b%5b1%3b31ma%3cscript%3eevil%5c..%2f%d8%01%c2%85%e2%88%95

# Create an archive of a web file, without encryption and without signature
curl https://raw.githubusercontent.com/ANSSI-FR/MLA/refs/heads/main/LICENSE.md | mlar create --unencrypted --unsigned -o my_archive.mla --stdin-data

# Create an archive of a web file and arbitrary byte string, without encryption and without signature (chosen separator should not be present in the two entries)
(curl https://raw.githubusercontent.com/ANSSI-FR/MLA/refs/heads/main/LICENSE.md; echo "SEPARATOR"; echo -n "All Hail MLA") | mlar create --unencrypted --unsigned -o my_archive.mla --stdin-data --stdin-data-separator "SEPARATOR" --stdin-data-entry-names great_license.md,hello.txt

# Create an archive passing the file list on stdin (not data)
echo -n -e "/etc/issue\n/etc/os-release" | mlar create -unencrypted --unsigned -o my_archive.mla --stdin-file-list

mlar 可通过以下方式获取:

为了获得更高的性能,您可以构建一个原生优化的二进制文件(不可移植),例如在 Linux 机器上:

RUSTFLAGS="-Ctarget-cpu=native" cargo build --release --target x86_64-unknown-linux-musl

注意:原生构建针对你机器的 CPU 进行了优化,不具备可移植性。仅在运行于构建所用的同一台机器上时使用它们。

API 用法

参见 https://docs.rs/mla

在其他语言中使用 MLA

提供以下语言的绑定:

安全性

在使用之前,你应该阅读 API 文档mlar --help。它们有时会提供重要的安全警告。doc/src/ENTRY_NAME.md 对于理解条目命名约定和安全影响也是必不可少的。

潜在问题

  • 由于符号链接攻击,通常不建议将归档解压到至少有一个祖先目录可被其他用户写入的目录中(例如 /tmp 或其他共享目录)。
    • 除了符号链接攻击外,mlar 不会在指定的输出目录之外进行解压。
  • 即使使用经过认证的密码进行加密,未签名的归档也不会验证其作者。任何拥有你公钥的人都可以创建这样的归档,因此其中可能包含任意(潜在恶意的)数据。
  • mlar 在输出时会对条目名称进行转义,以避免安全问题。

保证与限制

  • MLA 不提供任何针对侧信道攻击的保证。但是,如果您在此方面发现问题,请联系我们,我们将评估是否对其进行修复。
  • MLA Python 绑定的安全性和维护级别明确不予保证。
  • 已对 MLA 2.0.0-beta 进行了安全评估,记录了自那以后本应已修复的低严重性问题(参见 issue #465)。报告可在 doc/20260130-mla-security-assessment.pdf 中获取。

FAQ

MLAArchiveWriter Send

默认情况下,MLAArchiveWriter 不是 Send。如果内部可写类型也是 Send,则可以在 Cargo.toml 中为 mla 启用功能 send,例如:

[dependencies]
mla = { version = "...", default-features = false, features = ["send"]}

是否真的需要一种新格式?

由于现有的归档格式众多,可能并不需要。

但据作者所知,它们都不支持上述 特性(当然,它们更适合其他用途)。

例如(基于作者的理解):

  • tar 格式在添加文件之前需要知道文件大小,并且 不可寻址
  • zip 格式如果移除页脚,可能会丢失关于文件的信息
  • 7zip 格式在向其添加文件时需要重建整个归档 (不可流式处理)。它也相当复杂,因此在解包未知归档时更难审计/信任
  • journald 格式不可流式处理。此外,这里不需要单写者/多读者,因此释放了 journald 格式所具有的一些约束
  • 任何归档 + ageage 截至 MLA 2.0 发布,不支持后量子加密或签名。
  • 备份格式通常旨在避免诸如重复之类的问题, 因此它们需要在内存中保留更大的结构,或者不可 流式处理

调整这些格式很可能导致类似的特性。 选择保留对格式能力的更好控制,并(尝试)保持简单。

性能

可以通过基于 Criterion 的嵌入式基准测试来评估性能。

已嵌入多种场景,例如:

  • 文件添加,具有不同的大小和层配置
  • 文件添加,调整压缩质量
  • 文件读取,具有不同的大小和层配置
  • 随机文件读取,具有不同的大小和层配置
  • 线性归档提取,具有不同的大小和层配置

在 "Intel(R) Core(TM) i7-1255U CPU @ 2.60GHz" 上:

$ cargo bench
...
multiple_layers_multiple_block_size/compression: true, encryption: true, signature: true/1048576
                        time:   [7.0850 ms 7.1179 ms 7.1586 ms]
                        thrpt:  [139.69 MiB/s 140.49 MiB/s 141.14 MiB/s]
...
chunk_size_decompress_multifiles_random/compression: true, encryption: true, signature: true/1048576
                        time:   [11.285 ms 11.494 ms 11.663 ms]
                        thrpt:  [85.745 MiB/s 87.005 MiB/s 88.616 MiB/s]
...
reader_multiple_layers_multiple_block_size_multifiles_linear/compression: true, encryption: true, signature: true/1048576
                        time:   [4.6197 ms 4.6383 ms 4.6604 ms]
                        thrpt:  [214.58 MiB/s 215.60 MiB/s 216.47 MiB/s]
...

Criterion.rs 文档说明了如何获取 HTML 报告、比较结果等。

AES-NI 支持

aes crate 文档 所述,该 crate 在 i686x86_64 目标上使用运行时检测来检查 AES-NI 是否可用。如果未检测到 AES-NI,它将自动回退到恒定时间软件实现。

贡献

感谢您的帮助!若要贡献,请阅读我们的贡献指南