5 个版本 (破坏性更新)
0.5.0 | 2021年9月6日 |
---|---|
0.4.0 | 2021年3月25日 |
0.3.0 | 2020年11月2日 |
0.2.0 | 2020年7月8日 |
0.1.0 | 2020年2月18日 |
在 过程宏 中排名第1852
每月下载量 27,293
5KB
79 代码行
BER/DER解析器
一个用于基本编码规则(BER [X.690]) 和区分编码规则(DER [X.690]) 的解析器,使用nom解析器组合框架实现。
它完全用Rust编写,速度快,并广泛使用零拷贝。为了确保此crate的安全性,投入了大量精力,包括设计(递归限制、防御性编程)、测试和模糊测试。它还旨在无panic。
历史上,此解析器最初旨在仅用于DER,后来添加了对BER的支持。这可能会在一些命名方案中反映出来,但不会有其他后果:在此crate中使用的 BerObject
和 DerObject
是类型别名,因此所有函数都是兼容的。
DER解析函数还有额外的约束验证。
还添加了序列化(见序列化 )
代码在Github上可用,并是Rusticata项目的一部分。
BER/DER解析器
BER代表基本编码规则,由X.690定义。它定义了一组规则来对二进制中的ASN.1对象进行编码和解码。
X.690还定义了区分编码规则(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");
解析DER整数序列
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 版本要求
der-parser
的 9.0 系列要求 Rustc 版本 1.63 或更高,基于 asn1-rs
和 nom
7 依赖项。
序列化
目前正在测试对 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 许可证的定义,都应按照上述方式双重许可,不附加任何额外条款或条件。
依赖项
~2MB
~45K SLoC