Python新ASN.1 API:高性能、安全与现代化的密码学解析方案

本文介绍了Trail of Bits为Python开发的新ASN.1 API,基于Rust解析器提升性能,减少解析差异风险,并采用现代化dataclasses接口。适用于TLS、X.509证书及低层网络协议处理,增强密码学与供应链安全。

Python新ASN.1 API预览

ASN.1快速背景

ASN.1(Abstract Syntax Notation One)是一种接口描述语言(IDL),用于以语言和平台无关的方式描述数据结构。ASN.1本身不是序列化格式,而是定义编码规则,这些规则在不同设置下序列化和反序列化ASN.1结构。实践中,ASN.1通常与Distinguished Encoding Rules(DER)同义。

DER具有以下关键属性:

  • 规范编码:给定ASN.1结构只有一种DER编码方式,编码是确定性的,可以往返并保持比特级相等。
  • 相对紧凑:DER定义二进制格式,并禁止整数、布尔值和时间的非最小编码。
  • 自描述和自定界编码:DER消息可以在没有模式或格式描述的情况下完全解析。
  • 支持任意精度整数:DER的INTEGER类型大小无约束,适用于密码学中的大数表示。

这些属性使DER在密码学、网络和电信设置中非常流行。

为Python开发ASN.1库的动机

尽管大多数Python开发者不每天接触ASN.1,但许多情况下需要在X.509和其他已知格式之外进行ASN.1编码和解码。例如,Sigstore生态系统使用自定义X.509扩展,需要从Python中提取和处理这些扩展。

示例代码展示了如何使用PyCA Cryptography和pyasn1解析X.509扩展值:

1
2
3
4
5
6
7
8
from cryptography import x509
from pyasn1.codec.der.decoder import decode
from pyasn1.type.char import UTF8String

raw_cert = b"""..."""
cert = x509.load_pem_x509_certificate(raw_cert)
ext = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.57264.1.16")).value
ext_value = decode(ext.value, UTF8String)[0].decode()

为什么需要新库?

现有Python ASN.1实现(如pyasn1)存在三个主要问题:

  1. 性能:纯Python实现性能较低,新API使用纯Rust解析器(rust-asn1)接近原生性能。
  2. 减少差异:ASN.1实现异构,许多应用Postel定律解析“DER”数据,导致协议演进和安全问题。新库使用PyCA Cryptography已有的rust-asn1解析器,减少独立解析器数量。
  3. 现代化:新API暴露声明性dataclasses样式接口,支持类型提示,与类型检查器兼容。

示例ASN.1定义和对应Python代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from datetime import datetime
from cryptography.hazmat import asn1

@asn1.sequence
class Doohickies:
    tschotchkes: bytes
    baubles: int
    knickknacks: str
    whatchamacallits: list[asn1.ObjectIdentifier]
    gizmos: set[datetime] | None

doohickies = Doohickies.from_der(b"...")
print(doohickies.tschotchkes)
doohickies.to_der()  # b"..."

更多内容敬请期待

开发计划包括:

  1. 构建初始版本,支持@asn1.sequence@asn1.enum装饰器,以及ASN.1基本类型和修饰符。
  2. 集成到PyCA Cryptography,可能作为cryptography.asn1cryptography.hazmat.asn1,并尽可能去重类型。
  3. 随PyCA Cryptography主要版本发布。

感谢Alpha-Omega资助此工作,以及PyCA Cryptography维护者的支持和设计审查。


脚注

  • ASN.1也广泛使用Basic Encoding Rules(BER),但BER不是规范编码, historically是PKI生态系统中内存损坏和互操作性问题的来源。
  • X.509扩展值原因是微妙的:X.509本身说扩展值只是OCTET STRING(原始字节),而RFC 5280说OCTET STRING应包含对应扩展OID的ASN.1值的DER编码。
  • 部分感谢@typing.dataclass_transform,如PEP 681引入。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计