【问题标题】:How to model recursive ASN.1 specs using PyASN1?如何使用 PyASN1 对递归 ASN.1 规范进行建模?
【发布时间】:2013-07-04 11:01:55
【问题描述】:

PKCS#15 中有一个结构在CommonObjectAttributes 中描述了访问对象的规则。令我非常懊恼的是,它是递归的,也就是说,它可以包含自己:

SecurityCondition ::= CHOICE {
    authId Identifier,
    not [0] SecurityCondition,
    and [1] SEQUENCE SIZE (2..pkcs15-ub-securityConditions) OF SecurityCondition,
    or  [2] SEQUENCE SIZE (2..pkcs15-ub-securityConditions) OF SecurityCondition,
    ... -- For future extensions
}

我对如何使用 pyasn1 建模感到困惑。我想我可以强加一个固定级别的递归并简单地让它们相互依赖,但在我看来这不是一个非常有吸引力的解决方案。有没有人有更好的主意?

更新

通过省略SecurityCondition 的定义来测试 Ilya Etingofs 方法,起初我得到了这个:

 class SecurityCondition(univ.Choice):
    pass

securityConditionComponentType = namedtype.NamedTypes(
        namedtype.NamedType('authId', univ.OctetString().subtype(
            subtypeSpec=constraint.ValueSizeConstraint(0, univ.Integer(255)))
        ),
        namedtype.NamedType('not', SecurityCondition().subtype(
            implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)
            )
        ),
        namedtype.NamedType('and', univ.SequenceOf(componentType=SecurityCondition).subtype(
            #implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1),
            #subtypeSpec=constraint.ValueSizeConstraint(2, univ.Integer(255))
            )
        ),
        namedtype.NamedType('or', univ.SequenceOf(componentType=SecurityCondition).subtype(
            #implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2),
            #subtypeSpec=constraint.ValueSizeConstraint(2, univ.Integer(255))
            )
        )
    )
SecurityCondition.componentType = securityConditionComponentType

示例用法:

# Example usage
inner = univ.SequenceOf()
inner.setComponentByPosition(0, SecurityCondition().setComponentByName("authId", "\x02"))
inner.setComponentByPosition(1, SecurityCondition().setComponentByName("authId", "\x03"))

outer = univ.SequenceOf()
outer.setComponentByPosition(0, SecurityCondition().setComponentByName("authId", "\x01"))
outer.setComponentByPosition(1, SecurityCondition().setComponentByName("or", inner))

wrapper = SecurityCondition().setComponentByName("and", outer)

如果不使用子类型规范或隐式标签,它似乎可以工作:

>>> print wrapper.prettyPrint()
SecurityCondition:
 and=SequenceOf:
  SecurityCondition:
   authId=0x01
  SecurityCondition:
   or=SequenceOf:
    SecurityCondition:
     authId=0x02
    SecurityCondition:
     authId=0x03

SEQUENCE(2 elem)
    OCTET STRING(2 byte) 01
    SEQUENCE(2 elem)
        OCTET STRING(1 byte) 02
        OCTET STRING(1 byte) 03

如果 implicitTagsubtypeSpec 未注释错误

PyAsn1Error: Component type error SequenceOf() vs
SequenceOf().setComponentByPosition(0, SecurityCondition().setComponentByPosition(0,
     OctetString(hexValue='02'))).setComponentByPosition(1,
     SecurityCondition().setComponentByPosition(0, OctetString(hexValue='03')))

发生。巧合的是,如果尝试固定数量的递归,我会遇到同样的错误。

【问题讨论】:

    标签: python asn.1


    【解决方案1】:

    好的,我之前的 hack 并没有真正奏效。更新为更激进的 hack:

    class SecurityCondition(univ.Choice):
        componentType = namedtype.NamedTypes(
            namedtype.NamedType('authId', univ.OctetString().subtype(subtypeSpec=constraint.ValueSizeConstraint(0, 255))),
            namedtype.NamedType('not', univ.Any()),  # just a placeholder
            namedtype.NamedType('and', univ.Any()),  # just a placeholder
            namedtype.NamedType('or', univ.Any())    # just a placeholder
        )
    
    SecurityCondition.componentType[1]._NamedType__type = SecurityCondition().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))
    SecurityCondition.componentType[2]._NamedType__type =  univ.SequenceOf(componentType=SecurityCondition()).subtype(implicitTag=tag.Tag(tag.tagClass.ontext, tag.tagFormatSimple, 1), subtypeSpec=constraint.ValueSizeConstraint(2, 255))
    SecurityCondition.componentType[3]._NamedType__type =  univ.SequenceOf(componentType=SecurityCondition()).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2), subtypeSpec=constraint.ValueSizeConstraint(2, 255))
    
    # Initialize an instance of SecurityCondition
    
    top = SecurityCondition() # SecurityCondition
    top['and'] = None         # SecurityCondition->SequenceOf
    top['and'][0] = None      # SecurityCondition->SequenceOf->SecurityCondition
    top['and'][0]['authId'] = "\x02"
    top['and'][1] = None      # SecurityCondition->SequenceOf->SecurityCondition
    top['and'][1]['authId'] = "\x03"
    
    print(top.prettyPrint())
    

    是的,这很丑陋并且会创建循环引用。从好的方面来说,它似乎有效。

    【讨论】:

    • 问题是当它还不是一个完整的类时,SecurityCondition 在 componentType 规范中被实例化。所以虽然我为你的想法喝彩,但我看不到它有效:)
    • 无论如何我都进行了测试,并且在使用subtypeSpecimplicitTag 时它一直有效。您是否发现示例中的代码有任何错误?
    • 酷!它不漂亮,但它似乎对编码和解码都有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2021-05-17
    • 2023-04-02
    • 2014-07-09
    相关资源
    最近更新 更多