ASN.1(抽象语法标记)是一种跨平台数据描述语言,通过TLV结构(类型-Tag、长度-Length、值-Value)实现结构化数据的标准化编码。其特点包括:
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}")
功能:表示整数值,支持任意大小(包括负值)
代码示例:age = univ.Integer(25)
特点:
subtypeSpec=constraint.ValueRangeConstraint(0, 100)
)功能:存储二进制数据
代码示例:data = univ.OctetString(b'\x01\x02\xFF')
特点:
功能:限制ASCII可打印字符(含@
等特殊字符)
代码示例:name = char.PrintableString("Alice@2023")
约束:仅支持字母、数字及'()+,-./:=?
等符号
功能:支持多语言Unicode字符
代码示例:多语言混合字符串
特点:
功能:存储布尔值
代码示例:flag = univ.Boolean(True)
特性:
True
或False
两种值功能:唯一标识实体(如算法、协议)
代码示例:RSA加密算法OID 1.2.840.113549.1.1.1
规则:
功能:表示UTC时间
代码示例:time = useful.UTCTime("250513120000Z")
格式要求:
YYMMDDhhmmssZ
格式(年份为两位数)+0800
)功能:表示二进制位序列
代码示例:bitStr = univ.BitString(0B111000111)
特性:
功能:创建同类型元素的有序列表
代码示例:strList = univ.SequenceOf(char.UTF8String())
操作:
.append()
动态添加元素ASN.1复合类型通过组合基础类型和嵌套结构实现复杂数据建模,主要包含以下核心类型:
class MyStruct(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('myInt', univ.Integer()),
namedtype.NamedType('myBool', univ.Boolean()),
# ...其他字段...
)
特点:
namedtype.NamedTypes
定义严格字段顺序(与协议规范兼容的关键)namedtype.OptionalNamedType
支持可选字段(代码未展示但实际支持)class InnerSeq(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('id', univ.Integer()),
namedtype.NamedType('name', char.UTF8String())
)
# 在主结构体中嵌套
my_struct['mySequence'] = inner_seq
应用场景:
# 整数列表
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(...))
关键特性:
0x30
,SEQUENCE OF的Tag为0x30
(与SEQUENCE相同)asn1Spec
参数强制类型校验,确保数据完整性prettyPrint()
方法可输出结构化文本(验证嵌套层级)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())
ASN.1通过TLV(Tag-Length-Value)三元组实现数据编码,其中标签(Tag)由以下三部分构成:
00
:通用标签(UNIVERSAL),如INTEGER(2)、OCTET STRING(4)等基础类型01
:应用标签(APPLICATION),用于特定协议场景10
:上下文专用标签(CONTEXT-SPECIFIC),用于嵌套结构中的局部标识11
:私有标签(PRIVATE),用于厂商自定义类型0
:原始类型(Primitive),如INTEGER、字符串1
:结构化类型(Constructed),如SEQUENCE、SET示例:BF 81 15
解析为私有类(11)、结构化类型(1)、标签号149(通过多字节编码实现)。
ASN.1使用BNF范式定义数据类型,语法规则包括:
ASN.1支持多种编码规则,其中与标记语法密切相关的包括:
在ASN.1语法中,表达赋值时必须使用双冒号等于号::=
,这是其标准语法规范的核心符号。以下从语法规则、应用场景和规范约束三个角度详细说明:
::=
ASN.1通过::=
符号严格区分类型定义和值赋值两种场景:
::=
声明新类型的结构或约束 UserAccount ::= SEQUENCE { -- 类型定义
username PrintableString,
accountNr INTEGER
}::=
为已定义类型赋予具体值 myAccount UserAccount ::= { -- 值赋值
username "Alice",
accountNr 1001
}这种设计避免了与其他符号(如单冒号:
)的歧义,确保语法解析的准确性。SEQUENCE
或CHOICE
等复合类型中,字段名后的冒号仅用于分隔字段名与类型,而非赋值: NetworkConfig ::= SEQUENCE {
ipAddress OCTET STRING : SIZE(4), -- 冒号用于类型约束
subnetMask [0] IMPLICIT INTEGER
}[TAG] IMPLICIT/EXPLICIT
时,冒号用于标签修饰,与赋值无关: CustomData ::= [APPLICATION 15] IMPLICIT INTEGER -- 标签修饰场景 | 符号 | 示例 | 规范依据 |
---|---|---|---|
类型/值定义 |
|
| ASN.1标准 |
字段类型声明 |
|
| 类型分隔符 |
标签修饰 |
|
| 编码规则 |
约束条件 |
|
| 子类型定义 |
在ASN.1中,所有赋值操作必须使用::=
,其他符号(如=
或:
)仅用于字段分隔、标签修饰等场景,不可替代赋值语义。
BIT STRING
标签为03
ASN.1的标记语法通过标签分类、结构化定义和编码规则,实现了跨平台数据描述的精确性和灵活性。其核心在于通过标签唯一性保证数据解析一致性,结合SEQUENCE/SET等复合类型,可描述从简单整数到多层嵌套证书结构的复杂数据。实际开发中需注意标签类别选择、显隐式编码差异及约束条件定义。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。