46个版本
0.17.0 | 2024年8月1日 |
---|---|
0.16.2 | 2024年6月2日 |
0.16.1 | 2024年3月4日 |
0.15.5 | 2023年8月9日 |
0.1.0 | 2015年7月21日 |
#99 在 解析器实现
215,317 每月下载量
用于 4 crates
185KB
4.5K SLoC
rust-asn1
这是一个用于解析和生成ASN.1数据(仅DER)的Rust库。
安装
将asn1
添加到您的[dependencies]
部分中的Cargo.toml
[dependencies]
asn1 = "0.17"
基于Rust 1.59.0及更高版本构建。
rust-asn1
与#![no_std]
环境兼容
asn1 = { version = "0.17", default-features = false }
lib.rs
:
这个crate为您提供了生成和解析ASN.1编码数据的能力。更准确地说,它为您提供了生成和解析使用ASN.1的DER(区分编码规则)编码的数据的能力。它不支持BER(基本编码规则)、CER(规范编码规则)、XER(XML编码规则)、CXER(规范XML编码规则)或其他任何字母汤编码——并且永远也不会。
如果您想解析如下所示的ASN.1结构
Signature ::= SEQUENCE {
r INTEGER,
s INTEGER
}
那么您将编写以下代码
let result: asn1::ParseResult<_> = asn1::parse(data, |d| {
return d.read_element::<asn1::Sequence>()?.parse(|d| {
let r = d.read_element::<u64>()?;
let s = d.read_element::<u64>()?;
return Ok((r, s));
})
});
通常,所有关于解析的内容都是由向Parser.read_element
提供不同的类型参数驱动的。一些类型直接在基本类型上实现了Asn1Readable
trait,如u64
或&[u8]
(OCTET STRING
),而其他类型使用包装类型,这些类型只是为其他类型提供ASN.1编码和解码(如PrintableString
或UtcTime
)。还有如Implicit
和Explicit
这样的类型用于处理标记值,以及用于选择的Choice1
、Choice2
和Choice3
,以及用于处理OPTIONAL
值的Option<T>
。
要序列化DER的Sequence
结构,你需要编写以下内容:
let result = asn1::write(|w| {
w.write_element(&asn1::SequenceWriter::new(&|w| {
w.write_element(&r)?;
w.write_element(&s)?;
Ok(())
}))
});
派生
当使用derive
特性构建时(默认启用),这些也可以表示为Rust结构体
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct Signature {
r: u64,
s: u64,
}
let sig = asn1::parse_single::<Signature>(data);
let result = asn1::write_single(&Signature{r, s});
字段可以标记为EXPLICIT
或IMPLICIT
,通过结构体成员具有类型Explicit
和Implicit
,或者通过使用#[explicit]
和#[implicit]
注解来实现
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct SomeSequence<'a> {
#[implicit(0)]
a: Option<&'a [u8]>,
#[explicit(1)]
b: Option<u64>,
}
字段也可以使用#[default(VALUE)]
注解来表示ASN.1的OPTIONAL DEFAULT
值。在这种情况下,字段类型应该是T
,而不是Option<T>
。
这些派生也可以与enum
一起使用来生成CHOICE
实现。
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
enum Time {
UTCTime(asn1::UtcTime),
GeneralizedTime(asn1::GeneralizedTime)
}
所有变体都必须有一个未命名的字段。
定义
rust-asn1还为处理ASN.1结构中的ANY DEFINED BY
情况提供了便捷的实用工具。例如,给定以下ASN.1;
MySequence ::= SEQUENCE {
contentType OBJECT IDENTIFIER,
content ANY DEFINED BY contentType
}
这可以表示为
#[derive(asn1::Asn1Read, asn1::Asn1Write)]
struct MySequence {
content_type: asn1::DefinedByMarker<asn1::ObjectIdentifier>,
#[defined_by(content_type)]
content: Content,
}
#[derive(asn1::Asn1DefinedByRead, asn1::Asn1DefinedByWrite)]
enum Content {
#[defined_by(SOME_OID_CONSTANT)]
SomeVariant(i32),
}
设计理念
正如我们所设计的asn1
crate,我们重视以下事物,按此顺序:
- 安全性
- 正确性
- 性能
- 易用性
依赖性
~260–710KB
~17K SLoC