将ASN.1模式解析为Python代码,并使用每个编码器对其进行编码/解码
asn1PERser的Python项目详细描述
asn1perser
这个库可以将ASN.1文本模式解析为Python代码。每个(对齐的)解码器/编码器包含一个ASN.1,用于解析的模式。
支持的ASN.1类型及其约束是:
ASN.1 Type | Single value | Value range | Value size | can be extended (...) | used Python contraint class |
---|---|---|---|---|---|
INTEGER | X | X | X | ValueRange | |
BOOLEAN | |||||
ENUMERATED | X | ExtensionMarker | |||
BIT STRING | X | X | X | ValueSize | |
OCTET STRING | X | X | X | ValueSize | |
CHOICE | X | ExtensionMarker | |||
SEQUENCE | X | ExtensionMarker | |||
SEQUENCE OF | X | X | X | SequenceOfValueSize |
关于如何使用它们,请看下面的例子。
示例
遵循ASN.1模式:
asn_schema='''\SimpleProtocol DEFINITIONS AUTOMATIC TAGS ::=BEGINSimpleMessage ::= CHOICE { start Start, stop Stop, alive Alive, data Data, ...}Start ::= SEQUENCE { sequenceNumber SequenceNumber, timestamp UTC-Timestamp, srcPort Port, dstPort Port}Stop ::= SEQUENCE { sequenceNumber SequenceNumber, timestamp UTC-Timestamp, srcPort Port, dstPort Port}Alive ::= SEQUENCE { timestamp UTC-Timestamp, ...}Data ::= SEQUENCE { sequenceNumber SequenceNumber, swRelease ENUMERATED {rel1, rel2, rel3, ...}, macroId BIT STRING (SIZE(20)) OPTIONAL, payload Payload}Port ::= INTEGER (10000..65535)SequenceNumber ::= INTEGER (0..65535)UTC-Timestamp ::= SEQUENCE { seconds INTEGER (0..4294967295), useconds INTEGER (0..4294967295)}Payload ::= SEQUENCE (SIZE(1..5)) OF MessageMessage ::= OCTET STRING (SIZE(1..4))END'''
可以解析成如下的python代码:
fromasn1PERserimportparse_asn1_schemaparse_asn1_schema(asn1_schema=asn_schema,output_folder=r'C:/my_code/')
以上代码将在文件夹中创建文件“SimeEffice,Py”(它必须存在)c:/MyOxCult/`:
frompyasn1.type.namedtypeimportNamedType,NamedTypes,OptionalNamedType,DefaultedNamedTypefrompyasn1.type.namedvalimportNamedValuesfromasn1PERser.classes.data.builtinimport*fromasn1PERser.classes.types.typeimportAdditiveNamedTypesfromasn1PERser.classes.types.constraintimportMIN,MAX,NoConstraint,ExtensionMarker,SequenceOfValueSize, \ ValueRange,SingleValue,ValueSize,ConstraintOr,ConstraintAndclassPort(IntegerType):subtypeSpec=ValueRange(10000,65535)classSequenceNumber(IntegerType):subtypeSpec=ValueRange(0,65535)classMessage(OctetStringType):subtypeSpec=ValueSize(1,4)classUTC_Timestamp(SequenceType):classseconds(IntegerType):subtypeSpec=ValueRange(0,4294967295)classuseconds(IntegerType):subtypeSpec=ValueRange(0,4294967295)rootComponent=AdditiveNamedTypes(NamedType('seconds',seconds()),NamedType('useconds',useconds()),)componentType=rootComponentclassStart(SequenceType):rootComponent=AdditiveNamedTypes(NamedType('sequenceNumber',SequenceNumber()),NamedType('timestamp',UTC_Timestamp()),NamedType('srcPort',Port()),NamedType('dstPort',Port()),)componentType=rootComponentclassStop(SequenceType):rootComponent=AdditiveNamedTypes(NamedType('sequenceNumber',SequenceNumber()),NamedType('timestamp',UTC_Timestamp()),NamedType('srcPort',Port()),NamedType('dstPort',Port()),)componentType=rootComponentclassAlive(SequenceType):subtypeSpec=ExtensionMarker(True)rootComponent=AdditiveNamedTypes(NamedType('timestamp',UTC_Timestamp()),)componentType=rootComponentclassPayload(SequenceOfType):subtypeSpec=SequenceOfValueSize(1,5)componentType=Message()classData(SequenceType):classswRelease(EnumeratedType):subtypeSpec=ExtensionMarker(True)enumerationRoot=NamedValues(('rel1',0),('rel2',1),('rel3',2),)namedValues=enumerationRootclassmacroId(BitStringType):subtypeSpec=ValueSize(20,20)rootComponent=AdditiveNamedTypes(NamedType('sequenceNumber',SequenceNumber()),NamedType('swRelease',swRelease()),OptionalNamedType('macroId',macroId()),NamedType('payload',Payload()),)componentType=rootComponentclassSimpleMessage(ChoiceType):subtypeSpec=ExtensionMarker(True)rootComponent=AdditiveNamedTypes(NamedType('start',Start()),NamedType('stop',Stop()),NamedType('alive',Alive()),NamedType('data',Data()),)componentType=rootComponent
当模式被解析时,它可以被使用-消息可以被创建、编码和解码,使用每个编码器/解码器,以字节为单位 或python结构:
fromasn1PERserimportencode,decodefromSimpleProtocolimport*'''simple_message SimpleMessage ::= alive : { timestamp { seconds 1557528149, useconds 12345 }}'''utc_timestamp=UTC_Timestamp()utc_timestamp['seconds']=UTC_Timestamp.seconds(1557528149)utc_timestamp['useconds']=UTC_Timestamp.useconds(12345)msg_alive=Alive()msg_alive['timestamp']=utc_timestampsimple_message=SimpleMessage()simple_message['alive']=msg_aliveper_bytes=encode(asn1Spec=simple_message)print('encoded alive bytes as hex string:')print(per_bytes.hex())print('\n')decoded=decode(per_stream=per_bytes,asn1Spec=SimpleMessage())print('decoded alive message structure as string...:')print(decoded)print('...can be accessed like dictionary:')print(decoded['alive']['timestamp']['seconds'])
以上将输出:
encoded alive bytes as hex string:
4c5cd5fe55403039
alive message structure as string...:
SimpleMessage:
alive=Alive:
timestamp=UTC_Timestamp:
seconds=1557528149
useconds=12345
...can be accessed like dictionary:
1557528149
下一条消息:
'''simple_message SimpleMessage ::= start : { sequenceNumber 10, timestamp { seconds 1557528149, useconds 12345 }, srcPort 65533, dstPort 10000}'''utc_timestamp=UTC_Timestamp()utc_timestamp['seconds']=UTC_Timestamp.seconds(1557528149)utc_timestamp['useconds']=UTC_Timestamp.useconds(12345)msg_start=Start()msg_start['sequenceNumber']=SequenceNumber(10)msg_start['timestamp']=utc_timestampmsg_start['srcPort']=Port(65533)msg_start['dstPort']=Port(10000)simple_message=SimpleMessage()simple_message['start']=msg_startper_bytes=encode(asn1Spec=simple_message)print('encoded start bytes as hex string:')print(per_bytes.hex())print('\n')decoded=decode(per_stream=per_bytes,asn1Spec=SimpleMessage())print('start message structure as string...:')print(decoded)print('...can be accessed like dictionary:')print(decoded['start']['srcPort'])
以上将输出:
encoded start bytes as hex string:
00000ac05cd5fe55403039d8ed0000
start message structure as string...:
SimpleMessage:
start=Start:
sequenceNumber=10
timestamp=UTC_Timestamp:
seconds=1557528149
useconds=12345
srcPort=65533
dstPort=10000
...can be accessed like dictionary:
65533
下一条消息:
'''simple_message SimpleMessage ::= data : { sequenceNumber 55555, swRelease rel2, macroId '11110000111100001111'B, payload { 'DEAD'H, 'BEEF'H, 'FEED'H, 'AA'H, 'BBBBBBBB'H }}'''data_payload=Payload()data_payload.extend([Message(hexValue='DEAD')])data_payload.extend([Message(hexValue='BEEF')])data_payload.extend([Message(hexValue='FEED')])data_payload.extend([Message(hexValue='AA')])data_payload.extend([Message(hexValue='BBBBBBBB')])msg_data=Data()msg_data['sequenceNumber']=SequenceNumber(55555)msg_data['swRelease']=Data.swRelease('rel2')msg_data['macroId']=Data.macroId(binValue='11110000111100001111')msg_data['payload']=data_payloadsimple_message=SimpleMessage()simple_message['data']=msg_dataper_bytes=encode(asn1Spec=simple_message)print('encoded data bytes as hex string:')print(per_bytes.hex())print('\n')decoded=decode(per_stream=per_bytes,asn1Spec=SimpleMessage())print('data message structure as string...:')print(decoded)print('...can be accessed like dictionary:')print(bytes(decoded['data']['payload'][0]).hex())
以上将输出:
encoded data bytes as hex string:
70d90320f0f0f880dead40beef40feed00aac0bbbbbbbb
data message structure as string...:
SimpleMessage:
data=Data:
sequenceNumber=55555
swRelease=rel2
macroId=986895
payload=Payload:
0xdead 0xbeef 0xfeed 0xaa 0xbbbbbbbb
...can be accessed like dictionary:
dead
下一条消息:
'''simple_message SimpleMessage ::= data : { sequenceNumber 256, swRelease rel3, payload { 'DEADBEEF'H }}'''data_payload=Payload()data_payload.extend([Message(hexValue='DEADBEEF')])msg_data=Data()msg_data['sequenceNumber']=SequenceNumber(256)msg_data['swRelease']=Data.swRelease('rel3')msg_data['payload']=data_payloadsimple_message=SimpleMessage()simple_message['data']=msg_dataper_bytes=encode(asn1Spec=simple_message)print('encoded data bytes as hex string:')print(per_bytes.hex())print('\n')decoded=decode(per_stream=per_bytes,asn1Spec=SimpleMessage())print('data message structure as string...:')print(decoded)print('...can be accessed like dictionary:')print(decoded['data']['swRelease'])
以上将输出:
encoded data bytes as hex string:
60010043deadbeef
data message structure as string...:
SimpleMessage:
data=Data:
sequenceNumber=256
swRelease=rel3
payload=Payload:
0xdeadbeef
...can be accessed like dictionary:
rel3
其他信息
有关更多示例,请参见库测试:
- 分析测试,位于test/parsing/folder中。
- 编码/编码测试,位于测试/每个文件夹中。
所有上述示例和测试,使用: https://asn1.io/asn1playground/
这个库广泛地继承了pyasn1库,因此ber和其他编码也应该在这里工作。
解析可能需要时间-当试图解析大约2000行asn.1时,需要15-20分钟。 解析测试也需要时间。