基础认知

核心概念

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

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

基础类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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)

特性

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

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结构(主结构体)

1
2
3
4
5
6
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(结构体嵌套)

1
2
3
4
5
6
7
8
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类型(列表结构)

1
2
3
4
5
6
7
8
# 整数列表
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结果观察层次)
  1. 编码验证:der_data = encoder.encode(my_struct) # 生成二进制流 decoded_struct = decoder.decode(der_data) # 反向解析验证
  2. 解码时通过asn1Spec参数强制类型校验,确保数据完整性
  3. prettyPrint()方法可输出结构化文本(验证嵌套层级)

完整示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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())

img

标记语法

标签(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),用于厂商自定义类型
  1. 结构化位(P/C):1位,指示是否为复合结构:
  • 0:原始类型(Primitive),如INTEGER、字符串
  • 1:结构化类型(Constructed),如SEQUENCE、SET
  1. 标签号(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
  1. 标签修饰:CustomInt ::= [APPLICATION 15] IMPLICIT INTEGER – 标签替换
  • 显式标签(EXPLICIT):为原有类型添加新标签,编码时嵌套TLV结构
  • 隐式标签(IMPLICIT):直接替换原有标签,不嵌套TLV结构

编码规则

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

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

赋值表达

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

语法规则强制使用::=

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

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

规范约束与扩展场景

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

总结

场景符号示例规范依据
类型/值定义::=Age ::= INTEGERASN.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
  1. 网络协议(如SNMP):GetRequest-PDU ::= [0] IMPLICIT SEQUENCE { – 上下文标签0 request-id INTEGER, error-status INTEGER, variable-bindings SEQUENCE OF OCTET STRING }

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