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