#iterator #pem #parser #decode #private-key #crypto

no-std pem-iterator

遍历PEM编码数据

2个不稳定版本

使用旧的Rust 2015

0.2.0 2017年11月26日
0.1.0 2017年11月13日

#1430 in 加密学

MIT/Apache

52KB
1.5K SLoC

PEM迭代器

遍历PEM编码数据。

特性

  • 通过迭代器启用解码PEM格式数据。
  • 快速。当前基准测试表明它比pemcrate快2x-4x。
  • 无依赖,无不安全,无动态分配,仅需要core
  • 高度可定制的封装边界解析。
  • 健壮的解析。底层流产生的错误不会丢失状态。

用法

Cargo.toml:

[dependencies]
pem-iterator = "0.2"

crate根目录

extern crate pem_iterator;

示例

extern crate pem_iterator;

use pem_iterator::boundary::{BoundaryType, BoundaryParser, LabelMatcher};
use pem_iterator::body::Single;


const SAMPLE: &'static str = "-----BEGIN RSA PRIVATE KEY-----
MIIBPQIBAAJBAOsfi5AGYhdRs/x6q5H7kScxA0Kzzqe6WI6gf6+tc6IvKQJo5rQc
dWWSQ0nRGt2hOPDO+35NKhQEjBQxPh/v7n0CAwEAAQJBAOGaBAyuw0ICyENy5NsO
2gkT00AWTSzM9Zns0HedY31yEabkuFvrMCHjscEF7u3Y6PB7An3IzooBHchsFDei
AAECIQD/JahddzR5K3A6rzTidmAf1PBtqi7296EnWv8WvpfAAQIhAOvowIXZI4Un
DXjgZ9ekuUjZN+GUQRAVlkEEohGLVy59AiEA90VtqDdQuWWpvJX0cM08V10tLXrT
TTGsEtITid1ogAECIQDAaFl90ZgS5cMrL3wCeatVKzVUmuJmB/VAmlLFFGzK0QIh
ANJGc7AFk4fyFD/OezhwGHbWmo/S+bfeAiIh2Ss2FxKJ
-----END RSA PRIVATE KEY-----";

let mut input = SAMPLE.chars().enumerate();

let mut label_buf = String::new();
{
    let mut parser = BoundaryParser::from_chars(BoundaryType::Begin, &mut input, &mut label_buf);
    assert_eq!(parser.next(), None);
    assert_eq!(parser.complete(), Ok(()));
}
println!("PEM label: {}", label_buf);

// Parse the body
let data: Result<Vec<u8>, _> = Single::from_chars(&mut input).collect();
let data = data.unwrap();

// Verify the end boundary has the same label as the begin boundary
{
    let mut parser = BoundaryParser::from_chars(BoundaryType::End, &mut input, LabelMatcher(label_buf.chars()));
    assert_eq!(parser.next(), None);
    assert_eq!(parser.complete(), Ok(()));
}

println!("data: {:?}", data);

BoundaryParserLabel

解析PEM格式数据的第一步是解析BEGIN边界。进入BoundaryParser。此迭代器类型在构造时需要三个参数

  • 一个用于BEGINEND的枚举值。
  • 获取字符的流。
  • 处理标签的对象。

第三个参数拥有很多功能。基本上,解析器在遇到标签时,将通过Label特征通知此参数每个字符。这使它能够实现许多不同的行为,例如

  • 将字符累积到缓冲区中(例如,&mut String
  • 匹配已知字符。(例如,LabelMatcher("CERTIFICATE".chars())
  • 完全丢弃字符(例如,DiscardLabel

除了简单的Mismatch错误之外,此标签处理还可以返回自定义的复杂错误。使功能更加多样化和可扩展。

由于解析BEGIN标签与解析END标签完全独立,因此可以混合匹配策略以自定义严格的程度(例如,BEGINEND可以有不同的标签)。

分块与单次

对于解析主体,此crate提供了两个迭代器,ChunkedSingle。基本区别在于Chunked一次发出3字节输出(对应于4个输入字符),而Single一次只发出1字节。

这两个之间可能会有一些性能差异,但到目前为止,它们看起来几乎相同。最初,这两个之间有更多的区别,性能和功能之间需要进行权衡,但到现在,差异主要是人体工程学上的。

弹性解析

这个crate的主要类型(BoundaryParserChunkedSingle)都是迭代器。显然,体解析器是迭代器的原因是它们需要遍历输出字节。那么为什么BoundaryParser也是迭代器呢?

基本上,这使得解析更加弹性。如果底层流发出错误,可以将错误转发给调用者并处理,而不会丢失解析状态。这有用吗?可能没有。大多数情况下,你可能只想在流错误时失败。但这确实很酷。

无运行时依赖