• 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和之前手工制作的完全一样,同时成功解析

  • 相关阅读:
    根据中国气象局提供的API接口实现天气查询
    小程序——云函数发送请求
    apifm-wxapi API工厂
    首次使用 linux 阿里云服务器,入门及使用
    Android立体旋转动画实现与封装(支持以X、Y、Z三个轴为轴心旋转)
    Android来电监听和去电监听
    Android 源码下载方法(Git 方式clone)
    HandlerThread 创建一个异步的后台线程
    Android Toast cancel和show 不踩中不会知道的坑
    PopupWindow 点击外部和返回键无法消失背后的真相(setBackgroundDrawable(Drawable background))
  • 原文地址:https://www.cnblogs.com/20175211lyz/p/12769883.html
Copyright © 2020-2023  润新知