首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于 pyasn1 的ASN1 编码入门

基于 pyasn1 的ASN1 编码入门

原创
作者头像
密码学人CipherHUB
发布2025-05-13 15:51:50
发布2025-05-13 15:51:50
37610
代码可运行
举报
文章被收录于专栏:数安视界数安视界
运行总次数:0
代码可运行

基础认知

核心概念

ASN.1(抽象语法标记)是一种跨平台数据描述语言,通过TLV结构(类型-Tag、长度-Length、值-Value)实现结构化数据的标准化编码。其特点包括:

  • 平台无关性:适用于Java/Python/C等语言
  • 类型丰富:支持20+基础类型和复合结构
  • 编码规范:BER/DER/CER等编码规则保证数据一致性

基础类型

代码语言:python
代码运行次数:0
运行
复制
from __future__ import annotations

# 时间类型(UTCTime)
from pyasn1.type import char, univ, useful

# 整数类型(INTEGER)
age = univ.Integer(25)
print(f"INTEGER示例:{age.prettyPrint()}, 类型:{type(age)}")  # 输出:25

# 字节串(OCTET STRING)
data = univ.OctetString(b'\x01\x02\xFF')
print(f"OCTET STRING示例:{data.asOctets()}, 类型:{type(data)}")  # 输出:b'\x01\x02\xff'

# 可打印字符串(PrintableString)
name = char.PrintableString("Alice@2023")
print(f"字符串示例:{name.prettyPrint()}, 类型:{type(name)}")  # 输出:'Alice@2023'

# 布尔值(BOOLEAN)
flag = univ.Boolean(True)
print(f"布尔值示例:{flag.prettyPrint()}, 类型:{type(flag)}")  # 输出:True

# 对象标识符(OBJECT IDENTIFIER)
oid = univ.ObjectIdentifier('1.2.840.113549.1.1.1')  # RSA加密算法OID
print(f"OID示例:{oid.prettyPrint()}, 类型:{type(oid)}")  # 输出:1.2.840.113549.1.1.1

time = useful.UTCTime("250513120000Z")  # 2025-05-13 12:00:00 UTC
print(f"时间示例:{time.prettyPrint()}, 类型:{type(time)}")

# 中文、日文、韩文、泰语、越南语、印地语
utf8Str = char.UTF8String(
    "编码解码 エンコードとデコード 인코딩 및 디코딩 การเข้ารหัสและการถอดรหัส Mã hóa và Giải mã एन्कोडिंग और डिकोडिंग")
print(f"UTF8String示例:{utf8Str.prettyPrint()}, 类型:{type(utf8Str)}")

bitStr = univ.BitString(0B111000111)  # 可以指定任意长度的比特位
print(f"BitString示例:{bitStr.prettyPrint()}, 类型:{type(bitStr)}")

strList = univ.SequenceOf(char.UTF8String())  # 可以指定任意长度的字符串列表
for i in ['中文', '日文', '韩文', '泰语', '越南语', '印地语']:
    strList.append(char.UTF8String(i))
print(f"SequenceOf示例:{strList.prettyPrint()}, 类型:{type(strList)}, 元素类型:{strList.typeId}")

INTEGER类型

功能:表示整数值,支持任意大小(包括负值)

代码示例age = univ.Integer(25)

特点

  • 支持大整数运算,无溢出限制
  • 常用于版本号、计数器等场景
  • 可添加值域约束(如subtypeSpec=constraint.ValueRangeConstraint(0, 100)

OCTET STRING类型

功能:存储二进制数据

代码示例data = univ.OctetString(b'\x01\x02\xFF')

特点

  • 以字节序列形式存储任意二进制内容
  • 支持十六进制/二进制格式初始化
  • 常用于证书公钥、加密数据等场景

字符串类型

1. PrintableString

功能:限制ASCII可打印字符(含@等特殊字符)

代码示例name = char.PrintableString("Alice@2023")

约束:仅支持字母、数字及'()+,-./:=?等符号

2. UTF8String

功能:支持多语言Unicode字符

代码示例:多语言混合字符串

特点

  • 支持中文、日文、韩文等复杂字符集
  • 编码方式为UTF-8,兼容国际化场景

BOOLEAN类型

功能:存储布尔值

代码示例flag = univ.Boolean(True)

特性

  • 仅允许TrueFalse两种值
  • 常用于协议中的开关标记

OBJECT IDENTIFIER类型

功能:唯一标识实体(如算法、协议)

代码示例:RSA加密算法OID 1.2.840.113549.1.1.1

规则

  • 以点分十进制表示层级结构
  • 标准OID需遵循IANA注册规范

时间类型(UTCTime)

功能:表示UTC时间

代码示例time = useful.UTCTime("250513120000Z")

格式要求

  • 使用YYMMDDhhmmssZ格式(年份为两位数)
  • 年份范围通常解释为1950-2049
  • 支持带时区偏移(如+0800

BitString类型

功能:表示二进制位序列

代码示例bitStr = univ.BitString(0B111000111)

特性

  • 支持任意长度位操作
  • 可指定填充位(如网络协议标志位)

SEQUENCE OF类型

功能:创建同类型元素的有序列表

代码示例strList = univ.SequenceOf(char.UTF8String())

操作

  • 通过.append()动态添加元素
  • 支持嵌套复杂结构(如结构体列表)

复合类型

复合类型核心概念

ASN.1复合类型通过组合基础类型和嵌套结构实现复杂数据建模,主要包含以下核心类型:

  1. SEQUENCE:有序字段集合(类似C语言结构体)
  2. SEQUENCE OF:同类型元素的有序列表(类似数组)
  3. SET/SET OF:无序字段集合(代码未使用但需了解)
  4. CHOICE:多选一类型(代码未使用但需了解)

代码中复合类型实现详解

1. SEQUENCE结构(主结构体)

代码语言:python
代码运行次数:0
运行
复制
class MyStruct(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('myInt', univ.Integer()),
        namedtype.NamedType('myBool', univ.Boolean()),
        # ...其他字段...
    )

特点

  • 支持异构数据类型组合(如INTEGER、BOOLEAN、OCTET STRING等混合使用)
  • 通过namedtype.NamedTypes定义严格字段顺序(与协议规范兼容的关键)
  • 可扩展性:通过namedtype.OptionalNamedType支持可选字段(代码未展示但实际支持)

2. 嵌套SEQUENCE(结构体嵌套)

代码语言:python
代码运行次数:0
运行
复制
class InnerSeq(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('id', univ.Integer()),
        namedtype.NamedType('name', char.UTF8String())
    )

# 在主结构体中嵌套
my_struct['mySequence'] = inner_seq

应用场景

  • 实现树形数据结构(如证书中的签发者/主体信息嵌套)
  • 编码时自动生成嵌套TLV结构(Tag-Length-Value层次)
  • 支持无限层级嵌套(如X.509证书中的扩展字段)

3. SEQUENCE OF类型(列表结构)

代码语言:python
代码运行次数:0
运行
复制
# 整数列表
intList = univ.SequenceOf(univ.Integer())
for num in [1,2,3,4,5]:
    intList.append(univ.Integer(num))

# 结构体列表
seqOfSeq = univ.SequenceOf(InnerSeq())
seqOfSeq.append(InnerSeq().setComponents(...))

关键特性

  • 动态长度支持:无需预先声明元素数量
  • 同构约束:列表内所有元素必须为指定类型(如INTEGER或InnerSeq)
  • 编码优化:DER编码会对重复结构进行长度压缩

复合类型编码规则

  1. DER编码规范
    • 采用TLV三元组结构(Tag-Length-Value)
    • SEQUENCE的Tag值为0x30,SEQUENCE OF的Tag为0x30(与SEQUENCE相同)
    • 嵌套结构会产生多级TLV嵌套(可通过HEX结果观察层次)
  2. 编码验证:der_data = encoder.encode(my_struct) # 生成二进制流 decoded_struct = decoder.decode(der_data) # 反向解析验证
  3. 解码时通过asn1Spec参数强制类型校验,确保数据完整性
  4. prettyPrint()方法可输出结构化文本(验证嵌套层级)

完整示例代码

代码语言:python
代码运行次数:0
运行
复制
from __future__ import annotations

from pyasn1.codec.der import decoder, encoder
from pyasn1.type import char, namedtype, univ, useful


# 定义内嵌的Sequence类型
class InnerSeq(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('id', univ.Integer()),
        namedtype.NamedType('name', char.UTF8String()),
        namedtype.NamedType('enabled', univ.Boolean())
    )


# 主结构体
class MyStruct(univ.Sequence):
    componentType = namedtype.NamedTypes(
        namedtype.NamedType('myInt', univ.Integer()),  # INTEGER
        namedtype.NamedType('myBool', univ.Boolean()),  # BOOLEAN
        namedtype.NamedType('myOctets', univ.OctetString()),  # OCTET STRING
        namedtype.NamedType('myUtf8', char.UTF8String()),  # UTF8String
        namedtype.NamedType('myNull', univ.Null()),  # NULL
        namedtype.NamedType('myOid', univ.ObjectIdentifier()),  # OBJECT IDENTIFIER
        namedtype.NamedType('myBitStr', univ.BitString()),  # BIT STRING
        namedtype.NamedType('myTime', useful.UTCTime()),  # UTCTime
        namedtype.NamedType('mySequence', InnerSeq()),  # 嵌套Sequence,可以理解为嵌套的结构体
        namedtype.NamedType('intList', univ.SequenceOf(
            univ.Integer())),  # SequenceOf INTEGER
        namedtype.NamedType('seqOfSeq', univ.SequenceOf(
            InnerSeq()))  # SequenceOf InnerSeq
    )


# 创建数据实例
my_struct = MyStruct()

# 基本类型赋值
my_struct['myInt'] = 2025
my_struct['myBool'] = True
my_struct['myOctets'] = b'\x01\x02\x03'
my_struct['myInt'] = 123456789
my_struct['myBool'] = True
my_struct['myUtf8'] = '你好,世界'
my_struct['myNull'] = univ.Null()
my_struct['myOid'] = '1.3.6.1.4.1.99999'  # OBJECT IDENTIFIER
# my_struct['myBitStr'] = univ.BitString.fromHexString('FACE')  # 二进制位字符串
my_struct['myBitStr'] = 0b10101  # 二进制位字符串
my_struct['myTime'] = '230501120000Z'  # UTC时间(2023-05-01 12:00:00)

# 嵌套Sequence赋值
inner_seq = InnerSeq()
inner_seq['id'] = 65535
inner_seq['name'] = '嵌套结构'
inner_seq['enabled'] = False
my_struct['mySequence'] = inner_seq

# SequenceOf INTEGER赋值
# 正确赋值
for num in [1, 2, 3, 4, 5]:
    my_struct['intList'].append(univ.Integer(num))  # 正确方式

# SequenceOf InnerSeq赋值
seq_of_seq = [
    InnerSeq().setComponents(1, '第一个', True),
    InnerSeq().setComponents(2, '第二个', False)
]
for item in seq_of_seq:
    my_struct['seqOfSeq'].append(item)  # 正确方式

# DER编码
der_data = encoder.encode(my_struct)
print("DER编码结果:", der_data.hex())

# DER解码
decoded_struct, _ = decoder.decode(der_data, asn1Spec = MyStruct())

print(f"解码验证成功! decoded_struct类型:{type(decoded_struct)}")
print("嵌套Sequence:", decoded_struct['mySequence'].prettyPrint())
print("整数列表:", list(decoded_struct['intList']))
print("结构体列表:")
for i, item in enumerate(decoded_struct['seqOfSeq']):
    print(f"  结构体{i + 1}:", item.prettyPrint())
运行结果
运行结果

标记语法

标签(Tag)结构

ASN.1通过TLV(Tag-Length-Value)三元组实现数据编码,其中标签(Tag)由以下三部分构成:

  1. 类别位(Class):2位,定义标签的归属范围:
    • 00:通用标签(UNIVERSAL),如INTEGER(2)、OCTET STRING(4)等基础类型
    • 01:应用标签(APPLICATION),用于特定协议场景
    • 10:上下文专用标签(CONTEXT-SPECIFIC),用于嵌套结构中的局部标识
    • 11:私有标签(PRIVATE),用于厂商自定义类型
  2. 结构化位(P/C):1位,指示是否为复合结构:
    • 0:原始类型(Primitive),如INTEGER、字符串
    • 1:结构化类型(Constructed),如SEQUENCE、SET
  3. 标签号(Tag Number):5位或扩展编码,唯一标识具体类型:
    • 标签号≤30时,用单个字节表示
    • 标签号>30时,采用多字节编码(首个字节后5位全1,后续字节最高位为延续标志)

示例BF 81 15 解析为私有类(11)、结构化类型(1)、标签号149(通过多字节编码实现)。

类型定义语法

ASN.1使用BNF范式定义数据类型,语法规则包括:

  1. 基础类型:直接使用预定义标签,如:Age ::= INTEGER Name ::= PrintableString (SIZE(1..64))
  2. 复合类型
    • SEQUENCE:有序结构体(类似C语言struct):UserRecord ::= SEQUENCE { username UTF8String, age INTEGER, active BOOLEAN OPTIONAL }
    • SEQUENCE OF:同类型元素的有序列表(类似数组):IntList ::= SEQUENCE OF INTEGER
  3. 标签修饰:CustomInt ::= [APPLICATION 15] IMPLICIT INTEGER -- 标签替换
    • 显式标签(EXPLICIT):为原有类型添加新标签,编码时嵌套TLV结构
    • 隐式标签(IMPLICIT):直接替换原有标签,不嵌套TLV结构

编码规则

ASN.1支持多种编码规则,其中与标记语法密切相关的包括:

  1. BER(基本编码规则)
    • 每个数据单元编码为TLV结构,如:02 01 25 -- INTEGER类型(Tag=02),长度1字节,值0x25(十进制37)
    • 支持定长(短/长编码)和不定长格式
  2. DER(可辨别编码规则)
    • BER的子集,强制使用定长编码和严格标签排序,适用于数字证书等场景

赋值表达

在ASN.1语法中,表达赋值时必须使用双冒号等于号::=,这是其标准语法规范的核心符号。以下从语法规则、应用场景和规范约束三个角度详细说明:

语法规则强制使用::=

ASN.1通过::=符号严格区分类型定义值赋值两种场景:

  1. 类型定义:用::=声明新类型的结构或约束 UserAccount ::= SEQUENCE { -- 类型定义 username PrintableString, accountNr INTEGER }
  2. 值赋值:用::=为已定义类型赋予具体值 myAccount UserAccount ::= { -- 值赋值 username "Alice", accountNr 1001 }这种设计避免了与其他符号(如单冒号:)的歧义,确保语法解析的准确性。

规范约束与扩展场景

  1. 复合类型扩展:undefined在SEQUENCECHOICE等复合类型中,字段名后的冒号仅用于分隔字段名与类型,而非赋值: NetworkConfig ::= SEQUENCE { ipAddress OCTET STRING : SIZE(4), -- 冒号用于类型约束 subnetMask [0] IMPLICIT INTEGER }
  2. 显式/隐式标签修饰:undefined使用[TAG] IMPLICIT/EXPLICIT时,冒号用于标签修饰,与赋值无关: CustomData ::= [APPLICATION 15] IMPLICIT INTEGER -- 标签修饰

总结

场景

符号

示例

规范依据

类型/值定义

::=

Age ::= INTEGER

ASN.1标准

字段类型声明

:

username : PrintableString

类型分隔符

标签修饰

[]

[PRIVATE 2] IMPLICIT INTEGER

编码规则

约束条件

()

OCTET STRING (SIZE(4))

子类型定义

在ASN.1中,所有赋值操作必须使用::=,其他符号(如=:)仅用于字段分隔、标签修饰等场景,不可替代赋值语义。

典型应用示例

  1. 数字证书中的嵌套结构:Certificate ::= SEQUENCE { tbsCertificate TBSCertificate, signatureAlgorithm AlgorithmIdentifier, signature BIT STRING }
    • 每个字段通过标签标识类型,如BIT STRING标签为03
  2. 网络协议(如SNMP):GetRequest-PDU ::= [0] IMPLICIT SEQUENCE { -- 上下文标签0 request-id INTEGER, error-status INTEGER, variable-bindings SEQUENCE OF OCTET STRING }

ASN.1的标记语法通过标签分类、结构化定义和编码规则,实现了跨平台数据描述的精确性和灵活性。其核心在于通过标签唯一性保证数据解析一致性,结合SEQUENCE/SET等复合类型,可描述从简单整数到多层嵌套证书结构的复杂数据。实际开发中需注意标签类别选择、显隐式编码差异及约束条件定义。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基础认知
    • 核心概念
    • 基础类型
      • INTEGER类型
      • OCTET STRING类型
      • 字符串类型
      • BOOLEAN类型
      • OBJECT IDENTIFIER类型
      • 时间类型(UTCTime)
      • BitString类型
      • SEQUENCE OF类型
  • 复合类型
    • 复合类型核心概念
    • 代码中复合类型实现详解
      • 1. SEQUENCE结构(主结构体)
      • 2. 嵌套SEQUENCE(结构体嵌套)
      • 3. SEQUENCE OF类型(列表结构)
    • 复合类型编码规则
    • 完整示例代码
  • 标记语法
    • 标签(Tag)结构
    • 类型定义语法
    • 编码规则
    • 赋值表达
      • 语法规则强制使用::=
      • 规范约束与扩展场景
      • 总结
    • 典型应用示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档