pyasn1解析asn1


pyasn1

https://github.com/etingof/pyasn1
pyasn1文檔

這是一個作為Python包的ASN.1類型和編解碼器的免費開源實現。它最初是為了支持特定的協議(SNMP)而編寫的,但后來被推廣為適用於基於ASN.1規范的各種協議。

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.encoderpyasn1.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和之前手工制作的完全一樣,同時成功解析


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM