# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com> # License: https://pyasn1.readthedocs.io/en/latest/license.html # import io import os import sys import warnings
from pyasn1 import debug from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.codec.streaming import asSeekableStream from pyasn1.codec.streaming import isEndOfStream from pyasn1.codec.streaming import peekIntoStream from pyasn1.codec.streaming import readFromStream from pyasn1.compat import _MISSING from pyasn1.error import PyAsn1Error from pyasn1.type import base from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import tagmap from pyasn1.type import univ from pyasn1.type import useful
class AbstractPayloadDecoder(object):
protoComponent = None
def valueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options): """Decode value with fixed byte length.
The decoder is allowed to consume as many bytes as necessary. """ raise error.PyAsn1Error('SingleItemDecoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?
def indefLenValueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options): """Decode value with undefined length.
The decoder is allowed to consume as many bytes as necessary. """ raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?
while substrate.tell() - current_position < length: for component in decodeFun(
substrate, self.protoComponent, substrateFun=substrateFun,
**options): if isinstance(component, SubstrateUnderrunError): yield component
for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk
return
if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk
oid = ()
index = 0
substrateLen = len(chunk) while index < substrateLen:
subId = chunk[index]
index += 1 if subId < 128:
oid += (subId,) elif subId > 128: # Construct subid from a number of octets
nextSubId = subId
subId = 0 while nextSubId >= 128:
subId = (subId << 7) + (nextSubId & 0x7F) if index >= substrateLen: raise error.SubstrateUnderrunError( 'Short substrate for sub-OID past %s' % (oid,)
)
nextSubId = chunk[index]
index += 1
oid += ((subId << 7) + nextSubId,) elif subId == 128: # ASN.1 spec forbids leading zeros (0x80) in OID # encoding, tolerating it opens a vulnerability. See # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf # page 7 raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
# Decode two leading arcs if0 <= oid[0] <= 39:
oid = (0,) + oid elif40 <= oid[0] <= 79:
oid = (1, oid[0] - 40) + oid[1:] elif oid[0] >= 80:
oid = (2, oid[0] - 80) + oid[1:] else: raise error.PyAsn1Error('Malformed first OID octet: %s' % chunk[0])
while length == -1or substrate.tell() < original_position + length: for component in decodeFun(substrate, **options): if isinstance(component, SubstrateUnderrunError): yield component
if length == -1and component is eoo.endOfOctets: break
# Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF # The heuristics is: # * 1+ components of different types -> likely SEQUENCE/SET # * otherwise -> likely SEQUENCE OF/SET OF if len(componentTypes) > 1:
protoComponent = self.protoRecordComponent
asn1Object = protoComponent.clone( # construct tagSet from base tag from prototype ASN.1 object # and additional tags recovered from the substrate
tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags)
)
if LOG:
LOG('guessed %r container type (pass `asn1Spec` to guide the ' 'decoder)' % asn1Object)
for idx, component in enumerate(components):
asn1Object.setComponentByPosition(
idx, component,
verifyConstraints=False,
matchTags=False, matchConstraints=False
)
yield asn1Object
def valueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options): if tagSet[0].tagFormat != tag.tagFormatConstructed: raise error.PyAsn1Error('Constructed tag format expected')
original_position = substrate.tell()
if substrateFun: if asn1Spec isnotNone:
asn1Object = asn1Spec.clone()
for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk
return
if asn1Spec isNone: for asn1Object in self._decodeComponentsSchemaless(
substrate, tagSet=tagSet, decodeFun=decodeFun,
length=length, **options): if isinstance(asn1Object, SubstrateUnderrunError): yield asn1Object
if substrate.tell() < original_position + length: if LOG: for trailing in readFromStream(substrate, context=options): if isinstance(trailing, SubstrateUnderrunError): yield trailing
if LOG:
LOG('default open types map of component ' '"%s.%s" governed by component "%s.%s"' ':' % (asn1Object.__class__.__name__,
namedType.name,
asn1Object.__class__.__name__,
namedType.openType.name))
for k, v in namedType.openType.items():
LOG('%s -> %r' % (k, v))
for component in decodeFun(stream, asn1Spec=openType, **options): if isinstance(component, SubstrateUnderrunError): yield component
asn1Object.setComponentByPosition(idx, component)
else:
inconsistency = asn1Object.isInconsistent if inconsistency: raise error.PyAsn1Error(
f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")
else:
componentType = asn1Spec.componentType
if LOG:
LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
idx = 0
while substrate.tell() - original_position < length: for component in decodeFun(substrate, componentType, **options): if isinstance(component, SubstrateUnderrunError): yield component
for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk
return
if asn1Spec isNone: for asn1Object in self._decodeComponentsSchemaless(
substrate, tagSet=tagSet, decodeFun=decodeFun,
length=length, **dict(options, allowEoo=True)): if isinstance(asn1Object, SubstrateUnderrunError): yield asn1Object
if LOG:
LOG('default open types map of component ' '"%s.%s" governed by component "%s.%s"' ':' % (asn1Object.__class__.__name__,
namedType.name,
asn1Object.__class__.__name__,
namedType.openType.name))
for k, v in namedType.openType.items():
LOG('%s -> %r' % (k, v))
for component in decodeFun(stream, asn1Spec=openType,
**dict(options, allowEoo=True)): if isinstance(component, SubstrateUnderrunError): yield component
if component is eoo.endOfOctets: break
containerValue[pos] = component
else:
stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()) for component in decodeFun(stream, asn1Spec=openType,
**dict(options, allowEoo=True)): if isinstance(component, SubstrateUnderrunError): yield component
if component is eoo.endOfOctets: break
asn1Object.setComponentByPosition(idx, component)
else:
inconsistency = asn1Object.isInconsistent if inconsistency: raise error.PyAsn1Error(
f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")
else:
componentType = asn1Spec.componentType
if LOG:
LOG('decoding type %r chosen by given `asn1Spec`' % componentType)
idx = 0
whileTrue:
for component in decodeFun(
substrate, componentType, allowEoo=True, **options):
if isinstance(component, SubstrateUnderrunError): yield component
if asn1Object.tagSet == tagSet: if LOG:
LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,))
for component in decodeFun(
substrate, asn1Object.componentTagMap, **options): if isinstance(component, SubstrateUnderrunError): yield component
else: if LOG:
LOG('decoding %s as untagged CHOICE' % (tagSet,))
for component in decodeFun(
substrate, asn1Object.componentTagMap, tagSet, length,
state, **options): if isinstance(component, SubstrateUnderrunError): yield component
effectiveTagSet = component.effectiveTagSet
if LOG:
LOG('decoded component %s, effective tag set %s' % (component, effectiveTagSet))
if LOG: for chunk in peekIntoStream(substrate, length): if isinstance(chunk, SubstrateUnderrunError): yield chunk
LOG('decoding as untagged ANY, substrate ' '%s' % debug.hexdump(chunk))
if substrateFun: for chunk in substrateFun(
self._createComponent(asn1Spec, tagSet, noValue, **options),
substrate, length, options): yield chunk
return
for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk
elif asn1Spec.__class__ is tagmap.TagMap:
isTagged = tagSet in asn1Spec.tagMap
else:
isTagged = tagSet == asn1Spec.tagSet
if isTagged: # tagged Any type -- consume header substrate
chunk = b''
if LOG:
LOG('decoding as tagged ANY')
else: # TODO: Seems not to be tested
fullPosition = substrate.markedPosition
currentPosition = substrate.tell()
substrate.seek(fullPosition, os.SEEK_SET) for chunk in readFromStream(substrate, currentPosition - fullPosition, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk
if LOG:
LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(chunk))
# Any components do not inherit initial tag
asn1Spec = self.protoComponent
if substrateFun and substrateFun isnot self.substrateCollector:
asn1Object = self._createComponent(
asn1Spec, tagSet, noValue, **options)
for chunk in substrateFun(
asn1Object, chunk + substrate, length + len(chunk), options): yield chunk
return
if LOG:
LOG('assembling constructed serialization')
# All inner fragments are of the same type, treat them as octet string
substrateFun = self.substrateCollector
whileTrue: # loop over fragments
for component in decodeFun(
substrate, asn1Spec, substrateFun=substrateFun,
allowEoo=True, **options):
if isinstance(component, SubstrateUnderrunError): yield component
# Put in non-ambiguous types for faster codec lookup for typeDecoder in TAG_MAP.values(): if typeDecoder.protoComponent isnotNone:
typeId = typeDecoder.protoComponent.__class__.typeId if typeId isnotNoneand typeId notin TYPE_MAP:
TYPE_MAP[typeId] = typeDecoder
(stDecodeTag,
stDecodeLength,
stGetValueDecoder,
stGetValueDecoderByAsn1Spec,
stGetValueDecoderByTag,
stTryAsExplicitTag,
stDecodeValue,
stDumpRawValue,
stErrorCondition,
stStop) = [x for x in range(10)]
if isShortTag: # cache short tags
tagCache[firstOctet] = lastTag
if tagSet isNone: if isShortTag: try:
tagSet = tagSetCache[firstOctet]
except KeyError: # base tag not recovered
tagSet = tag.TagSet((), lastTag)
tagSetCache[firstOctet] = tagSet else:
tagSet = tag.TagSet((), lastTag)
else:
tagSet = lastTag + tagSet
state = stDecodeLength
if LOG:
LOG('tag decoded into %s, decoding length' % tagSet)
if state is stDecodeLength: # Decode length for firstOctet in readFromStream(substrate, 1, options): if isinstance(firstOctet, SubstrateUnderrunError): yield firstOctet
firstOctet = ord(firstOctet)
if firstOctet < 128:
length = firstOctet
elif firstOctet > 128:
size = firstOctet & 0x7F # encoded in size bytes for encodedLength in readFromStream(substrate, size, options): if isinstance(encodedLength, SubstrateUnderrunError): yield encodedLength
encodedLength = list(encodedLength) # missing check on maximum size, which shouldn't be a # problem, we can handle more than is possible if len(encodedLength) != size: raise error.SubstrateUnderrunError( '%s<%s at %s' % (size, len(encodedLength), tagSet)
)
length = 0 for lengthOctet in encodedLength:
length <<= 8
length |= lengthOctet
size += 1
else: # 128 means indefinite
length = -1
if length == -1andnot self.supportIndefLength: raise error.PyAsn1Error('Indefinite length encoding not supported by this codec')
state = stGetValueDecoder
if LOG:
LOG('value length decoded into %d' % length)
if state is stGetValueDecoder: if asn1Spec isNone:
state = stGetValueDecoderByTag
else:
state = stGetValueDecoderByAsn1Spec # # There're two ways of creating subtypes in ASN.1 what influences # decoder operation. These methods are: # 1) Either base types used in or no IMPLICIT tagging has been # applied on subtyping. # 2) Subtype syntax drops base type information (by means of # IMPLICIT tagging. # The first case allows for complete tag recovery from substrate # while the second one requires original ASN.1 type spec for # decoding. # # In either case a set of tags (tagSet) is coming from substrate # in an incremental, tag-by-tag fashion (this is the case of # EXPLICIT tag which is most basic). Outermost tag comes first # from the wire. # if state is stGetValueDecoderByTag: try:
concreteDecoder = tagMap[tagSet]
except KeyError:
concreteDecoder = None
if concreteDecoder:
state = stDecodeValue
else: try:
concreteDecoder = tagMap[tagSet[:1]]
except KeyError:
concreteDecoder = None
if concreteDecoder:
state = stDecodeValue else:
state = stTryAsExplicitTag
if LOG:
LOG('codec %s chosen by a built-in type, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or"<none>", state is stDecodeValue and'value'or'as explicit tag'))
debug.scope.push(concreteDecoder isNoneand'?'or concreteDecoder.protoComponent.__class__.__name__)
if state is stGetValueDecoderByAsn1Spec:
if asn1Spec.__class__ is tagmap.TagMap: try:
chosenSpec = asn1Spec[tagSet]
except KeyError:
chosenSpec = None
if LOG:
LOG('candidate ASN.1 spec is a map of:')
for firstOctet, v in asn1Spec.presentTypes.items():
LOG(' %s -> %s' % (firstOctet, v.__class__.__name__))
if asn1Spec.skipTypes:
LOG('but neither of: ') for firstOctet, v in asn1Spec.skipTypes.items():
LOG(' %s -> %s' % (firstOctet, v.__class__.__name__))
LOG('new candidate ASN.1 spec is %s, chosen by %s' % (chosenSpec isNoneand'<none>'or chosenSpec.prettyPrintType(), tagSet))
elif tagSet == asn1Spec.tagSet or tagSet in asn1Spec.tagMap:
chosenSpec = asn1Spec if LOG:
LOG('candidate ASN.1 spec is %s' % asn1Spec.__class__.__name__)
else:
chosenSpec = None
if chosenSpec isnotNone: try: # ambiguous type or just faster codec lookup
concreteDecoder = typeMap[chosenSpec.typeId]
if LOG:
LOG('value decoder chosen for an ambiguous type by type ID %s' % (chosenSpec.typeId,))
except KeyError: # use base type for codec lookup to recover untagged types
baseTagSet = tag.TagSet(chosenSpec.tagSet.baseTag, chosenSpec.tagSet.baseTag) try: # base type or tagged subtype
concreteDecoder = tagMap[baseTagSet]
if LOG:
LOG('value decoder chosen by base %s' % (baseTagSet,))
except KeyError:
concreteDecoder = None
if concreteDecoder:
asn1Spec = chosenSpec
state = stDecodeValue
else:
state = stTryAsExplicitTag
else:
concreteDecoder = None
state = stTryAsExplicitTag
if LOG:
LOG('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or"<none>", state is stDecodeValue and'value'or'as explicit tag'))
debug.scope.push(chosenSpec isNoneand'?'or chosenSpec.__class__.__name__)
if state is stDecodeValue: ifnot options.get('recursiveFlag', True) andnot substrateFun: # deprecate this def substrateFun(asn1Object, _substrate, _length, _options): """Legacy hack to keep the recursiveFlag=False option supported.
The decode(..., substrateFun=userCallback) option was introduced in0.1.4as a generalization
of the old recursiveFlag=False option. Users should pass their callback instead of using
recursiveFlag. """ yield asn1Object
original_position = substrate.tell()
if length == -1: # indef length for value in concreteDecoder.indefLenValueDecoder(
substrate, asn1Spec,
tagSet, length, stGetValueDecoder,
self, substrateFun, **options): if isinstance(value, SubstrateUnderrunError): yield value
else: for value in concreteDecoder.valueDecoder(
substrate, asn1Spec,
tagSet, length, stGetValueDecoder,
self, substrateFun, **options): if isinstance(value, SubstrateUnderrunError): yield value
bytesRead = substrate.tell() - original_position ifnot substrateFun and bytesRead != length: raise PyAsn1Error( "Read %s bytes instead of expected %s." % (bytesRead, length)) elif substrateFun and bytesRead > length: # custom substrateFun may be used for partial decoding, reading less is expected there raise PyAsn1Error( "Read %s bytes are more than expected %s." % (bytesRead, length))
if LOG:
LOG('codec %s yields type %s, value:\n%s\n...' % (
concreteDecoder.__class__.__name__, value.__class__.__name__,
isinstance(value, base.Asn1Item) and value.prettyPrint() or value))
state = stStop break
if state is stTryAsExplicitTag: if (tagSet and
tagSet[0].tagFormat == tag.tagFormatConstructed and
tagSet[0].tagClass != tag.tagClassUniversal): # Assume explicit tagging
concreteDecoder = rawPayloadDecoder
state = stDecodeValue
else:
concreteDecoder = None
state = self.defaultErrorState
if LOG:
LOG('codec %s chosen, decoding %s' % (concreteDecoder and concreteDecoder.__class__.__name__ or"<none>", state is stDecodeValue and'value'or'as failure'))
if state is stDumpRawValue:
concreteDecoder = self.defaultRawDecoder
if LOG:
LOG('codec %s chosen, decoding value' % concreteDecoder.__class__.__name__)
state = stDecodeValue
if state is stErrorCondition: raise error.PyAsn1Error( '%s not in asn1Spec: %r' % (tagSet, asn1Spec)
)
if LOG:
debug.scope.pop()
LOG('decoder left scope %s, call completed' % debug.scope)
yield value
class StreamingDecoder(object): """Create an iterator that turns BER/CER/DER byte stream into ASN.1 objects.
On each iteration, consume whatever BER/CER/DER serialization is
available in the `substrate` stream-like object and turns it into
one or more, possibly nested, ASN.1 objects.
Parameters
----------
substrate: :py:class:`file`, :py:class:`io.BytesIO`
BER/CER/DER serialization in form of a byte stream
Keyword Args
------------
asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item`
A pyasn1 type object to act as a template guiding the decoder.
Depending on the ASN.1 structure being decoded, `asn1Spec` may or may not be required. One of the reasons why `asn1Spec` may
me required is that ASN.1 structure is encoded in the *IMPLICIT*
tagging mode.
Yields
------
: :py:class:`~pyasn1.type.base.PyAsn1Item`, :py:class:`~pyasn1.error.SubstrateUnderrunError`
Decoded ASN.1 object (possibly, nested) or
:py:class:`~pyasn1.error.SubstrateUnderrunError` object indicating
insufficient BER/CER/DER serialization on input to fully recover ASN.1
objects from it.
In the latter case the caller is advised to ensure some more data in
the input stream, then call the iterator again. The decoder will resume
the decoding process using the newly arrived data.
The `context` property of :py:class:`~pyasn1.error.SubstrateUnderrunError`
object might hold a reference to the partially populated ASN.1 object
being reconstructed.
Raises
------
~pyasn1.error.PyAsn1Error, ~pyasn1.error.EndOfStreamError
`PyAsn1Error` on deserialization error, `EndOfStreamError` on
premature stream closure.
Examples
--------
Decode BER serialisation without ASN.1 schema
.. code-block:: pycon
>>> stream = io.BytesIO(
... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
>>>
>>> for asn1Object in StreamingDecoder(stream):
... print(asn1Object)
>>>
SequenceOf: 123
@classmethod def __call__(cls, substrate, asn1Spec=None, **options): """Turns BER/CER/DER octet stream into an ASN.1 object.
Takes BER/CER/DER octet-stream in form of :py:class:`bytes` and decode it into an ASN.1 object
(e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
may be a scalar or an arbitrary nested structure.
Parameters
----------
substrate: :py:class:`bytes`
BER/CER/DER octet-stream to parse
Keyword Args
------------
asn1Spec: :py:class:`~pyasn1.type.base.PyAsn1Item`
A pyasn1 type object (:py:class:`~pyasn1.type.base.PyAsn1Item`
derivative) to act as a template guiding the decoder.
Depending on the ASN.1 structure being decoded, `asn1Spec` may or
may not be required. Most common reason for it to require is that
ASN.1 structure is encoded in *IMPLICIT* tagging mode.
substrateFun: :py:class:`Union[
Callable[[pyasn1.type.base.PyAsn1Item, bytes, int],
Tuple[pyasn1.type.base.PyAsn1Item, bytes]],
Callable[[pyasn1.type.base.PyAsn1Item, io.BytesIO, int, dict],
Generator[Union[pyasn1.type.base.PyAsn1Item,
pyasn1.error.SubstrateUnderrunError], None, None]]
]`
User callback meant to generalize special use cases like non-recursive or
partial decoding. A 3-arg non-streaming variant is supported for backwards
compatiblilty in addition to the newer 4-arg streaming variant.
The callback will receive the uninitialized object recovered from substrate as1st argument, the uninterpreted payload as2nd argument, and the length
of the uninterpreted payload as3rd argument. The streaming variant will
additionally receive the decode(..., **options) kwargs as4th argument.
The non-streaming variant shall return an object that will be propagated as decode() return value as1st item, and the remainig payload for further
decode passes as2nd item.
The streaming variant shall yield an object that will be propagated as
decode() return value, and leave the remaining payload in the stream.
Returns
-------
: :py:class:`tuple`
A tuple of :py:class:`~pyasn1.type.base.PyAsn1Item` object
recovered from BER/CER/DER substrate and the unprocessed trailing
portion of the `substrate` (may be empty)
Raises
------
: :py:class:`~pyasn1.error.PyAsn1Error`
:py:class:`~pyasn1.error.SubstrateUnderrunError` on insufficient
input or :py:class:`~pyasn1.error.PyAsn1Error` on decoding error.
Examples
--------
Decode BER/CER/DER serialisation without ASN.1 schema
def substrateFunWrapper(asn1Object, substrate, length, options=None): """Support both 0.4 and 0.5 style APIs.
substrateFun API has changed in0.5for use with streaming decoders. To stay backwards compatible,
we first tryif we received a streaming user callback. If that fails,we assume we've received a
non-streaming v0.4 user callback and convert it for streaming on the fly """ try:
substrate_gen = origSubstrateFun(asn1Object, substrate, length, options) except TypeError as _value: if _value.__traceback__.tb_next: # Traceback depth > 1 means TypeError from inside user provided function raise # invariant maintained at Decoder.__call__ entry assert isinstance(substrate, io.BytesIO) # nosec assert_used
substrate_gen = Decoder._callSubstrateFunV4asV5(origSubstrateFun, asn1Object, substrate, length) for value in substrate_gen: yield value
#: Turns BER octet stream into an ASN.1 object. #: #: Takes BER octet-stream and decode it into an ASN.1 object #: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which #: may be a scalar or an arbitrary nested structure. #: #: Parameters #: ---------- #: substrate: :py:class:`bytes` #: BER octet-stream #: #: Keyword Args #: ------------ #: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure #: being decoded, *asn1Spec* may or may not be required. Most common reason for #: it to require is that ASN.1 structure is encoded in *IMPLICIT* tagging mode. #: #: Returns #: ------- #: : :py:class:`tuple` #: A tuple of pyasn1 object recovered from BER substrate (:py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: and the unprocessed trailing portion of the *substrate* (may be empty) #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error, ~pyasn1.error.SubstrateUnderrunError #: On decoding errors #: #: Notes #: ----- #: This function is deprecated. Please use :py:class:`Decoder` or #: :py:class:`StreamingDecoder` class instance. #: #: Examples #: -------- #: Decode BER serialisation without ASN.1 schema #: #: .. code-block:: pycon #: #: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') #: >>> str(s) #: SequenceOf: #: 1 2 3 #: #: Decode BER serialisation with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) #: >>> str(s) #: SequenceOf: #: 1 2 3 #:
decode = Decoder()
def __getattr__(attr: str): if newAttr := {"tagMap": "TAG_MAP", "typeMap": "TYPE_MAP"}.get(attr):
warnings.warn(f"{attr} is deprecated. Please use {newAttr} instead.", DeprecationWarning) return globals()[newAttr] raise AttributeError(attr)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.