10个版本
0.3.5 | 2023年1月23日 |
---|---|
0.3.4 | 2022年10月18日 |
0.3.3 | 2022年8月2日 |
0.3.2 | 2021年10月29日 |
0.1.2 | 2021年8月30日 |
#207 in 编码
2,069 monthly downloads
用于 2 个 crate (via kmip-protocol)
255KB
3.5K SLoC
kmip-ttlv - 用于序列化和反序列化KMIP TTLV的库
KMIP:
OASIS密钥管理互操作性协议规范,该规范定义了在密钥管理服务器上操作加密材料的消息格式。
TTLV:
KMIP规范的一个构建块,定义了如何将结构化数据编码/解码为二进制形式,作为Tag-Type-Length-Value(简称TTLV)项的序列。
欢迎
此crate提供KMIP v1.0 TTLV(反)序列化功能的部分实现,供kmip-protocol
crate使用。如果您想将自己的产品添加KMIP支持,应使用kmip-protocol
crate。TTLV在KMIP中定义,但与KMIP独立,因此理论上也可以用于除KMIP之外的应用程序的(反)序列化。
目的
此crate提供了从/到等效KMIP TTLV字节数表示的Rust原语(例如i32)的低级(反)序列化。它提供了一种基于Serde Derive的单个to_/from_
调用风格的(反)序列化整个Rust类型层次结构的API(这最容易被Serde Derive属性驱动),以及一个低级API,用于一次序列化一个TTLV字段(标签、类型、长度或值),以实现完全控制。
目前范围限于二进制TTLV协议。对后续KMIP规范中定义的XML或JSON表示形式的支持不在范围内。
文档
完整的API文档可以在https://docs.rs/kmip-ttlv/查看。
状态
此crate以现状提供,不提供稳定性、质量或正确性的保证。使用风险自负。
请参阅https://github.com/NLnetLabs/kmip-ttlv/blob/main/src/tests/,了解对低级和高级(基于Serde)API的各种自动化测试。已成功对PyKMIP和Kryptus Cloud HSM服务器进行了有限的手动测试。
问题报告、功能请求和贡献可以通过我们的GitHub仓库提交。
本crate的功能以及支持的TTLV和Rust数据类型,是为了为kmip-protocol
crate提供基础。因此,本crate目前还不支持所有可能的TTLV或Rust类型。
并非所有TTLV类型都受支持
TTLV类型 | TTLV类型代码 | 受支持? |
---|---|---|
结构 | 0x01 | ✅ |
整数 | 0x02 | ✅ |
长整数 | 0x03 | ✅ |
大整数 | 0x04 | ✅ (序列化仅在低级API中支持,不在Serde中支持) |
枚举 | 0x05 | ✅ |
布尔值 | 0x06 | ✅ |
文本字符串 | 0x07 | ✅ |
字节字符串 | 0x08 | ✅ |
日期时间 | 0x09 | ✅ |
间隔 | 0x0A | ❌ |
设计目标
- 提供一个强类型接口,防止在高级KMIP接口规范中没有正确意义的低级构建块的错误组合。利用Rust的编译时能力,尽可能防止编写错误的请求,以最大限度地减少运行时对协议的错误使用。
- 以简洁的方式支持高级KMIP请求结构的组合,并且使编写的代码与KMIP规范明显相关。
- 使用反序列化数据不应需要详细了解KMIP规范,即应使用Rust类型,而不是TTLV类型,并且与之交互的对象应具有清晰命名的字段,并且只包含与请求相关的响应字段。
- TTLV标签代码应在它们标记的类型定义附近定义。
示例代码
基于KMIP v1.0规范第3.1.1节中定义的“创建/销毁”用例。
以下示例假设客户端代码已定义Rust structs
,根据需要将其转换为#[derive(Serialize)]
或#[derive(Deserialize)]
,以便Serde基于(反)序列化器知道每个数据结构应使用哪些标签代码。
(可能更改)
请求构建
// serialize the request
let req = RequestMessage(
RequestHeader(
request::ProtocolVersion(ProtocolVersionMajor(1), ProtocolVersionMinor(0)),
Option::<MaximumResponseSize>::None,
Option::<Authentication>::None,
BatchCount(1),
),
vec![BatchItem(
Operation::Create,
Option::<UniqueBatchItemID>::None,
RequestPayload::Create(
ObjectType::SymmetricKey,
TemplateAttribute::named(
"Template1".into(),
vec![
Attribute::CryptographicAlgorithm(CryptographicAlgorithm::AES),
Attribute::CryptographicLength(128),
Attribute::CryptographicUsageMask(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
],
),
),
)],
);
let ttlv_wire: Vec<u8> = to_vec(&req).unwrap();
// now write the `ttlv_wire` request bytes to an open TLS connection to the server
响应处理
// read the `ttlv_wire` response bytes from an open TLS connection to the server:
let ttlv_wire: Vec<u8> = ...;
// deserialize the response
let res: ResponseMessage = from_slice(ttlv_wire.as_ref()).unwrap();
assert_eq!(res.header.protocol_version.major, 1);
assert_eq!(res.header.protocol_version.minor, 0);
assert_eq!(res.header.timestamp, 0x4AFBE7C5);
assert_eq!(res.header.batch_count, 1);
assert_eq!(res.batch_items.len(), 1);
let item = &res.batch_items[0];
assert!(matches!(item.result_status, ResultStatus::Success));
assert!(matches!(item.operation, Some(Operation::Create)));
assert!(matches!(&item.payload, Some(ResponsePayload::Create(_))));
if let Some(ResponsePayload::Create(payload)) = item.payload.as_ref() {
assert!(matches!(payload.object_type, ObjectType::SymmetricKey));
assert_eq!(&payload.unique_identifier, KEY_ID);
}
处理时间戳
时间戳以TTLV Date-Time
格式存储,该格式转换为64位整数,直到您正确并正确地解释它并在正确时区的上下文中,它才具有现实世界的意义。直接处理64位整数值可能不切实际。本crate目前不提供更轻松地处理这些值的方法,但使用Rust生态系统中的现有crate进行此操作相对容易。
例如,对于上面基于官方KMIP用例的示例,用例描述表明 0x4AFBE7C5
的值等同于 Thu Nov 12 11:47:32 CET 2009
。以下我们使用 chrono 包来演示这是真实的,并展示如何在您的应用程序中处理 Date-Time
值。
let one_hour_in_seconds = 3600;
let cet_tz = chrono::offset::FixedOffset::east(one_hour_in_seconds);
let cet_ts = cet_tz.timestamp(res.header.timestamp);
assert_eq!(cet_ts, cet_tz.ymd(2009,11,12).and_hms(11,47,32)
assert_eq!(cet_ts.format("%a %b %e %T %Z %Y").to_string(), "Thu Nov 12 11:47:32 +01:00 2009");
依赖关系
~1–12MB
~144K SLoC