Rust中如何使用预编码DER片段构造ASN.1 SEQUENCE的DER编码
问题描述
我需要在Rust中对如下ASN.1结构执行DER编码:
issuerAndSubject ::= SEQUENCE { issuer Name, subject Name }
上述结构中的Name结构定义于RFC5280标准,逻辑较为复杂,我不希望在Rust代码中重新实现该结构的定义。
我已经通过rust-openssl库创建得到了issuer和subject两个对象:
let issuer: &X509NameRef = get_issuer(); let subject: &X509NameRef = get_subject();
我可以很便捷地获取这两个对象对应的DER编码结果:
let issuer_der = issuer.to_der().unwrap(); let subject_der = subject.to_der().unwrap();
但我需要将这两段已编码的DER数据封装到一个SEQUENCE结构中。我优先选择使用Rust的asn1 crate来创建SEQUENCE,当前编写的示例代码如下:
let ias_der = asn1::write(|w| { w.write_element( &asn1::SequenceWriter::new(&|w| { w.write_element(&issuer_der); // I know, this doesn't work, but w.write_element(&subject_der); // how do I do it? })); });
核心诉求:是否存在可行的实现方式,能够直接使用已完成DER编码的数据构造目标SEQUENCE结构?
实现方案
基于asn1 crate的原生实现
你的代码无法正常运行的原因是write_element接收的是实现了Asn1Writable trait的类型,对于已经编码完成的完整DER片段,直接调用write_der方法写入即可,该方法会直接将合法的DER编码字节作为完整元素写入当前序列,不需要额外解析或重构,修正后的代码如下:
let ias_der = asn1::write(|w| { w.write_element(&asn1::SequenceWriter::new(&|w| { w.write_der(&issuer_der).unwrap(); w.write_der(&subject_der).unwrap(); })) }).unwrap();
注意:
write_der要求传入的字节必须是完整合法的DER TLV结构,X509NameRef::to_der()返回的结果刚好是符合要求的完整Name结构编码,可直接使用。
手动拼接DER结构(无额外依赖)
如果不想依赖asn1 crate的特定API,也可以按照DER编码规则手动拼接SEQUENCE结构,逻辑非常简单:
- 计算所有内部元素的总字节长度:两个DER片段的长度相加
- 生成SEQUENCE结构的TLV头:固定tag值为构造式通用SEQUENCE即
0x30,后接DER规则编码的长度值 - 按顺序拼接SEQUENCE头、issuer_der、subject_der即可得到最终结果
手动实现的参考代码:
fn wrap_der_sequence(elements: &[&[u8]]) -> Vec<u8> { let content_total_len: usize = elements.iter().map(|elem| elem.len()).sum(); let mut result = Vec::new(); // 写入SEQUENCE标签 result.push(0x30); // 按DER规则编码长度字段 match content_total_len { len if len < 128 => result.push(len as u8), len => { let len_be = len.to_be_bytes(); let valid_len_bytes = len_be.iter().skip_while(|&&b| b == 0).copied().collect::<Vec<u8>>(); result.push(0x80 | valid_len_bytes.len() as u8); result.extend_from_slice(&valid_len_bytes); } } // 拼接所有内部已编码元素 for elem in elements { result.extend_from_slice(elem); } result } // 调用示例 let ias_der = wrap_der_sequence(&[&issuer_der, &subject_der]);
两种方案生成的编码结果完全符合DER规范,均不需要重新实现RFC5280中定义的Name结构。
内容的提问来源于stack exchange,提问作者kletterstein
相关产品推荐
相关产品推荐

