You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

encoder.py 3.0KB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #
  2. # This file is part of pyasn1 software.
  3. #
  4. # Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
  5. # License: http://snmplabs.com/pyasn1/license.html
  6. #
  7. from pyasn1 import error
  8. from pyasn1.codec.cer import encoder
  9. from pyasn1.type import univ
  10. __all__ = ['encode']
  11. class SetEncoder(encoder.SetEncoder):
  12. @staticmethod
  13. def _componentSortKey(componentAndType):
  14. """Sort SET components by tag
  15. Sort depending on the actual Choice value (dynamic sort)
  16. """
  17. component, asn1Spec = componentAndType
  18. if asn1Spec is None:
  19. compType = component
  20. else:
  21. compType = asn1Spec
  22. if compType.typeId == univ.Choice.typeId and not compType.tagSet:
  23. if asn1Spec is None:
  24. return component.getComponent().tagSet
  25. else:
  26. # TODO: move out of sorting key function
  27. names = [namedType.name for namedType in asn1Spec.componentType.namedTypes
  28. if namedType.name in component]
  29. if len(names) != 1:
  30. raise error.PyAsn1Error(
  31. '%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', component))
  32. # TODO: support nested CHOICE ordering
  33. return asn1Spec[names[0]].tagSet
  34. else:
  35. return compType.tagSet
  36. tagMap = encoder.tagMap.copy()
  37. tagMap.update({
  38. # Set & SetOf have same tags
  39. univ.Set.tagSet: SetEncoder()
  40. })
  41. typeMap = encoder.typeMap.copy()
  42. typeMap.update({
  43. # Set & SetOf have same tags
  44. univ.Set.typeId: SetEncoder()
  45. })
  46. class Encoder(encoder.Encoder):
  47. fixedDefLengthMode = True
  48. fixedChunkSize = 0
  49. #: Turns ASN.1 object into DER octet stream.
  50. #:
  51. #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
  52. #: walks all its components recursively and produces a DER octet stream.
  53. #:
  54. #: Parameters
  55. #: ----------
  56. #: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
  57. #: A Python or pyasn1 object to encode. If Python object is given, `asnSpec`
  58. #: parameter is required to guide the encoding process.
  59. #:
  60. #: Keyword Args
  61. #: ------------
  62. #: asn1Spec:
  63. #: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
  64. #:
  65. #: Returns
  66. #: -------
  67. #: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
  68. #: Given ASN.1 object encoded into BER octet-stream
  69. #:
  70. #: Raises
  71. #: ------
  72. #: ~pyasn1.error.PyAsn1Error
  73. #: On encoding errors
  74. #:
  75. #: Examples
  76. #: --------
  77. #: Encode Python value into DER with ASN.1 schema
  78. #:
  79. #: .. code-block:: pycon
  80. #:
  81. #: >>> seq = SequenceOf(componentType=Integer())
  82. #: >>> encode([1, 2, 3], asn1Spec=seq)
  83. #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
  84. #:
  85. #: Encode ASN.1 value object into DER
  86. #:
  87. #: .. code-block:: pycon
  88. #:
  89. #: >>> seq = SequenceOf(componentType=Integer())
  90. #: >>> seq.extend([1, 2, 3])
  91. #: >>> encode(seq)
  92. #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
  93. #:
  94. encode = Encoder(tagMap, typeMap)