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 解析器实现
1,357,729 每月下载量
用于 1,058 个 crate (24 直接)
210KB
2.5K SLoC
BER/DER 解析器
使用 nom 解析器组合框架实现的 Basic Encoding Rules (BER [X.690]) 和 Distinguished Encoding Rules(DER [X.690]) 解析器。
它完全用 Rust 编写,速度快,并且大量使用零拷贝。在设计(递归限制、防御性编程)、测试和模糊测试等方面都十分注重确保此库的安全性。它还旨在无 panic。
历史上,此解析器最初仅用于 DER,后来添加了对 BER 的支持。这可能在某些命名方案中有所体现,但不会产生其他影响:此库中使用的 BerObject
和 DerObject
是类型别名,因此所有函数都是兼容的。
然而,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_ber
和 parse_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);
第二种(也是首选)解析方法是指定预期的对象进行递归。以下函数可以使用:
parse_ber_sequence_defined
和类似的序列和集合变体函数parse_ber_tagged_explicit
用于标记显式parse_ber_tagged_implicit
用于标记隐式parse_ber_container
用于通用解析等。- DER 对象使用
_der_
变体
例如,要读取包含两个整数的 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
,因此可以使用常规函数(如 map
、unwrap
等)。
注意事项
BER/DER 整数
DER 整数可以是任何大小,因此无法将它们作为简单的整数存储(它们以原始字节的形式存储)。
请注意,默认情况下,BER/DER 整数是带符号的。提供函数来请求读取无符号值,但如果整数值为负,它们将失败。
要获取所有可能的整数符号和大小对应的整数值,请使用 BerObject::as_bigint
(需要 bigint
功能)。
要获取预期在已知范围内的简单值,请使用类似 BerObject::as_i32
和 BerObject::as_i64
(或无符号版本 BerObject::as_u32
和 BerObject::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约束。 BerObject
和DerObject
是相同的对象(类型别名)。唯一的区别是在解析过程中验证约束。
Rust版本要求
基于asn1-rs
和nom
7依赖项,der-parser
的7.0系列需要Rustc版本1.53或更高版本。
序列化
目前正在测试对BER/DER对象的编码支持,可以通过启用serialize
功能来使用。请注意,当前状态是实验性的。
请参阅ber
模块中的ber_encode_*
函数,以及BerObject::to_vec
参考
基本编码规则(BER)、规范编码规则(CER)和专用编码规则(DER)。
更改
有关升级主要版本的说明,请参阅CHANGELOG.md
和UPGRADING.md
。
许可
根据您的选择,许可方式如下:
- Apache License,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义的您提交给工作的工作的所有有意贡献,将根据上述条款双许可,不附加任何其他条款或条件。
依赖关系
~1.6–2.4MB
~49K SLoC