encoder.py 3.4 KB

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