2011-04-01 27 views
14

我有一些pyOpenSSL給我的數據,'0\r\x82\x0bexample.com'。這應該是subjectAltName X509擴展名的值。我試着用pyasn1編碼這個擴展的ASN1規範的必要部分(基於的pyasn1例子之一):如何使用pyasn1解析subjectAltName擴展數據?

from pyasn1.type import univ, constraint, char, namedtype 

from pyasn1.codec.der.decoder import decode 

MAX = 64 

class DirectoryString(univ.Choice): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType(
      'teletexString', char.TeletexString().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     namedtype.NamedType(
      'printableString', char.PrintableString().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     namedtype.NamedType(
      'universalString', char.UniversalString().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     namedtype.NamedType(
      'utf8String', char.UTF8String().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     namedtype.NamedType(
      'bmpString', char.BMPString().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     namedtype.NamedType(
      'ia5String', char.IA5String().subtype(
       subtypeSpec=constraint.ValueSizeConstraint(1, MAX))), 
     ) 


class AttributeValue(DirectoryString): 
    pass 


class AttributeType(univ.ObjectIdentifier): 
    pass 


class AttributeTypeAndValue(univ.Sequence): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType('type', AttributeType()), 
     namedtype.NamedType('value', AttributeValue()), 
     ) 


class RelativeDistinguishedName(univ.SetOf): 
    componentType = AttributeTypeAndValue() 

class RDNSequence(univ.SequenceOf): 
    componentType = RelativeDistinguishedName() 


class Name(univ.Choice): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType('', RDNSequence()), 
     ) 


class Extension(univ.Sequence): 
    componentType = namedtype.NamedTypes(
     namedtype.NamedType('extnID', univ.ObjectIdentifier()), 
     namedtype.DefaultedNamedType('critical', univ.Boolean('False')), 
     namedtype.NamedType('extnValue', univ.OctetString()), 
     ) 


class Extensions(univ.SequenceOf): 
    componentType = Extension() 
    sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) 


class GeneralName(univ.Choice): 
    componentType = namedtype.NamedTypes(
     # namedtype.NamedType('otherName', AnotherName()), 
     namedtype.NamedType('rfc822Name', char.IA5String()), 
     namedtype.NamedType('dNSName', char.IA5String()), 
     # namedtype.NamedType('x400Address', ORAddress()), 
     namedtype.NamedType('directoryName', Name()), 
     # namedtype.NamedType('ediPartyName', EDIPartyName()), 
     namedtype.NamedType('uniformResourceIdentifier', char.IA5String()), 
     namedtype.NamedType('iPAddress', univ.OctetString()), 
     namedtype.NamedType('registeredID', univ.ObjectIdentifier()), 
     ) 


class GeneralNames(univ.SequenceOf): 
    componentType = GeneralName() 
    sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX) 


class SubjectAltName(GeneralNames): 
    pass 

print decode('0\r\x82\x0bexample.com', asn1Spec=GeneralNames()) 

顯然我接近尾聲時有些無聊,並沒有完全指定GeneralName類型。但是,測試字符串應該包含一個dNSName,而不是其中一個跳過的值,所以我希望它沒有關係。

當程序運行時,出現一個錯誤,我無法解釋:

Traceback (most recent call last): 
    File "x509.py", line 94, in <module> 
    print decode('0\r\x82\x0bexample.com', asn1Spec=GeneralNames()) 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/codec/ber/decoder.py", line 493, in __call__ 
    length, stGetValueDecoder, decodeFun 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/codec/ber/decoder.py", line 202, in valueDecoder 
    substrate, asn1Spec 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/codec/ber/decoder.py", line 453, in __call__ 
    __chosenSpec.getTypeMap().has_key(tagSet): 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/type/univ.py", line 608, in getTypeMap 
    return Set.getComponentTypeMap(self) 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/type/univ.py", line 535, in getComponentTypeMap 
    def getComponentTypeMap(self): return self._componentType.getTypeMap(1) 
    File "/usr/lib/pymodules/python2.6/pyasn1/v1/type/namedtype.py", line 126, in getTypeMap 
    'Duplicate type %s in map %s'%(k,self.__typeMap) 
pyasn1.error.PyAsn1Error: Duplicate type TagSet(Tag(tagClass=0, tagFormat=0, tagId=22)) in map {TagSet(Tag(tagClass=0, tagFormat=0, tagId=22)): IA5String()} 

在哪裏出了錯任何提示,以及如何成功地解析與pyasn1這個擴展型將是非常讚賞。

回答

15

我在pyasn1用戶列表上發佈了這個問題,Ilya Etingof(pyasn1的作者)指出了我的錯誤。簡而言之,每個NamedTypeGeneralName.componentType需要給予標籤信息。這是通過subtype方法完成的。例如,代替:

namedtype.NamedType('rfc822Name', char.IA5String()), 

的定義應該是:

namedtype.NamedType('rfc822Name', char.IA5String().subtype(
     implicitTag=tag.Tag(tag.tagClassContext, 
          tag.tagFormatSimple, 1))), 

其中1來自GeneralName的ASN.1定義:

GeneralName ::= CHOICE { 
    otherName      [0]  OtherName, 
    rfc822Name      [1]  IA5String, 
    dNSName       [2]  IA5String, 
    x400Address      [3]  ORAddress, 
    directoryName     [4]  Name, 
    ediPartyName     [5]  EDIPartyName, 
    uniformResourceIdentifier  [6]  IA5String, 
    iPAddress      [7]  OCTET STRING, 
    registeredID     [8]  OBJECT IDENTIFIER 
} 

限定標籤後對於componentType的這些字段中的每個字段,解析成功:

(GeneralNames().setComponentByPosition(
    0, GeneralName().setComponentByPosition(1, IA5String('example.com'))), '')