56 个版本 (29 个稳定版)

9.0.0 2024年2月23日
8.2.0 2023年3月7日
8.1.0 2022年5月24日
7.0.0 2022年2月10日
0.3.3 2017年3月27日

#38 in 解析器实现

Download history 225435/week @ 2024-04-27 209936/week @ 2024-05-04 243832/week @ 2024-05-11 255830/week @ 2024-05-18 256044/week @ 2024-05-25 279642/week @ 2024-06-01 255750/week @ 2024-06-08 250614/week @ 2024-06-15 278357/week @ 2024-06-22 249200/week @ 2024-06-29 288526/week @ 2024-07-06 313042/week @ 2024-07-13 336815/week @ 2024-07-20 319384/week @ 2024-07-27 334235/week @ 2024-08-03 312792/week @ 2024-08-10

1,357,729 每月下载量
用于 1,058 个 crate (24 直接)

MIT/Apache

210KB
2.5K SLoC

License: MIT Apache License 2.0 docs.rs crates.io Download numbers dependency status Github CI Minimum rustc version

BER/DER 解析器

使用 nom 解析器组合框架实现的 Basic Encoding Rules (BER [X.690]) 和 Distinguished Encoding Rules(DER [X.690]) 解析器。

它完全用 Rust 编写,速度快,并且大量使用零拷贝。在设计(递归限制、防御性编程)、测试和模糊测试等方面都十分注重确保此库的安全性。它还旨在无 panic。

历史上,此解析器最初仅用于 DER,后来添加了对 BER 的支持。这可能在某些命名方案中有所体现,但不会产生其他影响:此库中使用的 BerObjectDerObject 是类型别名,因此所有函数都是兼容的。

然而,DER 解析函数具有额外的约束验证。

还添加了序列化(请参阅 序列化

代码可在 Github 上找到,并是 Rusticata 项目的组成部分。

BER/DER 解析器

BER 代表基本编码规则,在 X.690 中定义。它定义了一组规则,用于在二进制中对 ASN.1 对象进行编码和解码。

X.690 还定义了 distinguished encoding rules (DER),这是在 BER 的基础上添加了确保对象二进制表示法的规范性和明确性的规则。

选择使用哪一个通常由基于 BER 或 DER 的数据格式规范指导:例如,X.509 使用 DER 作为编码表示。

请参阅相关模块以获取对象定义、函数和示例

  • [ber]: 基本编码规则
  • [der]: 特殊编码规则

示例

解析两个 BER 整数(请参阅 BER/DER 整数

use der_parser::ber::parse_ber_integer;

let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
let (rem, obj2) = parse_ber_integer(&rem).expect("parsing failed");

解析整数序列

use der_parser::der::{parse_der_integer, parse_der_sequence_of};

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (rem, seq) = parse_der_sequence_of(parse_der_integer)(&bytes)
                    .expect("parsing failed");

注意:所有解析函数都返回剩余的(未解析的)字节和解析对象,或错误。

DER 解析器设计

解析函数受到了 nom 的启发,并遵循相同的接口。最常用的返回类型是 BerResult,它存储剩余的字节和解析后的 BerObject 或错误。阅读 nom 文档可能有助于理解如何编写解析器和使用输出。

解析 DER 对象有两种不同的方法:在知道标签的情况下递归地读取对象,或指定预期对象的描述(通常来自 ASN.1 描述)。

第一种解析方法可以使用 parse_berparse_der 方法来完成。当解码任意 DER 对象时很有用。然而,它不能完全解析所有对象,特别是包含 IMPLICIT、OPTIONAL 或 DEFINED BY 项的对象。

use der_parser::parse_der;

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let parsed = parse_der(&bytes);

第二种(也是首选)解析方法是指定预期的对象进行递归。以下函数可以使用:

例如,要读取包含两个整数的 BER 序列

use der_parser::ber::*;
use der_parser::error::BerResult;

fn localparse_seq(i:&[u8]) -> BerResult {
    parse_ber_sequence_defined(|data| {
        let (rem, a) = parse_ber_integer(data)?;
        let (rem, b) = parse_ber_integer(rem)?;
        Ok((rem, vec![a, b]))
    })(i)
}

let bytes = [ 0x30, 0x0a,
              0x02, 0x03, 0x01, 0x00, 0x01,
              0x02, 0x03, 0x01, 0x00, 0x00,
];

let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");

assert_eq!(parsed[0].as_u64(), Ok(65537));
assert_eq!(parsed[1].as_u64(), Ok(65536));

所有函数都返回一个 BerResult 对象:解析后的 BerObject、一个 Incomplete 值或一个错误。

请注意,此类型也是 Result,因此可以使用常规函数(如 mapunwrap 等)。

注意事项

BER/DER 整数

DER 整数可以是任何大小,因此无法将它们作为简单的整数存储(它们以原始字节的形式存储)。

请注意,默认情况下,BER/DER 整数是带符号的。提供函数来请求读取无符号值,但如果整数值为负,它们将失败。

要获取所有可能的整数符号和大小对应的整数值,请使用 BerObject::as_bigint(需要 bigint 功能)。

要获取预期在已知范围内的简单值,请使用类似 BerObject::as_i32BerObject::as_i64(或无符号版本 BerObject::as_u32BerObject::as_u64)的方法,它们将返回值,如果整数值过大(或为负)则返回错误。

use der_parser::ber::*;

let data = &[0x02, 0x03, 0x01, 0x00, 0x01];

let (_, object) = parse_ber_integer(data).expect("parsing failed");
assert_eq!(object.as_u64(), Ok(65537));

#[cfg(feature = "bigint")]
assert_eq!(object.as_bigint(), Ok(65537.into()))

可以使用as_slice方法访问原始值。

解析器、组合器、宏

一些解析工具(例如,用于标记对象)以不同的形式提供

  • 解析器:接受输入并创建对象的函数
  • 组合器:接受解析器(或组合器)作为输入的函数,并返回一个函数(通常是解析器)。它们用作构建块(组合)来创建更复杂的解析器。
  • 宏:这些通常是解析器的早期(历史)版本,保留以兼容性。它们有时可以减少编写代码的数量,但难以调试。尽可能优先使用解析器。

其他说明

  • 使用parse_der时,会验证DER约束。
  • BerObjectDerObject是相同的对象(类型别名)。唯一的区别是在解析过程中验证约束。

Rust版本要求

基于asn1-rsnom 7依赖项,der-parser的7.0系列需要Rustc版本1.53或更高版本。

序列化

目前正在测试对BER/DER对象的编码支持,可以通过启用serialize功能来使用。请注意,当前状态是实验性的

请参阅ber模块中的ber_encode_*函数,以及BerObject::to_vec

参考

  • [X.680] 抽象语法符号一(ASN.1):基本符号规范。
  • [X.690] ASN.1编码规则:基本编码规则(BER)、规范编码规则(CER)和专用编码规则(DER)的规范。

基本编码规则(BER)、规范编码规则(CER)和专用编码规则(DER)。

更改

有关升级主要版本的说明,请参阅CHANGELOG.mdUPGRADING.md

许可

根据您的选择,许可方式如下:

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的您提交给工作的工作的所有有意贡献,将根据上述条款双许可,不附加任何其他条款或条件。

依赖关系

~1.6–2.4MB
~49K SLoC