Как создать GeneralName с pyasn1? - PullRequest
0 голосов
/ 26 февраля 2020

Будучи довольно новым для pyasn1 (pyasn1 0.4.8, pyasn1-modules 0.2.8) и ASN.1 в целом, я пытаюсь создать GeneralName:

>>> from pyasn1.codec.der.encoder import encode
>>> from pyasn1.type import char
>>> from pyasn1_modules import rfc2459
>>> from pyasn1_modules.rfc2459 import (
...     AttributeTypeAndValue, GeneralName, Name, RelativeDistinguishedName, RDNSequence)
>>> 
>>> rdn = RelativeDistinguishedName()
>>> attr_type_and_value = AttributeTypeAndValue()
>>> attr_type_and_value['type'] = rfc2459.id_at_countryName
>>> attr_type_and_value['value'] = encode(char.UTF8String('DE'))
>>> rdn.append(attr_type_and_value)
>>> 
>>> rdn_sequence = RDNSequence()
>>> rdn_sequence.append(rdn)
>>> 
>>> name = Name()
>>> name[0] = rdn_sequence
>>> 
>>> general_name = GeneralName()
>>> general_name['directoryName'] = name
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/pyasn1/type/univ.py", line 2246, in __setitem__
    self.setComponentByName(idx, value)
  File "/usr/lib/python3.6/site-packages/pyasn1/type/univ.py", line 2413, in setComponentByName
    idx, value, verifyConstraints, matchTags, matchConstraints
  File "/usr/lib/python3.6/site-packages/pyasn1/type/univ.py", line 3119, in setComponentByPosition
    Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints)
  File "/usr/lib/python3.6/site-packages/pyasn1/type/univ.py", line 2601, in setComponentByPosition
    raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType))
pyasn1.error.PyAsn1Error: Component value is tag-incompatible: <Name value object, tagSet=<TagSet object, untagged>, [...]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/pyasn1/type/univ.py", line 2250, in __setitem__
    raise KeyError(sys.exc_info()[1])
KeyError: PyAsn1Error('Component value is tag-incompatible: <Name value object, tagSet=<TagSet object, untagged>, [...]

Я обрезал очень длинные сообщения об исключениях. Суть в том, насколько я понимаю, в том, что предоставленный объект Name не тегирован, в то время как ожидаются определенные теги. Я могу обойти исключение, используя general_name.setComponentByName('directoryName', name, matchTags=False), но я не уверен, что это просто отключит желаемую / важную проверку и укусит меня позже. Документация pyasn1 Tag и TagSet не просветила меня, но это возможно потому, что я не совсем понял назначение тегов в ASN.1.

Итак, мой главный вопрос: как Я правильно создаю GeneralName с pyasn1? Подвопросы:

  • Какова цель тегов в ASN.1? Я думал о них как о спецификаторах типов (например: «это целое число, логическое значение, последовательность и т. Д. c.»), Но, по-видимому, я что-то упускаю.
  • Я использую UTF8String. Расшифровывая ответ с отметкой времени, созданный с помощью OpenSSL, я обнаружил, что PrintableString использовался в GeneralName. Я интуитивно выбрал первое, но может ли это привести к проблеме (в зависимости от контекста использования)?

1 Ответ

1 голос
/ 27 февраля 2020

Я думаю, что это ошибка или ограничение pyasn1

Интересно, связано ли это с этим: https://github.com/etingof/pyasn1/issues/179

spe c говорит

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}

Name            ::=   CHOICE { -- only one possibility for now --
                                 rdnSequence  RDNSequence }

RDNSequence     ::=   SEQUENCE OF RelativeDistinguishedName

В ASN.1 обычно есть этап компиляции, который генерирует некоторый код. С pyasn1 вы либо пишете код самостоятельно, либо включаете некоторые модули.

Поскольку вы включаете pyasn1_modules.rfc2459 , единственная работа - использовать классы.

Ваше написание выглядит очень законно

>>> rdn_sequence = RDNSequence()
>>> rdn_sequence.append(rdn)
>>> 
>>> name = Name()
>>> name[0] = rdn_sequence
>>> 
>>> general_name = GeneralName()
>>> general_name['directoryName'] = name

Но кажется, что pyasn1 разрешает только сокращенный доступ

>>> rdn_sequence = RDNSequence()
>>> rdn_sequence.append(rdn)
>>> 
>>> general_name = GeneralName()
>>> general_name['directoryName'][''] = rdn_sequence

Я думаю, что оба должны быть разрешены ...

Что касается тегов : поскольку вы используете модули pyasn1, вам не нужно беспокоиться о них. Они необходимы для кодирования сообщений, когда формой кодирования является Tag / Length / Value (правила кодирования BER, CER и DER ASN.1).

Что касается типов (например, UTF8String): вы можете ' Чтобы изменить их, они должны быть типами, которые вы прочитали из Спецификации ASN.1. С ними связан (так называемый универсальный) тег, и получатель не поймет ваше закодированное сообщение.

Обратите внимание, что между реализацией Name и spe c есть небольшое расхождение (spe c имеет именованный тип, а реализация не имеет имени). Это было позволено в старину.

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

Но я не думаю, что это проблема.

...