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),
}
设计理念
正如我们所设计的asn1crate,我们重视以下事物,按此顺序:
- 安全性
- 正确性
- 性能
- 易用性
依赖性
~260–710KB
~17K SLoC