https://github.com/etingof/pyasn1
pyasn1文档
这是一个作为Python包的ASN.1类型和编解码器的免费开源实现。它最初是为了支持特定的协议(SNMP)而编写的,但后来被推广为适用于基于ASN.1规范的各种协议。
pyasn1在pyasn1.type
中定义了ASN.1标准中的所有类型,对于结构化的类型,我们可以用类的方法来定义一个模板。比如这样的ASN.1结构
Record ::= SEQUENCE {
id INTEGER,
room [0] INTEGER OPTIONAL,
house [1] INTEGER DEFAULT 0
}
可以表示成这样的python代码
class Record(Sequence):
componentType = NamedTypes(
NamedType(‘id‘, Integer()),
OptionalNamedType(
‘room‘, Integer().subtype(
implicitTag=Tag(tagClassContext, tagFormatSimple, 0)
)
),
DefaultedNamedType(
‘house‘, Integer(0).subtype(
implicitTag=Tag(tagClassContext, tagFormatSimple, 1)
)
)
)
具体的Type有自己的行为,在文档里都有说明,虽然我感觉文档写的也不是特别清楚。
可以在定义数据类型的时候直接赋值,例如Integer(1)
就直接生成值为1的Integer类型。但是更多的是先定义一个schema,再赋值,例如
>>> record = Record()
>>> record[‘id‘] = 123
>>> record[‘room‘] = 321
>>> str(record)
Record:
id=123
room=321
>>>
这是对于NamedType
可以直接用类似键值对的方式赋值,不同类型也可能有其他的赋值方法,比如说setComponentByPosition
,或者extend
加解码函数包含在pyasn1.codec.der.encoder
和pyasn1.codec.der.decoder
中,der
也可以是cer
或者其他ASN.1的表示方法
encode
函数可以将定义好的ASN.1结构序列化,例如
>>> from pyasn1.codec.der.encoder import encode
>>> substrate = encode(record)
>>> hexdump(substrate)
00000: 30 07 02 01 7B 80 02 01 41
decode
函数可以解码二进制数据,也可以指定格式来解码,例如
>>> from pyasn1.codec.der.decoder import decode
>>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record())
>>>
>>> for field in received_record:
>>> print(‘{} is {}‘.format(field, received_record[field]))
id is 123
room is 321
house is 0
返回值是反序列化出来的pyasn1对象的元组和未处理的尾随部分(可能为空)
接着上一次asn.1 格式学习最后的例子,我们用代码来实现对ASN.1结构的加解码
首先定义好schema
from pyasn1.type.tag import *
from pyasn1.type.namedtype import *
from pyasn1.type.univ import *
from pyasn1.type.char import *
class AttributeValueAssertion(Sequence):
componentType = NamedTypes(
NamedType(‘attributeType‘, ObjectIdentifier()),
NamedType(‘attributeValue‘, PrintableString())
)
class RelativeDistinguishedName(SetOf):
componentType = AttributeValueAssertion()
class RDNSequence(SequenceOf):
componentType = RelativeDistinguishedName()
加解码部分
from pyasn1.codec.der.encoder import encode
from pyasn1.codec.der.decoder import decode
from pyasn1.debug import hexdump
from schema import *
def X501factory(attribute_list: {str: str}) -> RDNSequence:
rnd = RDNSequence()
for key, value in attribute_list.items():
attrib = AttributeValueAssertion()
attrib[‘attributeType‘] = ObjectIdentifier(key)
attrib[‘attributeValue‘] = PrintableString(value)
relative = RelativeDistinguishedName()
relative.setComponentByPosition(0, attrib)
rnd.append(relative)
return rnd
rnd = X501factory({
‘2.5.4.6‘: ‘US‘,
‘2.5.4.10‘: ‘Exampla Organization‘,
‘2.5.4.3‘: ‘Test User 1‘
})
print(hexdump(encode(rnd)))
received_record, _ = decode(encode(rnd))
print(received_record)
最后结果如下
生成的der和之前手工制作的完全一样,同时成功解析
原文:https://www.cnblogs.com/20175211lyz/p/12769883.html