././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2954316 pyasn1-0.6.1/0000755000175000017500000000000014670145404013206 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726005917.0 pyasn1-0.6.1/CHANGES.rst0000644000175000017500000011205414670141235015011 0ustar00spichugispichugiRevision 0.6.1, released 10-09-2024 --------------------------------------- - Added support for Python 3.13 and updated GitHub Actions [pr #73](https://github.com/pyasn1/pyasn1/pull/73/) - Removed Python 2 support and related code [pr #62](https://github.com/pyasn1/pyasn1/pull/62/) [pr #61](https://github.com/pyasn1/pyasn1/pull/61/) [pr #60](https://github.com/pyasn1/pyasn1/pull/60/) - Improved error handling and consistency [pr #71](https://github.com/pyasn1/pyasn1/pull/71/) [pr #70](https://github.com/pyasn1/pyasn1/pull/70/) - Runtime deprecation of `tagMap` and `typeMap` aliases [pr #72](https://github.com/pyasn1/pyasn1/pull/72/) - Fixed duplicated and missing declarations [pr #64](https://github.com/pyasn1/pyasn1/pull/64/) - Cleaned documentation and comments [pr #63](https://github.com/pyasn1/pyasn1/pull/63/) - Removed bdist_wheel universal flag from setup.cfg [pr #69](https://github.com/pyasn1/pyasn1/pull/69/) Revision 0.6.0, released 26-03-2024 --------------------------------------- - Added support for previously missing `RELATIVE-OID` construct [pr #48](https://github.com/pyasn1/pyasn1/pull/48/) - Updated link to Layman's Guide Now it provides a link to links to a formatted PDF version of the paper, at a stable domain (researchgate), using https [pr #50](https://github.com/pyasn1/pyasn1/pull/50/) - Removed support for EOL Python 2.7, 3.6, 3.7 [pr #56](https://github.com/pyasn1/pyasn1/pull/56/) Revision 0.5.1, released 20-11-2023 --------------------------------------- - Added support for PyPy 3.10 and Python 3.12 [pr #32](https://github.com/pyasn1/pyasn1/pull/32/) - Updated RTD configuration to include a dummy index.rst redirecting to contents.html, ensuring compatibility with third-party documentation and search indexes. [pr #47](https://github.com/pyasn1/pyasn1/pull/47/) - Fixed the API breakage wih decoder.decode(substrateFun=...). A substrateFun passed to ``decoder.decode()`` can now be either v0.4 Non-Streaming or v0.5 Streaming. pyasn1 will detect and handle both cases transparently. A substrateFun passed to one of the new streaming decoders is still expected to be v0.5 Streaming only. [pr #30](https://github.com/pyasn1/pyasn1/pull/30/) [pr #39](https://github.com/pyasn1/pyasn1/pull/39/) Revision 0.5.0, released 19-04-2023 --------------------------------------- - Change `RealEncoder.supportIndefLenMode` type to a boolean [pr #21](https://github.com/pyasn1/pyasn1/pull/21/) - Fix CI for py39 test environment [pr #25](https://github.com/pyasn1/pyasn1/pull/25/) - Replace all snmplabs.com links [issue #4](https://github.com/pyasn1/pyasn1/issues/4) - Use correct SPDX identifier for the license [pr #16](https://github.com/pyasn1/pyasn1/pull/16) - Re-add ``tagMap`` and ``typeMap`` module level attributes to all encoder and decoder modules. They are aliases for ``TAG_MAP`` and ``TYPE_MAP``, [issue #9](https://github.com/pyasn1/pyasn1/issues/9). - Restore API for passing for ``tagMap`` and ``typeMap`` arguments to ``Encoder`` and ``Decoder`` classes by name and position, [issue #12](https://github.com/pyasn1/pyasn1/issues/12). - Re-add ``tagMap`` and ``typeMap`` module level attributes to all encoder and decoder modules. They are aliases for ``TAG_MAP`` and ``TYPE_MAP``, [issue #9](https://github.com/pyasn1/pyasn1/issues/9). - Restore API for passing for ``tagMap`` and ``typeMap`` arguments to ``Encoder`` and ``Decoder`` classes by name and position, - Make BER/CER/DER decoders streaming and suspendible The goal of this change is to make the decoder yielding on input data starvation and resuming from where it stopped whenever the caller decides to try again (hopefully making sure that some more input becomes available). This change makes it possible for the decoder to operate on streams of data (meaning that the entire DER blob might not be immediately available on input). On top of that, the decoder yields partially reconstructed ASN.1 object on input starvation making it possible for the caller to inspect what has been decoded so far and possibly consume partial ASN.1 data. All these new feature are natively available through `StreamingDecoder` class. Previously published API is implemented as a thin wrapper on top of that ensuring backward compatibility. - Added support for Python 3.8, 3.9, 3.10, 3.11 - Removed support for EOL Pythons 2.4, 2.5, 2.6, 3.2, 3.3, 3.4, 3.5 - Added support for PyPy 3.7, 3.8, 3.9 - Modernized packaging and testing. pyasn1 now uses ``setup.cfg``, ``pyproject.toml``, [build](https://pypi.org/project/build/), and GitHub Actions. - PyPI package ownership for `pyasn1` and `pyasn1-module` has been transfered to *Christian Heimes* and *Simon Pichugin* in [PyPI support ticket #2090](https://github.com/pypa/pypi-support/issues/2090). - The upstream repositories for `pyasn1` and `pyasn1-modules` are now in the GitHub organization https://github.com/pyasn1/. Revision 0.4.8, released 16-11-2019 ----------------------------------- - Added ability of combining `SingleValueConstraint` and `PermittedAlphabetConstraint` objects into one for proper modeling `FROM ... EXCEPT ...` ASN.1 clause. Revision 0.4.7, released 01-09-2019 ----------------------------------- - Added `isInconsistent` property to all constructed types. This property conceptually replaces `verifySizeSpec` method to serve a more general purpose e.g. ensuring all required fields are in a good shape. By default this check invokes subtype constraints verification and is run by codecs on value de/serialisation. - Deprecate `subtypeSpec` attributes and keyword argument. It is now recommended to pass `ValueSizeConstraint`, as well as all other constraints, to `subtypeSpec`. - Fixed a design bug in a way of how the items assigned to constructed types are verified. Now if `Asn1Type`-based object is assigned, its compatibility is verified based on having all tags and constraint objects as the type in field definition. When a bare Python value is assigned, then field type object is cloned and initialized with the bare value (constraints verificaton would run at this moment). - Added `WithComponentsConstraint` along with related `ComponentPresentConstraint` and `ComponentAbsentConstraint` classes to be used with `Sequence`/`Set` types representing `SET ... WITH COMPONENTS ...` like ASN.1 constructs. Revision 0.4.6, released 31-07-2019 ----------------------------------- - Added previously missing `SET OF ANY` construct encoding/decoding support. - Added `omitEmptyOptionals` option which is respected by `Sequence` and `Set` encoders. When `omitEmptyOptionals` is set to `True`, empty initialized optional components are not encoded. Default is `False`. - New elements to `SequenceOf`/`SetOf` objects can now be added at any position - the requirement for the new elements to reside at the end of the existing ones (i.e. s[len(s)] = 123) is removed. - List-like slicing support added to `SequenceOf`/`SetOf` objects. - Removed default initializer from `SequenceOf`/`SetOf` types to ensure consistent behaviour with the rest of ASN.1 types. Before this change, `SequenceOf`/`SetOf` instances immediately become value objects behaving like an empty list. With this change, `SequenceOf`/`SetOf` objects remain schema objects unless a component is added or `.clear()` is called. This change can potentially cause incompatibilities with existing pyasn1 objects which assume `SequenceOf`/`SetOf` instances are value objects right upon instantiation. The behaviour of `Sequence`/`Set` types depends on the `componentType` initializer: if on `componentType` is given, the behaviour is the same as `SequenceOf`/`SetOf` have. IF `componentType` is given, but neither optional nor defaulted components are present, the created instance remains schema object, If, however, either optional or defaulted component isi present, the created instance immediately becomes a value object. - Added `.reset()` method to all constructed types to turn value object into a schema object. - Added `PyAsn1UnicodeDecodeError`/`PyAsn1UnicodeDecodeError` exceptions to help the caller treating unicode errors happening internally to pyasn1 at the upper layers. - Added support for subseconds CER/DER encoding edge cases in `GeneralizedTime` codec. - Fixed 3-digit fractional seconds value CER/DER encoding of `GeneralizedTime`. - Fixed `AnyDecoder` to accept possible `TagMap` as `asn1Spec` to make dumping raw value operational Revision 0.4.5, released 29-12-2018 ----------------------------------- - Debug logging refactored for more efficiency when disabled and for more functionality when in use. Specifically, the global LOG object can easily be used from any function/method, not just from codec main loop as it used to be. - More debug logging added to BER family of codecs to ease encoding problems troubleshooting. - Copyright notice extended to the year 2019 - Fixed defaulted constructed SEQUENCE component initialization. Revision 0.4.4, released 26-07-2018 ----------------------------------- - Fixed native encoder type map to include all ASN.1 types rather than just ambiguous ones - Fixed crash in `.prettyPrint` of `Sequence` and `Set` occurring at OPTIONAL components Revision 0.4.3, released 23-05-2018 ----------------------------------- - Copyright notice extended to the year 2018 - Fixed GeneralizedTime.asDateTime to perform milliseconds conversion correctly Revision 0.4.2, released 23-11-2017 ----------------------------------- - Fixed explicit tag splitting in chunked encoding mode at OctetString and BitString encoders Revision 0.4.1, released 23-11-2017 ----------------------------------- - ANY DEFINED BY clause support implemented - Encoders refactored to take either a value (as ASN.1 object) or a Python value plus ASN.1 schema - BitString decoder optimised for better performance when running on constructed encoding - Constructed types' .getComponentBy*() methods accept the `default` parameter to return instead if schema object is to be returned - Constructed types' .getComponentBy*() methods accept the `instantiate` parameter to disable automatic inner component instantiation - The ASN.1 types' `__repr__` implementation reworked for better readability at the cost of not being `eval`-compliant - Most ASN.1 types' `__str__` magic methods (except for OctetString and character types) reworked to call `.prettyPrint()` rather than `.prettyPrint` calling `__str__` as it was before. The intention is to eventually deprecate `.prettyPrint()` in favor of `str()`. The other related change is that `str()` of enumerations and boolean types will return string label instead of number. - Fixed Choice.clear() to fully reset internal state of the object - Sphinx documentation rearranged, simplified and reworded - The `isValue` singleton is now the only way to indicate ASN.1 schema as opposed to ASN.1 schema instance. The legacy `None` initializer support has been removed. - Changed `Null` object initialization behaviour: previous default value (`''`) is not set anymore. Thus `Null()` call produces a ASN.1 schema object, while `Null('')` - value object. - Migrated all docs and references from SourceForge - Imports PEP8'ed - Fixed ASN.1 encoder not to omit empty substrate produced for inner component if the inner component belongs to the simple class (as opposed to constructed class) - Fixed CER/DER encoders to respect tagged CHOICE when ordering SET components - Fixed ASN.1 types not to interfere with the Pickle protocol - Fixed Sequence/SequenceOf types decoding heuristics in schema-less decoding mode Revision 0.3.7, released 04-10-2017 ----------------------------------- - Fixed ASN.1 time types pickling/deepcopy'ing Revision 0.3.6, released 21-09-2017 ----------------------------------- - End-of-octets encoding optimized at ASN.1 encoders - The __getitem__/__setitem__ behavior of Set/Sequence and SetOf/SequenceOf objects aligned with the canonical Mapping and Sequence protocols in part - Fixed crash in ASN.1 encoder when encoding an explicitly tagged component of a Sequence Revision 0.3.5, released 16-09-2017 ----------------------------------- - Codecs signatures unified and pass the options kwargs through the call chain - Explicit tag encoding optimized to avoid unnecessary copying - End-of-octets sentinel encoding optimized - Refactored ASN.1 codecs properties to silently enforce proper length and chunk size encoding modes - Fixed DER encoder to always produce primitive encoding - Fixed crash at SequenceOf native decoder - Fixed Real.prettyPrint() to fail gracefully on overflow - Fixed a couple of crashes when debug mode is enabled Revision 0.3.4, released 07-09-2017 ----------------------------------- - Fixed Native encoder to handle SEQUENCE/SET objects without the componentType property - Added missing component-less SEQUENCE/SET objects dict duck-typing support - Fixed unnecessary duplicate tags detection at NamesType.tagMap - Fixed crash at SEQUENCE and SEQUENCE OF CER encoder when running in schemaless mode - Fixed Character types instantiation from OctetString type -- double unicode decoding may have scrambled the data Revision 0.3.3, released 27-08-2017 ----------------------------------- - Improved ASN.1 types instantiation performance - Improved BER/CER/DER decoder performance by not unconditionally casting substrate into str/bytes. - Fixed exponential index size growth bug when building ambiguous NamedTypes tree - Fixed constructed types decoding failure at BER codec if running in schema-less mode - Fixed crash on prettyPrint'ing a SEQUENCE with no defined components - Fixed SetOf ordering at CER/DER encoder - Fixed crash on conditional binascii module import - Fix to TagSet hash value build Revision 0.3.2, released 04-08-2017 ----------------------------------- - Fixed SequenceOf/SetOf types initialization syntax to remain backward compatible with pyasn1 0.2.* - Rectified thread safety issues by moving lazy, run-time computation into object initializer. - Fixed .isValue property to return True for empty SetOf/SequenceOf objects - Fixed GeneralizedTime/UTCTime CER/DER codecs to actually get invoked - Fixed DER/CER encoders handling optional SEQUENCE/SET fields containing nested SEQUENCE/SET with optional fields. - Fixed crash in SequenceOf/SetOf pretty printing and decoding (in some cases) - Fixed documentation markup issues. Revision 0.3.1, released 26-07-2017 ----------------------------------- - ASN.1 types __init__(), .clone() and .subtype() signatures refactored into keyword arguments to simplify their signatures. - ASN.1 types initialization refactored to minimize the use of relatively expensive isNoValue() call - Lazily pre-populate list of values of Sequence/Set/Choice types - NamedTypes comparison made more efficient - More efficient constraints computation and code clean up - The __getitem__() implementation of some ASN.1 types & tag object refactored for better performance - BER/CER/DER value encoders refactored to produce either tuple of bytes or octet-stream depending on what is more optimal - Reduced the frequency of expensive isinstance() calls - Tag-related classes optimized, refactored into properties and documented. - The NamedValues implementation refactored to mimic Python dict, its use in ASN.1 types refactored into properties and better documented. WARNING: this change introduces a deviation from original API. - NamedType family of classes overhauled, optimized and documented. - The `componentType` attribute of constructed ASN.1 types turned read-only on instances. - Sequence/Set DER/CER/DER decoder optimized to skip the case of reordered components handling when not necessary. - Tags and constraints-related getter methods refactored into read-only instance attributes. - The .hasValue() method refactored into .isValue property. All ASN.1 objects now support them, not just scalars. - The Real.{isInfinity, isPlusInfinity, isMinusInfinity} methods refactored into properties and renamed into IsInf, IsPlusInf and isMinusInf - The end-of-octets type refactored to ensure it is a singleton. Codecs changed to rely on that for better performance. - Codecs lookup made more efficient at BER/CER/DER decoder main loop by assigning `typeId` to every ASN.1 type, not just ambiguous ones. - The .getComponent*() methods of constructed ASN.1 types changed to lazily instantiate underlying type rather than return `None`. This should simplify its API as initialization like `X[0][1] = 2` becomes possible. WARNING: this change introduces a deviation from the original API. - The .setComponent*() methods of SetOf/SequenceOf types changed not to allow uninitialized "holes" inside the sequences of their components. They now behave similarly to Python lists. WARNING: this change introduces a deviation from the original API. - Default and optional components en/decoding of Constructed type refactored towards better efficiency and more control. - OctetsString and Any decoder optimized to avoid creating ASN.1 objects for chunks of substrate. Instead they now join substrate chunks together and create ASN.1 object from it just once. - The GeneralizedTime and UTCTime types now support to/from Python datetime object conversion. - Unit tests added for the `compat` sub-package. - Fixed BitString named bits initialization bug. - Fixed non-functional tag cache (when running Python 2) at DER decoder. - Fixed chunked encoding restriction on DER encoder. - Fixed SET components ordering at DER encoder. - Fixed BIT STRING & OCTET STRING encoding to be always non-chunked (e.g. primitive) at DER encoder - Fixed `compat.integer.from_bytes()` behaviour on empty input. Revision 0.2.3, released 25-02-2017 ----------------------------------- - Improved SEQUENCE/SET/CHOICE decoding performance by maintaining a single shared NamedType object for all instances of SEQUENCE/SET object. - Improved INTEGER encoding/decoding by switching to Python's built-in integer serialisation functions. - Improved BitString performance by rebasing it onto Python int type and leveraging fast Integer serialisation functions. - BitString type usability improved in many ways: for example bitshifting and numeric operation on BitString is now possible. - Minor ObjectIdentifier type performance optimization. - ASN.1 character types refactored to keep unicode contents internally (rather than serialised octet stream) and duck-type it directly. - ASN.1 OctetString initialized from a Python object performs bytes() on it when running on Python 3 (used to do str() which is probably less logical). - Missing support for NoValue.__sizeof__ added. - Added checks to make sure SEQUENCE/SET components being assigned match the prototypes. - Setter methods for constructed types consistently accept matchTags and matchConstraints flags to control the strictness of inner components compatibility verification. Previously, these checks were tied to verifyConstraints flag, now they are all independent. - General documentation improvements here and there. - Fix to __reversed__() magic to make it returning an iterator. - Test suite simplified and unified. - The __all__ variable added to most of the Python modules. - The "test" directory renamed into "tests" not to collide with the "test" module. Revision 0.2.2, released 07-02-2017 ----------------------------------- - FIX TO A SECURITY WEAKNESS: define length only decoders could have successfully processed indefinite length serialisation. - FIX TO A SECURITY WEAKNESS: canonical decoders (CER/DER) may have successfully consumed non-canonical variations of (otherwise valid) serialisation. - Broken Enumerated subtyping fixed. Revision 0.2.1, released 05-02-2017 ----------------------------------- - FIX TO A SECURITY WEAKNESS: BER decoder improperly cached long tags. - New "native" codec implemented to transform pyasn1 types to Python built-in types and back. - Switched to new-style classes. - Sphinx documentation added. - BitString improvements: * simple string of binary digits is now supported as initializer * default str() yields string of binary digits (used to yield str(tuple()) * binValue and hexValue initializers added * .asNumbers(), .asOctets() and asInteger() representation added - Components of constructed ASN.1 types can now be populated with uninitialized ASN.1 objects by assigning either noValue sentinel or setupComponent() function return in addition to now-legacy None sentinel. This should improve code readability. - NoValue class improved to become a singleton and catch more kinds of access to it. - Compatibility wrappers str2octs() and oct2strs() fixed to run over iso-8859-1 encoding. - Integer changed to emit Real instance if division produces a float. - True division operation now supported by Integer type. - The __contains__(), __reverse__() methods implemented for container types - Iterator protocol support implemented for all container types. Warning, warning, warning: this change may potentially affect backward compatibility when: * user class overrides __getitem__() without overriding __iter__() * when user code iterates over SEQUENCE object to get its components (now keys will be yielded) - Almost complete Python list and dict protocols added to SequenceOf/SetOf and Sequence/Set respectively - Fix to divmod operation implementation in Integer type. - Fix to IntegerDecoder's precomputed value map on Python 3. - Fix to base ASN.1 types to run in "unicode_literals" mode. - Fix to composite constraints "+" operands ordering (AbstractConstraintSet.__radd__) - Fix to constraints merge in .subtype() -- on merge existing constraints are expanded to accommodate new constraints, not the other way round. When existing constraints are wrapped in ConstraintsIntersection composite, additional constraints being added on subtyping effectively further narrow the set of allowed values, which aligns well with the notion of subtyping. - Fix to NamedTypes methods to handle .getTagMap() returning None - Fix to Set/Sequence.setDefaultComponents() to return self - Copyright notice added to non-trivial source code files. - Author's email changed, copyright extended to 2017 Revision 0.1.9, released 28-09-2015 ----------------------------------- - Wheel distribution format now supported. - Extensions added to text files, CVS attic flushed. - Fix to make uninitialized pyasn1 objects failing properly on hash(). - Fix to ObjectIdentifier initialization from unicode string. - Fix to CER/DER Boolean decoder - fail on non single-octet payload. Revision 0.1.8, released 22-06-2015 ----------------------------------- - ObjectIdentifier codec fixed to work properly with arc 0 and arc 2 values. - Explicit limit on ObjectIdentifier arc value size removed. - Unicode initializer support added to OctetString type and derivatives. - New prettyPrintType() abstract method implemented to base pyasn1 types to facilitate encoding errors analysis. - The __str__() method implemented to Tag, TagSet and TagMap classes to ease encoding errors troubleshooting. easing encoding errors - Fix to SEQUENCE and SET types to give them their private componentTypes collection (which is a NamedTypes object) so that they won't collide in a MT execution environment. - Missing T61String,ISO646String character types and ObjectDescriptor useful type added. - Distribute is gone, switched to setuptools completely. - Missing NamedValues.__repr__() added. - The base.NoValue() class, that indicates uninitialized ASN.1 object, made public. - The base.NoValue() class instances now support __repr__() what makes possible to perform repr() on uninitialized pyasn1 types objects. - When comparing ASN.1 types, by-tag and/or by-constraints matching can now be performed with the isSuperTypeOf()/isSameTypeWith() optional flags. - Constructed types now verify their consistency by invoking isSameTypeWith(matchTags=True, matchConstraints=False) and isSuperTypeOf(matchTags=False, matchConstraints=True) for each of their components rather than isSuperTypeOf() as it used to be. Constriants check could be enforced to isSameTypeWith() with the strictConstraints=True constructed classes attribute. - Constructed types can now be initialized with new .setComponents() method which accepts both var-args and keyword-args. Default repr() modified to reflect this change. - NamedTypes() and NamedValues() made comparable. - Test coverage extended to cover pyasn1 types __repr__() function. - The abs(Integer()) & abs(Real()) operation now returns respective pyasn1 type, not a Python type. - More Python magic methods implementations added to Integer & Real classes (e.g. __pos__, __neg__, __round__, __floor__, __ceil__, __trunc__) - The Integer.__invert__ Python magic method implemented. - The OctetString.__int__() and .__float__() magic methods implemented. - Handle the case of null writer at Debug printer. - BitString encoder/decoder performance improved. - Built-in debugging is now based on Python logging module. - Fix to NamedType.__repr__() to work properly. - Fixes to __repr__() implementation of many built-in ASN.1 types to take into account all of their initializers such as tagSet, subtypeSpec etc. - String typed float initializer to REAL type now supported. - Float typed mantissa initializer to REAL type for base 2 added. - Encoding bases 8 and 16 support for REAL type binary encoder added. - More strict CER/DER encoders added for GeneralizedTime and UTCTime types. - Asn1Item.hasValue() added to easily distinguish initalized ASN.1 objects from uninitialized ones (e.g. pure types). - Fix to REAL type binary decoder to handle different bases and scale factor. - Fix to TagSet.repr() to include [obsolete] baseTag information. - Fix to broken REAL type decoding handling. - Fix to BitString and OctetString decoders dealing with constructed encoding -- it used to be possible to embed other types in substrate. - DER codec hardened not to tolerate indefinite length encoding/decoding. - Fix to end-of-octest sentinel handling: + require strict two-zeros sentinel encoding + recognize EOO sentinel only when explicitly requested by caller of the decoder via allowEoo=True parameter (warning: API change) Revision 0.1.7 -------------- - License updated to vanilla BSD 2-Clause to ease package use (https://opensource.org/licenses/BSD-2-Clause). - Test suite made discoverable by unittest/unittest2 discovery feature. - Fix to decoder working on indefinite length substrate -- end-of-octets marker is now detected by both tag and value. Otherwise zero values may interfere with end-of-octets marker. - Fix to decoder to fail in cases where tagFormat indicates inappropriate format for the type (e.g. BOOLEAN is always PRIMITIVE, SET is always CONSTRUCTED and OCTET STRING is either of the two) - Fix to REAL type encoder to force primitive encoding form encoding. - Fix to CHOICE decoder to handle explicitly tagged, indefinite length mode encoding - Fix to REAL type decoder to handle negative REAL values correctly. Test case added. Revision 0.1.6 -------------- - The compact (valueless) way of encoding zero INTEGERs introduced in 0.1.5 seems to fail miserably as the world is filled with broken BER decoders. So we had to back off the *encoder* for a while. There's still the IntegerEncoder.supportCompactZero flag which enables compact encoding form whenever it evaluates to True. - Report package version on debugging code initialization. Revision 0.1.5 -------------- - Documentation updated and split into chapters to better match web-site contents. - Make prettyPrint() working for non-initialized pyasn1 data objects. It used to throw an exception. - Fix to encoder to produce empty-payload INTEGER values for zeros - Fix to decoder to support empty-payload INTEGER and REAL values - Fix to unit test suites imports to be able to run each from their current directory Revision 0.1.4 -------------- - Built-in codec debugging facility added - Added some more checks to ObjectIdentifier BER encoder catching posible 2^8 overflow condition by two leading sub-OIDs - Implementations overriding the AbstractDecoder.valueDecoder method changed to return the rest of substrate behind the item being processed rather than the unprocessed substrate within the item (which is usually empty). - Decoder's recursiveFlag feature generalized as a user callback function which is passed an uninitialized object recovered from substrate and its uninterpreted payload. - Catch inappropriate substrate type passed to decoder. - Expose tagMap/typeMap/Decoder objects at DER decoder to uniform API. - Obsolete __init__.MajorVersionId replaced with __init__.__version__ which is now in-sync with distutils. - Package classifiers updated. - The __init__.py's made non-empty (rumors are that they may be optimized out by package managers). - Bail out gracefully whenever Python version is older than 2.4. - Fix to Real codec exponent encoding (should be in 2's complement form), some more test cases added. - Fix in Boolean truth testing built-in methods - Fix to substrate underrun error handling at ObjectIdentifier BER decoder - Fix to BER Boolean decoder that allows other pre-computed values besides 0 and 1 - Fix to leading 0x80 octet handling in DER/CER/DER ObjectIdentifier decoder. See https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf Revision 0.1.3 -------------- - Include class name into asn1 value constraint violation exception. - Fix to OctetString.prettyOut() method that looses leading zero when building hex string. Revision 0.1.2 -------------- - Fix to __long__() to actually return longs on py2k - Fix to OctetString.__str__() workings of a non-initialized object. - Fix to quote initializer of OctetString.__repr__() - Minor fix towards ObjectIdentifier.prettyIn() reliability - ObjectIdentifier.__str__() is aliased to prettyPrint() - Exlicit repr() calls replaced with '%r' Revision 0.1.1 -------------- - Hex/bin string initializer to OctetString object reworked (in a backward-incompatible manner) - Fixed float() infinity compatibility issue (affects 2.5 and earlier) - Fixed a bug/typo at Boolean CER encoder. - Major overhawl for Python 2.4 -- 3.2 compatibility: + get rid of old-style types + drop string module usage + switch to rich comparation + drop explicit long integer type use + map()/filter() replaced with list comprehension + apply() replaced with \*/\*\*args + switched to use 'key' sort() callback function + support both __nonzero__() and __bool__() methods + modified not to use py3k-incompatible exception syntax + getslice() operator fully replaced with getitem() + dictionary operations made 2K/3K compatible + base type for encoding substrate and OctetString-based types is now 'bytes' when running py3k and 'str' otherwise + OctetString and derivatives now unicode compliant. + OctetString now supports two python-neutral getters: asOcts() & asInts() + print OctetString content in hex whenever it is not printable otherwise + in test suite, implicit relative import replaced with the absolute one + in test suite, string constants replaced with numerics Revision 0.0.13 --------------- - Fix to base10 normalization function that loops on univ.Real(0) Revision 0.0.13b ---------------- - ASN.1 Real type is now supported properly. - Objects of Constructed types now support __setitem__() - Set/Sequence objects can now be addressed by their field names (string index) and position (integer index). - Typo fix to ber.SetDecoder code that prevented with schema decoding operation. - Fix to explicitly tagged items decoding support. - Fix to OctetString.prettyPrint() to better handle non-printable content. - Fix to repr() workings of Choice objects. Revision 0.0.13a ---------------- - Major codec re-design. - Documentation significantly improved. - ASN.1 Any type is now supported. - All example ASN.1 modules moved to separate pyasn1-modules package. - Fix to initial sub-OID overflow condition detection an encoder. - BitString initialization value verification improved. - The Set/Sequence.getNameByPosition() method implemented. - Fix to proper behaviour of PermittedAlphabetConstraint object. - Fix to improper Boolean substrate handling at CER/DER decoders. - Changes towards performance improvement: + all dict.has_key() & dict.get() invocations replaced with modern syntax (this breaks compatibility with Python 2.1 and older). + tag and tagset caches introduced to decoder + decoder code improved to prevent unnecessary pyasn1 objects creation + allow disabling components verification when setting components to structured types, this is used by decoder whilst running with schema mode. + BER decoder for integer values now looks up a small set of pre-computed substrate values to save on decoding. + a few pre-computed values configured to ObjectIdentifier BER encoder. + ChoiceDecoder split-off SequenceOf one to save on unnecessary checks. + replace slow hasattr()/getattr() calls with isinstance() introspection. + track the number of initialized components of Constructed types to save on default/optional components initialization. + added a shortcut ObjectIdentifier.asTuple() to be used instead of __getitem__() in hotspots. + use Tag.asTuple() and pure integers at tag encoder. + introduce and use in decoder the baseTagSet attribute of the built-in ASN.1 types. Revision 0.0.12a ---------------- - The individual tag/length/value processing methods of encoder.AbstractItemEncoder renamed (leading underscore stripped) to promote overloading in cases where partial substrate processing is required. - The ocsp.py, ldap.py example scripts added. - Fix to univ.ObjectIdentifier input value handler to disallow negative sub-IDs. Revision 0.0.11a ---------------- - Decoder can now treat values of unknown types as opaque OctetString. - Fix to Set/SetOf type decoder to handle uninitialized scalar SetOf components correctly. Revision 0.0.10a ---------------- - API versioning mechanics retired (pyasn1.v1 -> pyasn1) what makes it possible to zip-import pyasn1 sources (used by egg and py2exe). Revision 0.0.9a --------------- - Allow any non-zero values in Boolean type BER decoder, as it's in accordnance with the standard. Revision 0.0.8a --------------- - Integer.__index__() now supported (for Python 2.5+). - Fix to empty value encoding in BitString encoder, test case added. - Fix to SequenceOf decoder that prevents it skipping possible Choice typed inner component. - Choice.getName() method added for getting currently set component name. - OctetsString.prettyPrint() does a single str() against its value eliminating an extra quotes. Revision 0.0.7a --------------- - Large tags (>31) now supported by codecs. - Fix to encoder to properly handle explicitly tagged untagged items. - All possible value lengths (up to 256^126) now supported by encoders. - Fix to Tag class constructor to prevent negative IDs. Revision 0.0.6a --------------- - Make use of setuptools. - Constraints derivation verification (isSuperTypeOf()/isSubTypeOf()) fixed. - Fix to constraints comparation logic -- can't cmp() hash values as it may cause false positives due to hash conflicts. Revision 0.0.5a --------------- - Integer BER codec reworked fixing negative values encoding bug. - clone() and subtype() methods of Constructed ASN.1 classes now accept optional cloneValueFlag flag which controls original value inheritance. The default is *not* to inherit original value for performance reasons (this may affect backward compatibility). Performance penalty may be huge on deeply nested Constructed objects re-creation. - Base ASN.1 types (pyasn1.type.univ.*) do not have default values anymore. They remain uninitialized acting as ASN.1 types. In this model, initialized ASN.1 types represent either types with default value installed or a type instance. - Decoders' prototypes are now class instances rather than classes. This is to simplify initial value installation to decoder's prototype value. - Bugfix to BitString BER decoder (trailing bits not regarded). - Bugfix to Constraints use as mapping keys. - Bugfix to Integer & BitString clone() methods - Bugix to the way to distinguish Set from SetOf at CER/DER SetOfEncoder - Adjustments to make it running on Python 1.5. - In tests, substrate constants converted from hex escaped literals into octals to overcome indefinite hex width issue occuring in young Python. - Minor performance optimization of TagSet.isSuperTagSetOf() method - examples/sshkey.py added Revision 0.0.4a --------------- * Asn1Type.prettyPrinter() -> \*.prettyPrint() Revision 0.0.3a --------------- * Simple ASN1 objects now hash to their Python value and don't depend upon tag/constraints/etc. * prettyIn & prettyOut methods of SimplleAsn1Object become public * many syntax fixes Revision 0.0.2a --------------- * ConstraintsIntersection.isSuperTypeOf() and ConstraintsIntersection.hasConstraint() implemented * Bugfix to NamedValues initialization code * +/- operators added to NamedValues objects * Integer.__abs__() & Integer.subtype() added * ObjectIdentifier.prettyOut() fixes * Allow subclass components at SequenceAndSetBase * AbstractConstraint.__cmp__() dropped * error.Asn1Error replaced with error.PyAsn1Error Revision 0.0.1a --------------- * Initial public alpha release ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707975790.0 pyasn1-0.6.1/LICENSE.rst0000644000175000017500000000246614563322156015034 0ustar00spichugispichugiCopyright (c) 2005-2020, Ilya Etingof All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/MANIFEST.in0000644000175000017500000000022214525242621014736 0ustar00spichugispichugiinclude *.rst *.md recursive-include tests *.py recursive-include docs Makefile *.rst *.svg conf.py prune docs/build prune docs/source/.templates ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2954316 pyasn1-0.6.1/PKG-INFO0000644000175000017500000002027714670145404014313 0ustar00spichugispichugiMetadata-Version: 2.1 Name: pyasn1 Version: 0.6.1 Summary: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) Home-page: https://github.com/pyasn1/pyasn1 Author: Ilya Etingof Author-email: etingof@gmail.com Maintainer: pyasn1 maintenance organization Maintainer-email: Christian Heimes License: BSD-2-Clause Project-URL: Documentation, https://pyasn1.readthedocs.io Project-URL: Source, https://github.com/pyasn1/pyasn1 Project-URL: Issues, https://github.com/pyasn1/pyasn1/issues Project-URL: Changelog, https://pyasn1.readthedocs.io/en/latest/changelog.html Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Education Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: Intended Audience :: Telecommunications Industry Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Communications Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/markdown License-File: LICENSE.rst ASN.1 library for Python ------------------------ [![PyPI](https://img.shields.io/pypi/v/pyasn1.svg?maxAge=2592000)](https://pypi.org/project/pyasn1) [![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1.svg)](https://pypi.org/project/pyasn1/) [![Build status](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml/badge.svg)](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml) [![Coverage Status](https://img.shields.io/codecov/c/github/pyasn1/pyasn1.svg)](https://codecov.io/github/pyasn1/pyasn1) [![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/pyasn1/pyasn1/master/LICENSE.txt) This is a free and open source implementation of ASN.1 types and codecs as a Python package. It has been first written to support particular protocol (SNMP) but then generalized to be suitable for a wide range of protocols based on [ASN.1 specification](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items). **NOTE:** The package is now maintained by *Christian Heimes* and *Simon Pichugin* in project https://github.com/pyasn1/pyasn1. Features -------- * Generic implementation of ASN.1 types (X.208) * Standards compliant BER/CER/DER codecs * Can operate on streams of serialized data * Dumps/loads ASN.1 structures from Python types * 100% Python, works with Python 3.8+ * MT-safe * Contributed ASN.1 compiler [Asn1ate](https://github.com/kimgr/asn1ate) Why using pyasn1 ---------------- ASN.1 solves the data serialisation problem. This solution was designed long ago by the wise Ancients. Back then, they did not have the luxury of wasting bits. That is why ASN.1 is designed to serialise data structures of unbounded complexity into something compact and efficient when it comes to processing the data. That probably explains why many network protocols and file formats still rely on the 30+ years old technology. Including a number of high-profile Internet protocols and file formats. Quite a number of books cover the topic of ASN.1. [Communication between heterogeneous systems](http://www.oss.com/asn1/dubuisson.html) by Olivier Dubuisson is one of those high quality books freely available on the Internet. The pyasn1 package is designed to help Python programmers tackling network protocols and file formats at the comfort of their Python prompt. The tool struggles to capture all aspects of a rather complicated ASN.1 system and to represent it on the Python terms. How to use pyasn1 ----------------- With pyasn1 you can build Python objects from ASN.1 data structures. For example, the following ASN.1 data structure: ```bash Record ::= SEQUENCE { id INTEGER, room [0] INTEGER OPTIONAL, house [1] INTEGER DEFAULT 0 } ``` Could be expressed in pyasn1 like this: ```python class Record(Sequence): componentType = NamedTypes( NamedType('id', Integer()), OptionalNamedType( 'room', Integer().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 0) ) ), DefaultedNamedType( 'house', Integer(0).subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 1) ) ) ) ``` It is in the spirit of ASN.1 to take abstract data description and turn it into a programming language specific form. Once you have your ASN.1 data structure expressed in Python, you can use it along the lines of similar Python type (e.g. ASN.1 `SET` is similar to Python `dict`, `SET OF` to `list`): ```python >>> record = Record() >>> record['id'] = 123 >>> record['room'] = 321 >>> str(record) Record: id=123 room=321 >>> ``` Part of the power of ASN.1 comes from its serialisation features. You can serialise your data structure and send it over the network. ```python >>> from pyasn1.codec.der.encoder import encode >>> substrate = encode(record) >>> hexdump(substrate) 00000: 30 07 02 01 7B 80 02 01 41 ``` Conversely, you can turn serialised ASN.1 content, as received from network or read from a file, into a Python object which you can introspect, modify, encode and send back. ```python >>> from pyasn1.codec.der.decoder import decode >>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record()) >>> >>> for field in received_record: >>> print('{} is {}'.format(field, received_record[field])) id is 123 room is 321 house is 0 >>> >>> record == received_record True >>> received_record.update(room=123) >>> substrate = encode(received_record) >>> hexdump(substrate) 00000: 30 06 02 01 7B 80 01 7B ``` The pyasn1 classes struggle to emulate their Python prototypes (e.g. int, list, dict etc.). But ASN.1 types exhibit more complicated behaviour. To make life easier for a Pythonista, they can turn their pyasn1 classes into Python built-ins: ```python >>> from pyasn1.codec.native.encoder import encode >>> encode(record) {'id': 123, 'room': 321, 'house': 0} ``` Or vice-versa -- you can initialize an ASN.1 structure from a tree of Python objects: ```python >>> from pyasn1.codec.native.decoder import decode >>> record = decode({'id': 123, 'room': 321, 'house': 0}, asn1Spec=Record()) >>> str(record) Record: id=123 room=321 >>> ``` With ASN.1 design, serialisation codecs are decoupled from data objects, so you could turn every single ASN.1 object into many different serialised forms. As of this moment, pyasn1 supports BER, DER, CER and Python built-ins codecs. The extremely compact PER encoding is expected to be introduced in the upcoming pyasn1 release. More information on pyasn1 APIs can be found in the [documentation](https://pyasn1.readthedocs.io/en/latest/pyasn1/contents.html), compiled ASN.1 modules for different protocols and file formats could be found in the pyasn1-modules [repo](https://github.com/pyasn1/pyasn1-modules). How to get pyasn1 ----------------- The pyasn1 package is distributed under terms and conditions of 2-clause BSD [license](https://pyasn1.readthedocs.io/en/latest/license.html). Source code is freely available as a GitHub [repo](https://github.com/pyasn1/pyasn1). You could `pip install pyasn1` or download it from [PyPI](https://pypi.org/project/pyasn1). If something does not work as expected, [open an issue](https://github.com/epyasn1/pyasn1/issues) at GitHub or post your question [on Stack Overflow](https://stackoverflow.com/questions/ask) or try browsing pyasn1 [mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/). Copyright (c) 2005-2020, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004984.0 pyasn1-0.6.1/README.md0000644000175000017500000001467014670137370014500 0ustar00spichugispichugi ASN.1 library for Python ------------------------ [![PyPI](https://img.shields.io/pypi/v/pyasn1.svg?maxAge=2592000)](https://pypi.org/project/pyasn1) [![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1.svg)](https://pypi.org/project/pyasn1/) [![Build status](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml/badge.svg)](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml) [![Coverage Status](https://img.shields.io/codecov/c/github/pyasn1/pyasn1.svg)](https://codecov.io/github/pyasn1/pyasn1) [![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/pyasn1/pyasn1/master/LICENSE.txt) This is a free and open source implementation of ASN.1 types and codecs as a Python package. It has been first written to support particular protocol (SNMP) but then generalized to be suitable for a wide range of protocols based on [ASN.1 specification](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items). **NOTE:** The package is now maintained by *Christian Heimes* and *Simon Pichugin* in project https://github.com/pyasn1/pyasn1. Features -------- * Generic implementation of ASN.1 types (X.208) * Standards compliant BER/CER/DER codecs * Can operate on streams of serialized data * Dumps/loads ASN.1 structures from Python types * 100% Python, works with Python 3.8+ * MT-safe * Contributed ASN.1 compiler [Asn1ate](https://github.com/kimgr/asn1ate) Why using pyasn1 ---------------- ASN.1 solves the data serialisation problem. This solution was designed long ago by the wise Ancients. Back then, they did not have the luxury of wasting bits. That is why ASN.1 is designed to serialise data structures of unbounded complexity into something compact and efficient when it comes to processing the data. That probably explains why many network protocols and file formats still rely on the 30+ years old technology. Including a number of high-profile Internet protocols and file formats. Quite a number of books cover the topic of ASN.1. [Communication between heterogeneous systems](http://www.oss.com/asn1/dubuisson.html) by Olivier Dubuisson is one of those high quality books freely available on the Internet. The pyasn1 package is designed to help Python programmers tackling network protocols and file formats at the comfort of their Python prompt. The tool struggles to capture all aspects of a rather complicated ASN.1 system and to represent it on the Python terms. How to use pyasn1 ----------------- With pyasn1 you can build Python objects from ASN.1 data structures. For example, the following ASN.1 data structure: ```bash Record ::= SEQUENCE { id INTEGER, room [0] INTEGER OPTIONAL, house [1] INTEGER DEFAULT 0 } ``` Could be expressed in pyasn1 like this: ```python class Record(Sequence): componentType = NamedTypes( NamedType('id', Integer()), OptionalNamedType( 'room', Integer().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 0) ) ), DefaultedNamedType( 'house', Integer(0).subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 1) ) ) ) ``` It is in the spirit of ASN.1 to take abstract data description and turn it into a programming language specific form. Once you have your ASN.1 data structure expressed in Python, you can use it along the lines of similar Python type (e.g. ASN.1 `SET` is similar to Python `dict`, `SET OF` to `list`): ```python >>> record = Record() >>> record['id'] = 123 >>> record['room'] = 321 >>> str(record) Record: id=123 room=321 >>> ``` Part of the power of ASN.1 comes from its serialisation features. You can serialise your data structure and send it over the network. ```python >>> from pyasn1.codec.der.encoder import encode >>> substrate = encode(record) >>> hexdump(substrate) 00000: 30 07 02 01 7B 80 02 01 41 ``` Conversely, you can turn serialised ASN.1 content, as received from network or read from a file, into a Python object which you can introspect, modify, encode and send back. ```python >>> from pyasn1.codec.der.decoder import decode >>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record()) >>> >>> for field in received_record: >>> print('{} is {}'.format(field, received_record[field])) id is 123 room is 321 house is 0 >>> >>> record == received_record True >>> received_record.update(room=123) >>> substrate = encode(received_record) >>> hexdump(substrate) 00000: 30 06 02 01 7B 80 01 7B ``` The pyasn1 classes struggle to emulate their Python prototypes (e.g. int, list, dict etc.). But ASN.1 types exhibit more complicated behaviour. To make life easier for a Pythonista, they can turn their pyasn1 classes into Python built-ins: ```python >>> from pyasn1.codec.native.encoder import encode >>> encode(record) {'id': 123, 'room': 321, 'house': 0} ``` Or vice-versa -- you can initialize an ASN.1 structure from a tree of Python objects: ```python >>> from pyasn1.codec.native.decoder import decode >>> record = decode({'id': 123, 'room': 321, 'house': 0}, asn1Spec=Record()) >>> str(record) Record: id=123 room=321 >>> ``` With ASN.1 design, serialisation codecs are decoupled from data objects, so you could turn every single ASN.1 object into many different serialised forms. As of this moment, pyasn1 supports BER, DER, CER and Python built-ins codecs. The extremely compact PER encoding is expected to be introduced in the upcoming pyasn1 release. More information on pyasn1 APIs can be found in the [documentation](https://pyasn1.readthedocs.io/en/latest/pyasn1/contents.html), compiled ASN.1 modules for different protocols and file formats could be found in the pyasn1-modules [repo](https://github.com/pyasn1/pyasn1-modules). How to get pyasn1 ----------------- The pyasn1 package is distributed under terms and conditions of 2-clause BSD [license](https://pyasn1.readthedocs.io/en/latest/license.html). Source code is freely available as a GitHub [repo](https://github.com/pyasn1/pyasn1). You could `pip install pyasn1` or download it from [PyPI](https://pypi.org/project/pyasn1). If something does not work as expected, [open an issue](https://github.com/epyasn1/pyasn1/issues) at GitHub or post your question [on Stack Overflow](https://stackoverflow.com/questions/ask) or try browsing pyasn1 [mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/). Copyright (c) 2005-2020, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/TODO.rst0000644000175000017500000000365714525242621014516 0ustar00spichugispichugi Things to be done ================= Big things to tackle, anyone interested is welcome to fork pyasn1, work on it and come up with a PR! New codecs ---------- * PER * OER * XER * LWER * JSON (alinged with existing experimental schemas) Lazy codecs ----------- Implement a thin layer over base types to cache pieces of substrate being decoded till the very moment of ASN.1 object access in the parse tree. Codecs generator interface -------------------------- For indefinite length or chunked encoding mode, make codecs iterable producing/consuming substrate/objects. ASN.1 schema compiler --------------------- Ideally, the compiler should parse modern schema files and be designed to emit code for arbitrary languages (including SQL). Base types ---------- Implement X.680 constructs, including information schema. Examples -------- Add examples, including advanced/obscure use cases. Documentation ------------- Document more API, add notes and example snippets. More fresh modules ------------------ Compile and ship more Pythonized ASN.1 modules for various ASN.1-based protocols (e.g. Kerberos etc). Refresh outdated modules in pyasn1-packages. Minor, housekeeping things -------------------------- * more PEP8'ing at places * consider simplifying repr(), otherwise it tend to be too hard to grasp * Specialize ASN.1 character and useful types * ber.decoder: * suspend codec on underrun error ? * present subtypes ? * component presence check wont work at innertypeconst * type vs value, defaultValue * ber.encoder: * Asn1Item.clone() / shallowcopy issue * large length encoder? * lookup type by tag first to allow custom codecs for non-base types * type.useful: * may need to implement prettyIn/Out * type.char: * may need to implement constraints * type.namedtypes * type vs tagset name convention * how untagged TagSet should be initialized? * type and codecs for Real needs refactoring ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2704315 pyasn1-0.6.1/docs/0000755000175000017500000000000014670145404014136 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/Makefile0000644000175000017500000001637214525242621015605 0ustar00spichugispichugi# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " coverage to run coverage check of the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyASN1.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyASN1.qhc" applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp @echo @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." @echo "N.B. You won't be able to view it unless you put it in" \ "~/Library/Documentation/Help or install it in your application" \ "bundle." devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/PyASN1" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyASN1" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." coverage: $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILDDIR)/coverage/python.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2714314 pyasn1-0.6.1/docs/source/0000755000175000017500000000000014670145404015436 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/.static/0000755000175000017500000000000014670145404017003 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/.static/logo.svg0000644000175000017500000003276314525242621020475 0ustar00spichugispichugi ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/changelog.rst0000644000175000017500000000006614525242621020117 0ustar00spichugispichugi Changelog ========= .. include:: ../../CHANGES.rst ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/conf.py0000644000175000017500000002510714525242621016740 0ustar00spichugispichugi# -*- coding: utf-8 -*- # # PyASN1 documentation build configuration file, created by # sphinx-quickstart on Sat Jun 27 23:15:54 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) import os, sys # add ../.. to module lookup path sys.path.insert( 0, os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "..") ) ) import pyasn1 # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.intersphinx', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['.templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'contents' # General information about the project. project = u'ASN.1 types and codecs' copyright = u'2005-2020, Ilya Etingof ' author = u'Ilya Etingof ' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = ".".join(pyasn1.__version__.split(".")[:2]) # The full version, including alpha/beta/rc tags. release = pyasn1.__version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = "en" # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { 'logo': 'logo.svg', 'description': '

Brewing free software for the greater good

', 'show_powered_by': False, 'github_user': 'etingof', 'github_repo': 'pyasn1', 'fixed_sidebar': True, } html_sidebars = { '**': [ 'about.html', 'navigation.html', 'relations.html', 'searchbox.html', 'donate.html', ] } # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = "" # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = '.static/favicon.ico' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['.static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' # html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value # html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. htmlhelp_basename = 'pyasn1doc' # html_context = { # 'include_analytics': 'PYASN1DEV' in os.environ # } # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', # Latex figure (float) alignment # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'PyASN1.tex', u'PyASN1 Documentation', u'Ilya Etingof \\textless{}etingof@gmail.com\\textgreater{}', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'pyasn1', u'PyASN1 Documentation', [author], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'PyASN1', u'PyASN1 Documentation', author, 'PyASN1', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'python': ('https://docs.python.org/3.10/', None)} # this merges constructor docstring with class docstring autoclass_content = 'both' # Sort members by type autodoc_member_order = 'bysource' # autodoc_member_order = 'groupwise' # Napoleon settings napoleon_google_docstring = False napoleon_numpy_docstring = True napoleon_include_private_with_doc = False napoleon_include_special_with_doc = True napoleon_use_admonition_for_examples = False napoleon_use_admonition_for_notes = False napoleon_use_admonition_for_references = False napoleon_use_ivar = False napoleon_use_param = False napoleon_use_rtype = False ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707975693.0 pyasn1-0.6.1/docs/source/contents.rst0000644000175000017500000001254214563322015020025 0ustar00spichugispichugi.. _Start Content: ASN.1 library for Python ======================== .. toctree:: :maxdepth: 1 Abstract Syntax Notation One (`ASN.1 `_) is a technology for exchanging structured data in a universally understood, hardware agnostic way. Many industrial, security and telephony applications heavily rely on ASN.1. The `pyasn1 `_ library implements ASN.1 support in pure-Python. What is ASN.1 ------------- ASN.1 is a large, arguably over-engineered and extremely old data modelling and serialisation tool. It is probably among the first serialisation protocols in the history of computer science and technology. ASN.1 started its life over 30 years ago as a serialisation mechanism for the first electronic mail (known as X.400). Later on if was split off the e-mail application and become a stand-alone tech still being actively supported by its designers and widely used in industry and technology. Since then ASN.1 is sort of haunted by its relations with the OSI model -- the first, unsuccessful, version of the Internet. You can read many interesting `discussions `_ on that topic. In the following years, generations of software engineers tackled the serialisation problem many times. We can see that in Google's `ProtoBuffers `_ or `FlatBuffers `_, for example. Interestingly, many new takes on binary protocol design do not depart far from ASN.1 from technical perspective. It's more of a matter of striking a balance between processing overhead, wire format overhead and human readability. Looking at what ASN.1 has to offer, it has three loosely coupled parts: * Data types: the standard introduces a collection of basic data types (integers, bits, strings, arrays and records) that can be used for describing arbitrarily complex, nested data structures. * Serialisation protocols: the above data structures could be converted into a series of octets for storage or transmission over the wire as well as recovered back into their structured form. The system is fully agnostic to hardware architectures differences. * Schema language: ASN.1 data structures could be described in terms of a schema language for ASN.1 compiler to turn it into platform-specific implementation. ASN.1 applications ------------------ Being an old and generally successful standard, ASN.1 is widely adopted for many uses. To give you an example, these technologies use ASN.1 for their data exchange needs: * Signaling standards for the public switched telephone network (SS7 family) * Network management standards (SNMP, CMIP) * Directory standards (X.500 family, LDAP) * Public Key Infrastructure standards (X.509, etc.) * PBX control (CSTA) * IP-based Videoconferencing (H.323 family) * Biometrics (BIP, CBEFF, ACBio) * Intelligent transportation (SAE J2735) * Cellular telephony (GSM, GPRS/EDGE, UMTS, LTE) ASN.1 gotchas ------------- Apparently, ASN.1 is hard to implement properly. Quality open-source ASN.1 tools are rare, but ad-hoc implementations are numerous. Judging from the `statistics `_ on discovered security vulnerabilities, many people have implemented ASN.1 parsers and oftentimes fell victim to its edge cases. On the bright side, ASN.1 has been around for a long time, it is well understood and security reviewed. Documentation ------------- .. toctree:: :maxdepth: 2 /pyasn1/contents Use case -------- .. toctree:: :maxdepth: 2 /example-use-case Download & Install ------------------ .. toctree:: :maxdepth: 2 /download Changes ------- All changes and release history is maintained in changelog. There you could also download the latest unreleased pyasn1 tarball containing the latest fixes and improvements. .. toctree:: :maxdepth: 1 /changelog License ------- The PyASN1 software is distributed under 2-clause BSD License. .. toctree:: :maxdepth: 2 /license Getting help ------------ Please, file your `issues `_ and `PRs `_ at GitHub. Alternatively, you could ask for help at `Stack Overflow `_ or search `pyasn1-users `_ mailing list archive. Books on ASN.1 -------------- The pyasn1 implementation is largely based on reading up the following awesome books: * `ASN.1 - Communication between heterogeneous systems `_ by Olivier Dubuisson * `ASN.1 Complete `_ by Prof John Larmouth Here you can get the official standards which is hard to read: * `ITU standards `_ On the other end of the readability spectrum, here is a quick and sweet write up: * `A Layman's Guide to a Subset of ASN.1, BER, and DER `_ by Burton S. Kaliski If you are working with ASN.1, we'd highly recommend reading a proper book on the subject. .. hidden toctree to include `index.rst` for RTD .. toctree:: :hidden: /index ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1710280662.0 pyasn1-0.6.1/docs/source/download.rst0000644000175000017500000000104614574147726020014 0ustar00spichugispichugi Download & Install ================== The *pyasn1* library is a pure-Python package with no external dependencies. It works with Python 3.8+. The best way to obtain PyASN1 is by running `pip`: .. code-block:: bash $ virtualenv venv $ source venv/bin/activate $ pip install pyasn1 You may also want to use `pyasn1-modules`: .. code-block:: bash $ pip install pyasn1-modules Alternatively, you can download the latest release from `GitHub `_ or `PyPI `_. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/example-use-case.rst0000644000175000017500000001437514525242621021336 0ustar00spichugispichugi Example use case ================ .. toctree:: :maxdepth: 2 To briefly explain how to approach pyasn1, consider a quick workflow example. Grab ASN.1 schema for SSH keys ------------------------------ ASN.1 is widely used in many Internet protocols. Frequently, whenever ASN.1 is employed, data structures are described in ASN.1 schema language right in the RFC. Take `RFC2437 `_ for example -- we can look into it and weed out data structures specification into a local file: .. code-block:: python # pkcs-1.asn PKCS-1 {iso(1) member(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) modules(0) pkcs-1(1)} DEFINITIONS EXPLICIT TAGS ::= BEGIN RSAPrivateKey ::= SEQUENCE { version Version, modulus INTEGER, publicExponent INTEGER, privateExponent INTEGER, prime1 INTEGER, prime2 INTEGER, exponent1 INTEGER, exponent2 INTEGER, coefficient INTEGER } Version ::= INTEGER END Compile ASN.1 schema into Python -------------------------------- In the best case, you should be able to automatically compile ASN.1 spec into Python classes. For that purpose we have the `asn1ate `_ tool: .. code-block:: bash $ asn1ate pkcs-1.asn > rsakey.py Though it may not work out as, as it stands now, asn1ate does not support all ASN.1 language constructs. Alternatively, you could check out the `pyasn1-modules `_ package to see if it already has the ASN.1 spec you are looking for compiled and shipped there. Then just install the package, import the data structure you need and use it: .. code-block:: bash $ pip install pyasn1-modules As a last resort, you could express ASN.1 in Python by hand. The end result should be a declarative Python code resembling original ASN.1 syntax like this: .. code-block:: python # rsakey.py class Version(Integer): pass class RSAPrivateKey(Sequence): componentType = NamedTypes( NamedType('version', Version()), NamedType('modulus', Integer()), NamedType('publicExponent', Integer()), NamedType('privateExponent', Integer()), NamedType('prime1', Integer()), NamedType('prime2', Integer()), NamedType('exponent1', Integer()), NamedType('exponent2', Integer()), NamedType('coefficient', Integer()) ) Read your ~/.ssh/id_rsa ----------------------- Given we've put our Python classes into the `rsakey.py` module, we could import the top-level object for SSH keys container and initialize it from our `~/.ssh/id_rsa` file (for sake of simplicity here we assume no passphrase is set on the key file): .. code-block:: python from base64 import b64decode from pyasn1.codec.der.decoder import decode as der_decoder from rsakey import RSAPrivateKey # Read SSH key from file (assuming no passphrase) with open('.ssh/id_rsa') as key_file: b64_serialisation = ''.join(key_file.readlines()[1:-1]) # Undo BASE64 serialisation der_serialisation = b64decode(b64_serialisation) # Undo DER serialisation, reconstruct SSH key structure private_key, rest_of_input = der_decoder(der_serialisation, asn1Spec=RSAPrivateKey()) Once we have Python ASN.1 structures initialized, we could inspect them: .. code-block:: pycon >>> print('%s' % private_key) RSAPrivateKey: version=0 modulus=280789907761334970323210643584308373... publicExponent=65537 privateExponent=1704567874679144879123080924... prime1=1780178536719561265324798296279384073... prime2=1577313184995269616049017780493740138... exponent1=1193974819720845247396384239609024... exponent2=9240965721817961178848297404494811... coefficient=10207364473358910343346707141115... Play with the keys ------------------ As well as use them nearly as we do with native Python types: .. code-block:: pycon >>> pk = private_key >>> >>> pk['prime1'] * pk['prime2'] == pk['modulus'] True >>> pk['prime1'] == pk['modulus'] // pk['prime2'] True >>> pk['exponent1'] == pk['privateExponent'] % (pk['prime1'] - 1) True >>> pk['exponent2'] == pk['privateExponent'] % (pk['prime2'] - 1) True Technically, pyasn1 classes `emulate `_ Python built-in types. Transform to built-ins ---------------------- ASN.1 data structures exhibit a way more complicated behaviour compared to Python types. You may wish to simplify things by turning the whole tree of pyasn1 objects into an analogous tree made of base Python types: .. code-block:: pycon >>> from pyasn1.codec.native.encoder import encode >>> ... >>> py_private_key = encode(private_key) >>> py_private_key {'version': 0, 'modulus': 280789907761334970323210643584308373, 'publicExponent': 65537, 'privateExponent': 1704567874679144879123080924, 'prime1': 1780178536719561265324798296279384073, 'prime2': 1577313184995269616049017780493740138, 'exponent1': 1193974819720845247396384239609024, 'exponent2': 9240965721817961178848297404494811, 'coefficient': 10207364473358910343346707141115} You can do vice-versa: initialize ASN.1 structure from a dict: .. code-block:: pycon >>> from pyasn1.codec.native.decoder import decode >>> py_private_key = {'modulus': 280789907761334970323210643584308373} >>> private_key = decode(py_private_key, asn1Spec=RSAPrivateKey()) Write it back ------------- Possibly not that applicable to the SSH key example, but you can of course modify any part of the ASN.1 data structure and serialise it back into the same or other wire representation: .. code-block:: python from pyasn1.codec.der.encoder import encode as der_encoder # Serialise SSH key data structure into DER stream der_serialisation = der_encoder(private_key) # Serialise DER stream into BASE64 stream b64_serialisation = '-----BEGIN RSA PRIVATE KEY-----\n' b64_serialisation += b64encode(der_serialisation) b64_serialisation += '-----END RSA PRIVATE KEY-----\n' with open('.ssh/id_rsa.new', 'w') as key_file: key_file.write(b64_serialisation) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/index.rst0000644000175000017500000000014714525242621017277 0ustar00spichugispichugiIndex ===== .. Make RTD happy. We have a redirect index.html to contents.html. :ref:`Start Content` ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/license.rst0000644000175000017500000000007614525242621017613 0ustar00spichugispichugi.. _license: License ======= .. include:: ../../LICENSE.rst ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/pyasn1/0000755000175000017500000000000014670145404016651 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2664316 pyasn1-0.6.1/docs/source/pyasn1/codec/0000755000175000017500000000000014670145404017726 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/pyasn1/codec/ber/0000755000175000017500000000000014670145404020476 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/codec/ber/contents.rst0000644000175000017500000000033714525242621023066 0ustar00spichugispichugi Basic Encoding Rules -------------------- .. autofunction:: pyasn1.codec.ber.encoder.encode(value, asn1Spec=None, defMode=True, maxChunkSize=0) .. autofunction:: pyasn1.codec.ber.decoder.decode(substrate, asn1Spec=None) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/pyasn1/codec/cer/0000755000175000017500000000000014670145404020477 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/codec/cer/contents.rst0000644000175000017500000000031114525242621023057 0ustar00spichugispichugi Canonical Encoding Rules ------------------------ .. autofunction:: pyasn1.codec.cer.encoder.encode(value, asn1Spec=None) .. autofunction:: pyasn1.codec.cer.decoder.decode(substrate, asn1Spec=None) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/pyasn1/codec/der/0000755000175000017500000000000014670145404020500 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/codec/der/contents.rst0000644000175000017500000000032114525242621023061 0ustar00spichugispichugi Distinguished Encoding Rules ---------------------------- .. autofunction:: pyasn1.codec.der.encoder.encode(value, asn1Spec=None) .. autofunction:: pyasn1.codec.der.decoder.decode(substrate, asn1Spec=None) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2724316 pyasn1-0.6.1/docs/source/pyasn1/codec/native/0000755000175000017500000000000014670145404021214 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/codec/native/contents.rst0000644000175000017500000000026414525242621023603 0ustar00spichugispichugi Native Python types ------------------- .. autofunction:: pyasn1.codec.native.encoder.encode(asn1Value) .. autofunction:: pyasn1.codec.native.decoder.decode(pyObject, asn1Spec) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1710280662.0 pyasn1-0.6.1/docs/source/pyasn1/contents.rst0000644000175000017500000001505314574147726021260 0ustar00spichugispichugi .. _pyasn1-library: Library documentation ===================== As of this moment, pyasn1 library implements all ASN.1 data types as Python objects in accordance with X.208 standard. Later, post-1995, revision (X.680) introduced some changes to the schema language which may not be fully supported by pyasn1. Aside from data types a collection of data transformation codecs comes with the pyasn1 package. As for ASN.1 schema language, pyasn1 package does not ship any compiler for it. However, there's a tool called `asn1late `_ which is an ASN.1 grammar parser paired to code generator capable of generating pyasn1 code. So this is an alternative (or at least a good start) to manual implementation of pyasn1 classes from ASN.1 specification. Both `pyasn1 `_ and `pyasn1-modules `_ libraries can be used out-of-the-box with Python versions 3.8+. No external dependencies required. .. _pyasn1-types: ASN.1 types ----------- The ASN.1 data description `language `_ defines a handful of built-in data types. ASN.1 types exhibit different semantics (e.g. number vs string) and can be distinguished from each other by :ref:`tags `. Subtypes can be created on top of base ASN.1 types by adding/overriding the :ref:`tags ` and/or imposing additional :ref:`constraints ` on accepted values. ASN.1 types in pyasn1 are Python objects. One or more ASN.1 types comprise a *schema* describing data structures of unbounded complexity. .. code-block:: python class RSAPublicKey(Sequence): """ ASN.1 specification: RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e } """ componentType = NamedTypes( NamedType('modulus', Integer()), NamedType('publicExponent', Integer()) ) ASN.1 schema can be "instantiated" by essentially putting some concrete value into the type container. Such instantiated schema object can still be used as a schema, but additionally it can play a role of a value in the context of any applicable operator (e.g. arithmetic etc.). .. code-block:: python rsaPublicKey = RSAPublicKey() # ASN.1 SEQUENCE type quacks like Python dict rsaPublicKey['modulus'] = 280789907761334970323210643584308373 rsaPublicKey['publicExponent'] = 65537 Main use of ASN.1 schemas is to guide data transformation. Instantiated ASN.1 schemas carry concrete data to/from data transformation services. .. _isValue: To tell instantiated schema object from just a schema, the *.isValue* property can come in handy: .. code-block:: python schema = RSAPublicKey() # non-instantiated schema assert schema.isValue == False rsaPublicKey['modulus'] = 280789907761334970323210643584308373 # partially instantiated schema assert schema['modulus'].isValue == True assert schema.isValue == False rsaPublicKey['publicExponent'] = 65537 # fully instantiated schema assert schema.isValue == True Copies of existing ASN.1 types can be created with *.clone()* method. All the existing properties of the prototype ASN.1 object get copied over the new type unless the replacements are given. Main use-case for *.clone()* is to instantiate a schema. .. _clone: .. code-block:: python instantiated_schema_A = Integer(1) # ASN.1 INTEGER type quacks like Python int assert instantiated_schema_A == 1 instantiated_schema_B = instantiated_schema_A.clone(2) assert instantiated_schema_B == 2 .. _subtype: New ASN.1 types can be created on top of existing ASN.1 types with the *subtype()* method. Desired properties of the new type get merged with the corresponding properties of the old type. Main use-case for *.subtype()* is to assemble new ASN.1 types by :ref:`tagging ` or applying additional :ref:`constraints ` to accepted type's values. .. code-block:: python parent_type_schema = Integer() child_type_schema = parent_type_schema.subtype( explicitTag=Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x06) ) # test ASN.1 type relationships assert child_type_schema.isSubtypeOf(parent_type_schema) == True assert child_type_schema.isSameTypeWith(parent_type_schema) == False .. toctree:: :maxdepth: 2 /pyasn1/type/base/contents /pyasn1/type/univ/contents /pyasn1/type/char/contents /pyasn1/type/useful/contents ASN.1 type harness ++++++++++++++++++ The identification and behaviour of ASN.1 types is determined by :ref:`tags ` and :ref:`constraints `. The inner structure of *constructed* ASN.1 types is defined by its :ref:`fields ` specification. .. toctree:: :maxdepth: 2 /pyasn1/type/tag/contents /pyasn1/type/constraint/contents /pyasn1/type/namedtype/contents /pyasn1/type/opentype/contents /pyasn1/type/namedval/contents .. _pyasn1-codecs: Serialisation codecs -------------------- Common use-case for pyasn1 is to instantiate ASN.1 schema with user-supplied values and pass instantiated schema to the encoder. The encoder will then turn the data structure into serialised form (stream of bytes) suitable for storing into a file or sending over the network. .. code-block:: python value = 1 instantiated_schema = Integer(value) serialised = encode(instantiated_schema) Alternatively, value and schema can be passed separately: .. code-block:: python value = 1 schema = Integer() serialised = encode(value, asn1Spec=schema) At the receiving end, a decoder would be invoked and given the serialised data as received from the network along with the ASN.1 schema describing the layout of the data structures. The outcome would be an instance of ASN.1 schema filled with values as supplied by the sender. .. code-block:: python serialised = b'\x01\x01\x01' schema = Integer() value, _ = decode(serialised, asn1Spec=schema) assert value == 1 Many distinct serialisation protocols exist for ASN.1, some are implemented in pyasn1. .. toctree:: :maxdepth: 2 /pyasn1/codec/ber/contents /pyasn1/codec/cer/contents /pyasn1/codec/der/contents /pyasn1/codec/native/contents Exceptions ---------- Operations on PyASN1 schema and value objects might cause errors. These errors are manifested to the caller in form of Python exceptions. The exception hierarchy is as follows (ordered from least specific). .. toctree:: :maxdepth: 2 /pyasn1/error/contents ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2734315 pyasn1-0.6.1/docs/source/pyasn1/error/0000755000175000017500000000000014670145404020002 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/error/contents.rst0000644000175000017500000000226014525242621022367 0ustar00spichugispichugi .. _error.PyAsn1Error: .. |PyAsn1Error| replace:: PyAsn1Error |PyAsn1Error| ------------- .. autoclass:: pyasn1.error.PyAsn1Error :members: .. _error.ValueConstraintError: .. |ValueConstraintError| replace:: ValueConstraintError |ValueConstraintError| ---------------------- .. autoclass:: pyasn1.error.ValueConstraintError :members: .. _error.SubstrateUnderrunError: .. |SubstrateUnderrunError| replace:: SubstrateUnderrunError |SubstrateUnderrunError| ------------------------ .. autoclass:: pyasn1.error.SubstrateUnderrunError :members: .. _error.PyAsn1UnicodeError: .. |PyAsn1UnicodeError| replace:: PyAsn1UnicodeError |PyAsn1UnicodeError| -------------------- .. autoclass:: pyasn1.error.PyAsn1UnicodeError :members: .. _error.PyAsn1UnicodeDecodeError: .. |PyAsn1UnicodeDecodeError| replace:: PyAsn1UnicodeDecodeError |PyAsn1UnicodeDecodeError| -------------------------- .. autoclass:: pyasn1.error.PyAsn1UnicodeDecodeError :members: .. _error.PyAsn1UnicodeEncodeError: .. |PyAsn1UnicodeEncodeError| replace:: PyAsn1UnicodeEncodeError |PyAsn1UnicodeEncodeError| -------------------------- .. autoclass:: pyasn1.error.PyAsn1UnicodeEncodeError :members: ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2674315 pyasn1-0.6.1/docs/source/pyasn1/type/0000755000175000017500000000000014670145404017632 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2734315 pyasn1-0.6.1/docs/source/pyasn1/type/base/0000755000175000017500000000000014670145404020544 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/base/asn1type.rst0000644000175000017500000000041114525242621023034 0ustar00spichugispichugi .. _base.Asn1Type: .. |ASN.1| replace:: Asn1Type |ASN.1| type ------------ .. autoclass:: pyasn1.type.base.Asn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/base/constructedasn1type.rst0000644000175000017500000000047614525242621025325 0ustar00spichugispichugi .. _base.ConstructedAsn1Type: .. |ASN.1| replace:: ConstructedAsn1Type |ASN.1| type ------------ .. autoclass:: pyasn1.type.base.ConstructedAsn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), componentType=None) :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/base/contents.rst0000644000175000017500000000104314525242621023127 0ustar00spichugispichugi .. _type.base: ASN.1 type system ----------------- The ASN.1 language defines a collection of data types such as *INTEGER* or *SET*. With pyasn1, ASN.1 types are represented by Python classes. The base classes are described in this part of the documentation. User code might not need to use them directly, except for figuring out if given object belongs to ASN.1 type or not. .. toctree:: :maxdepth: 2 /pyasn1/type/base/asn1type /pyasn1/type/base/simpleasn1type /pyasn1/type/base/constructedasn1type /pyasn1/type/base/novalue ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/base/novalue.rst0000644000175000017500000000014514525242621022745 0ustar00spichugispichugi.. _type.base.NoValue: NoValue sentinel ---------------- .. autoclass:: pyasn1.type.base.NoValue() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/base/simpleasn1type.rst0000644000175000017500000000046514525242621024257 0ustar00spichugispichugi .. _base.SimpleAsn1Type: .. |ASN.1| replace:: SimpleAsn1Type |ASN.1| type ------------ .. autoclass:: pyasn1.type.base.SimpleAsn1Type(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2764316 pyasn1-0.6.1/docs/source/pyasn1/type/char/0000755000175000017500000000000014670145404020547 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/bmpstring.rst0000644000175000017500000000142714525242621023310 0ustar00spichugispichugi .. _char.BMPString: .. |ASN.1| replace:: BMPString .. |encoding| replace:: utf-16-be |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.BMPString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-16 big endian. .. automethod:: pyasn1.type.char.BMPString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.BMPString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/contents.rst0000644000175000017500000000153514525242621023140 0ustar00spichugispichugi .. _type.char: Character types --------------- Besides :ref:`universal types ` also defines a collection of text types. Most of these types come from the past trying to capture the fragments of long-forgotten technologies. These *character* types are all scalars. They are similar to :ref:`OctetString ` except that they all operate on text, not bytes. .. toctree:: :maxdepth: 2 /pyasn1/type/char/numericstring /pyasn1/type/char/printablestring /pyasn1/type/char/teletexstring /pyasn1/type/char/t61string /pyasn1/type/char/videotexstring /pyasn1/type/char/ia5string /pyasn1/type/char/graphicstring /pyasn1/type/char/visiblestring /pyasn1/type/char/iso646string /pyasn1/type/char/generalstring /pyasn1/type/char/universalstring /pyasn1/type/char/bmpstring /pyasn1/type/char/utf8string ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/generalstring.rst0000644000175000017500000000147514525242621024152 0ustar00spichugispichugi .. _char.GeneralString: .. |ASN.1| replace:: GeneralString .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.GeneralString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a character string similar to :py:class:`GraphicString` but additionally including control characters. .. automethod:: pyasn1.type.char.GeneralString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.GeneralString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/graphicstring.rst0000644000175000017500000000151114525242621024141 0ustar00spichugispichugi .. _char.GraphicString: .. |ASN.1| replace:: GraphicString .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.GraphicString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a character string that can hold any "graphical" characters mixed with control ones to select particular alphabet. .. automethod:: pyasn1.type.char.GraphicString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.GraphicString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/ia5string.rst0000644000175000017500000000143514525242621023207 0ustar00spichugispichugi .. _char.IA5String: .. |ASN.1| replace:: IA5String .. |encoding| replace:: us-ascii |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.IA5String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a basic character string first published in 1963 as an ISO/ITU standard, then it turned into ASCII. .. automethod:: pyasn1.type.char.IA5String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.IA5String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/iso646string.rst0000644000175000017500000000137214525242621023563 0ustar00spichugispichugi .. _char.ISO646String: .. |ASN.1| replace:: ISO646String .. |encoding| replace:: us-ascii |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.ISO646String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type is an alias to the :py:class:`VisibleString` type .. automethod:: pyasn1.type.char.ISO646String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.ISO646String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/numericstring.rst0000644000175000017500000000140714525242621024172 0ustar00spichugispichugi .. _char.NumericString: .. |ASN.1| replace:: NumericString .. |encoding| replace:: us-ascii |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.NumericString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| models character string that can be entered from a telephone handset. .. automethod:: pyasn1.type.char.NumericString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.NumericString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/printablestring.rst0000644000175000017500000000152114525242621024505 0ustar00spichugispichugi .. _char.PrintableString: .. |ASN.1| replace:: PrintableString .. |encoding| replace:: us-ascii |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.PrintableString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| models character string that can be entered from a very rudimentary terminals featuring letters, digits and punctuation marks. .. automethod:: pyasn1.type.char.PrintableString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.PrintableString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/t61string.rst0000644000175000017500000000134314525242621023141 0ustar00spichugispichugi .. _char.T61String: .. |ASN.1| replace:: T61String .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.T61String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type is an alias to :py:class:`TeletexString` type. .. automethod:: pyasn1.type.char.T61String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.T61String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/teletexstring.rst0000644000175000017500000000167214525242621024206 0ustar00spichugispichugi .. _char.TeletexString: .. |ASN.1| replace:: TeletexString .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.TeletexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models character string that can be entered from a sophisticated text processing machines (by 20-th century standards) featuring letters from multiple alphabets (308 characters!), digits, punctuation marks and escape sequences. .. automethod:: pyasn1.type.char.TeletexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.TeletexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/universalstring.rst0000644000175000017500000000145614525242621024544 0ustar00spichugispichugi .. _char.UniversalString: .. |ASN.1| replace:: UniversalString .. |encoding| replace:: utf-32-be |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.UniversalString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-32 big endian. .. automethod:: pyasn1.type.char.UniversalString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.UniversalString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/utf8string.rst0000644000175000017500000000141414525242621023414 0ustar00spichugispichugi .. _char.UTF8String: .. |ASN.1| replace:: UTF8String .. |encoding| replace:: utf-8 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.UTF8String(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a Unicode (ISO10646-1) character string implicitly serialised into UTF-8. .. automethod:: pyasn1.type.char.UTF8String.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.UTF8String.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/videotexstring.rst0000644000175000017500000000156214525242621024361 0ustar00spichugispichugi .. _char.VideotexString: .. |ASN.1| replace:: VideotexString .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.VideotexString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models character string that can be consumed by sophisticated video terminals (by 20-th century standards) to render ascii-art style pictures and animations. .. automethod:: pyasn1.type.char.VideotexString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.VideotexString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/char/visiblestring.rst0000644000175000017500000000151614525242621024166 0ustar00spichugispichugi .. _char.VisibleString: .. |ASN.1| replace:: VisibleString .. |encoding| replace:: us-ascii |ASN.1| type ------------ .. autoclass:: pyasn1.type.char.VisibleString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap .. note:: The |ASN.1| type models a character string that can hold any "graphical" characters mixed with control ones to select particular alphabet. .. automethod:: pyasn1.type.char.VisibleString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.char.VisibleString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2774315 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/0000755000175000017500000000000014670145404022016 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/constraintsexclusion.rst0000644000175000017500000000032714525242621027051 0ustar00spichugispichugi .. _constrain.ConstraintsExclusion: .. |Constraint| replace:: ConstraintsExclusion Constraints exclusion --------------------- .. autoclass:: pyasn1.type.constraint.ConstraintsExclusion(constraint) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/constraintsintersection.rst0000644000175000017500000000035014525242621027542 0ustar00spichugispichugi .. _constrain.ConstraintsIntersection: .. |Constraint| replace:: ConstraintsIntersection Constraints intersection ------------------------ .. autoclass:: pyasn1.type.constraint.ConstraintsIntersection(*constraints) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/constraintsunion.rst0000644000175000017500000000030514525242621026164 0ustar00spichugispichugi .. _constrain.ConstraintsUnion: .. |Constraint| replace:: ConstraintsUnion Constraints union ----------------- .. autoclass:: pyasn1.type.constraint.ConstraintsUnion(*constraints) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/containedsubtype.rst0000644000175000017500000000035314525242621026127 0ustar00spichugispichugi .. _constrain.ContainedSubtypeConstraint: .. |Constraint| replace:: ContainedSubtypeConstraint Contained subtype constraint ---------------------------- .. autoclass:: pyasn1.type.constraint.ContainedSubtypeConstraint :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/contents.rst0000644000175000017500000000357214525242621024412 0ustar00spichugispichugi .. _type.constraint: Constraints ----------- ASN.1 standard has a built-in way of limiting the set of values a type can possibly have. Imposing value constraints on an ASN.1 type, together with :ref:`tagging `, is a way of creating a more specialized subtype of an ASN.1 type. The pyasn1 implementation represents all flavors of constraints, as well as their combinations, as immutable Python objects. Ultimately, they get attached to ASN.1 type object at a *.subtypeSpec* attribute. .. code-block:: python class Age(Integer): """ ASN.1 specification: Age ::= INTEGER (0..120) """ subtypeSpec = ValueRangeConstraint(0, 120) .. toctree:: :maxdepth: 2 /pyasn1/type/constraint/singlevalue /pyasn1/type/constraint/containedsubtype /pyasn1/type/constraint/valuerange /pyasn1/type/constraint/valuesize /pyasn1/type/constraint/permittedalphabet /pyasn1/type/constraint/withcomponents Logic operations on constraints +++++++++++++++++++++++++++++++ Sometimes multiple constraints are applied on an ASN.1 type. To capture this situation, individual constraint objects can be glued together by the logic operator objects. The logic operators are Python objects that exhibit similar behaviour as the constraint objects do with the only difference that logic operators are instantiated on the constraint and logic operator objects, not on the bare values. .. code-block:: python class PhoneNumber(NumericString): """ ASN.1 specification: PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE (10)) """ subtypeSpec = ConstraintsIntersection( ValueRangeConstraint('0', '9'), ValueSizeConstraint(10) ) .. toctree:: :maxdepth: 2 /pyasn1/type/constraint/constraintsintersection /pyasn1/type/constraint/constraintsunion /pyasn1/type/constraint/constraintsexclusion ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/permittedalphabet.rst0000644000175000017500000000037314525242621026247 0ustar00spichugispichugi .. _constrain.PermittedAlphabetConstraint: .. |Constraint| replace:: PermittedAlphabetConstraint Permitted alphabet constraint ----------------------------- .. autoclass:: pyasn1.type.constraint.PermittedAlphabetConstraint(*alphabet) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/singlevalue.rst0000644000175000017500000000032214525242621025061 0ustar00spichugispichugi .. _constrain.SingleValueConstraint: .. |Constraint| replace:: SingleValueConstraint Single value constraint ----------------------- .. autoclass:: pyasn1.type.constraint.SingleValueConstraint :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/valuerange.rst0000644000175000017500000000033114525242621024674 0ustar00spichugispichugi .. _constrain.ValueRangeConstraint: .. |Constraint| replace:: ValueRangeConstraint Value range constraint ---------------------- .. autoclass:: pyasn1.type.constraint.ValueRangeConstraint(start, end) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/valuesize.rst0000644000175000017500000000033314525242621024554 0ustar00spichugispichugi .. _constrain.ValueSizeConstraint: .. |Constraint| replace:: ValueSizeConstraint Value size constraint ---------------------- .. autoclass:: pyasn1.type.constraint.ValueSizeConstraint(minimum, maximum) :members: ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/constraint/withcomponents.rst0000644000175000017500000000061314525242621025627 0ustar00spichugispichugi .. _constrain.WithComponentsConstraint: .. |Constraint| replace:: WithComponentsConstraint WITH COMPONENTS constraint -------------------------- .. autoclass:: pyasn1.type.constraint.WithComponentsConstraint(*fields) :members: .. autoclass:: pyasn1.type.constraint.ComponentPresentConstraint() :members: .. autoclass:: pyasn1.type.constraint.ComponentAbsentConstraint() :members: ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2784317 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/0000755000175000017500000000000014670145404021620 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/contents.rst0000644000175000017500000000205514525242621024207 0ustar00spichugispichugi .. _type.namedtype: Fields of constructed types --------------------------- The :ref:`Sequence `, :ref:`Set ` and :ref:`Choice ` ASN.1 types embed other ASN.1 types as named fields. Each field can be expressed via the :ref:`NamedType ` object while the individual fields are brought together by the :ref:`NamedTypes ` object. Ultimately, the fields get attached to the ASN.1 type's *.componentType* attributes. .. code-block:: python class RSAPublicKey(Sequence): """ ASN.1 specification: RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER -- e } """ componentType = NamedTypes( NamedType('modulus', Integer()), NamedType('publicExponent', Integer()) ) .. toctree:: :maxdepth: 2 /pyasn1/type/namedtype/namedtype /pyasn1/type/namedtype/optionalnamedtype /pyasn1/type/namedtype/defaultednamedtype /pyasn1/type/namedtype/namedtypes ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/defaultednamedtype.rst0000644000175000017500000000102014525242621026205 0ustar00spichugispichugi .. _namedtype.DefaultedNamedType: .. |NamedType| replace:: DefaultedNamedType DefaultedNamedType ------------------ .. autoclass:: pyasn1.type.namedtype.DefaultedNamedType :members: .. note:: The *DefaultedNamedType* class models named field of a constructed ASN.1 type which has a default value. The *DefaultedNamedType* objects are normally utilized by the :ref:`NamedTypes ` objects to model individual fields of the constructed ASN.1 types. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/namedtype.rst0000644000175000017500000000070114525242621024334 0ustar00spichugispichugi .. _namedtype.NamedType: .. |NamedType| replace:: NamedType NamedType --------- .. autoclass:: pyasn1.type.namedtype.NamedType :members: .. note:: The *NamedType* class models a mandatory field of a constructed ASN.1 type. The *NamedType* objects are normally utilized by the the :ref:`NamedTypes ` objects to model individual fields of the constructed ASN.1 types. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/namedtypes.rst0000644000175000017500000000056614525242621024530 0ustar00spichugispichugi .. _namedtype.NamedTypes: NamedTypes ---------- .. autoclass:: pyasn1.type.namedtype.NamedTypes :members: .. note:: The *NamedTypes* objects are normally utilized by the constructed ASN.1 types (e.g. :ref:`Sequence `, :ref:`Set ` and :ref:`Choice `) to model the set of fields of those types. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedtype/optionalnamedtype.rst0000644000175000017500000000076514525242621026114 0ustar00spichugispichugi .. _namedtype.OptionalNamedType: .. |NamedType| replace:: OptionalNamedType OptionalNamedType ----------------- .. autoclass:: pyasn1.type.namedtype.OptionalNamedType :members: .. note:: The *OptionalNamedType* class models an optional field of a constructed ASN.1 type. The *OptionalNamedType* objects are normally utilized by the :ref:`NamedTypes ` objects to model individual fields of the constructed ASN.1 types. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2784317 pyasn1-0.6.1/docs/source/pyasn1/type/namedval/0000755000175000017500000000000014670145404021421 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedval/contents.rst0000644000175000017500000000164614525242621024015 0ustar00spichugispichugi .. _type.namedval: Enumerating numbers ------------------- Some ASN.1 types such as :ref:`Integer `, :ref:`Enumerated ` and :ref:`BitString ` may enumerate their otherwise numeric values associating them with human-friendly labels. .. code-block:: python class ErrorStatus(Integer): """ ASN.1 specification: error-status INTEGER { noError(0), tooBig(1), noSuchName(2), ... } """ namedValues = NamedValues( ('noError', 0), ('tooBig', 1), ('noSuchName', 2) ) The enumerated types behave exactly like the non-enumerated ones but, additionally, values can be referred by labels. .. code-block:: python errorStatus = ErrorStatus('tooBig') assert errorStatus == 1 .. toctree:: :maxdepth: 2 /pyasn1/type/namedval/namedval ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/namedval/namedval.rst0000644000175000017500000000036414525242621023743 0ustar00spichugispichugi .. _namedval.NamedValues: .. |NamedValues| replace:: NamedValues |NamedValues| ------------- The |NamedValues| class associates human-friendly names to a set of numbers or bits. .. autoclass:: pyasn1.type.namedval.NamedValues :members: ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2794316 pyasn1-0.6.1/docs/source/pyasn1/type/opentype/0000755000175000017500000000000014670145404021475 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/opentype/contents.rst0000644000175000017500000000703314525242621024065 0ustar00spichugispichugi .. _type.opentype: Dynamic or open type -------------------- ASN.1 allows data structure designer to leave "holes" in field type specification of :ref:`Sequence ` or :ref:`Set ` types. The idea behind that feature is that there can be times, when the exact field type is not known at the design time, or it is anticipated that new field types may come up in the future. This "hole" type is manifested in the data structure by :ref:`Any ` type. Technically, the actual type is serialized into an octet stream and then put into :ref:`Any ` "container", which is in fact an (untagged, by default) specialization of ASN.1 :ref:`OctetString ` type. .. code-block:: bash Algorithm ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } On the receiving end, to know how to interpret the open type serialization, the receiver can rely on the supplied value in the other field of the data structure. That other field is semantically linked with the open type field. This link is expressed in ASN.1 by the *DEFINE BY* clause. From ASN.1 perspective, it is not an error if the decoder does not know a type selector value it receives. In that case pyasn1 decoder just leaves serialized blob in the open type field. .. note:: By default, ASN.1 ANY type has no tag. That makes it an "invisible" in serialization. However, like any other ASN.1 type, ANY type can be subtyped by :ref:`tagging `. Besides scalar open type fields, ASN.1 allows using *SET OF* or *SEQUENCE OF* containers holding zero or more of *ANY* scalars. .. code-block:: bash AttributeTypeAndValues ::= SEQUENCE { type OBJECT IDENTIFIER, values SET OF ANY DEFINED BY type } .. note:: A single type selector field is used to guide the decoder of potentially many elements of a *SET OF* or *SEQUENCE OF* container all at once. That implies that all *ANY* elements must be of the same type in any given instance of a data structure. When expressing ASN.1 type "holes" in pyasn1, the :ref:`OpenType ` object should be used to establish a semantic link between type selector field and open type field. .. code-block:: python algo_map = { ObjectIdentifier('1.2.840.113549.1.1.1'): rsaEncryption(), ObjectIdentifier('1.2.840.113549.1.1.2'): md2WithRSAEncryption() } class Algorithm(Sequence): """ Algorithm ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm } """ componentType = NamedTypes( NamedType('algorithm', ObjectIdentifier()), NamedType('parameters', Any(), openType=OpenType('algorithm', algo_map)) ) Similarly for `SET OF ANY DEFINED BY` or `SEQUENCE OF ANY DEFINED BY` constructs: .. code-block:: python algo_map = { ObjectIdentifier('1.2.840.113549.1.1.1'): rsaEncryption(), ObjectIdentifier('1.2.840.113549.1.1.2'): md2WithRSAEncryption() } class Algorithm(Sequence): """ Algorithm ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters SET OF ANY DEFINED BY algorithm } """ componentType = NamedTypes( NamedType('algorithm', ObjectIdentifier()), NamedType('parameters', SetOf(componentType=Any()), openType=OpenType('algorithm', algo_map)) ) .. toctree:: :maxdepth: 2 /pyasn1/type/opentype/opentype ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/opentype/opentype.rst0000644000175000017500000000033114525242621024065 0ustar00spichugispichugi .. _opentype.OpenType: .. |OpenType| replace:: OpenType |OpenType| ----------- .. autoclass:: pyasn1.type.opentype.OpenType :members: More information on open type use can be found :ref:`here `.././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2804315 pyasn1-0.6.1/docs/source/pyasn1/type/tag/0000755000175000017500000000000014670145404020405 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/tag/contents.rst0000644000175000017500000000255014525242621022774 0ustar00spichugispichugi .. _type.tag: Tags ---- ASN.1 types formally differ from each other by carrying distinct tags. A tag is essentially an integer exhibiting certain inner structure. Individual tags are usually combined into a collection known as *TagSet*. Tags and tag sets in pyasn1 are immutable objects assigned to ASN.1 types as the *tagSet* attribute. Tags can be appended to one another (in EXPLICIT tagging mode) or overridden (IMPLICIT tagging mode) ultimately creating a new ASN.1 subtype. .. code-block:: python class Counter64(Integer): """ ASN.1 specification: Counter64 ::= [APPLICATION 6] IMPLICIT INTEGER """ tagSet = Integer.tagSet.tagImplicitly( Tag(tagClassApplication, tagFormatSimple, 6) ) # alternatively counter64 = Integer().subtype( implicitTag=Tag(tagClassApplication, tagFormatSimple, 6) ) ASN.1 types can be related to each other via the *.isSameTypeWith()*, *.isSuperTypeOf()* and *.isSubTypeOf()* methods. Internally, the *.tagSet* of the types are compared along with the value constraints (e.g. *.subtypeSpec*). .. code-block:: python assert Counter64().isSubTypeOf(Integer()) == True assert Counter64().isSameTypeWith(Integer()) == False .. toctree:: :maxdepth: 2 /pyasn1/type/tag/tag /pyasn1/type/tag/tagset /pyasn1/type/tag/tagmap ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/tag/tag.rst0000644000175000017500000000063514525242621021714 0ustar00spichugispichugi .. _tag.tag: Solitary tag ------------ .. automodule:: pyasn1.type.tag :members: tagClassUniversal, tagClassApplication, tagClassContext, tagClassPrivate, tagFormatSimple, tagFormatConstructed .. autoclass:: pyasn1.type.tag.Tag :members: .. note:: The *Tag* objects are normally used by the :ref:`TagSet `, objects to model a collection of ASN.1 tags. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/tag/tagmap.rst0000644000175000017500000000044014525242621022404 0ustar00spichugispichugi .. _tag.tagmap: Tag->type map ------------- .. autoclass:: pyasn1.type.tagmap.TagMap :members: .. note:: The *TagMap* objects are used by the :ref:`TagSet `, objects for looking up components of constructed ASN.1 types by :ref:`Tag `. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/tag/tagset.rst0000644000175000017500000000044414525242621022426 0ustar00spichugispichugi .. _tag.tagset: Tag set ------- .. autoclass:: pyasn1.type.tag.TagSet :members: .. note:: The *TagSet* objects are normally used by all ASN.1 type objects both simple (like :ref:`Integer `) and constructed (e.g. :ref:`Sequence `). ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2824316 pyasn1-0.6.1/docs/source/pyasn1/type/univ/0000755000175000017500000000000014670145404020613 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/any.rst0000644000175000017500000000171314525242621022134 0ustar00spichugispichugi .. _univ.Any: .. |ASN.1| replace:: Any .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Any(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec .. note:: The |ASN.1| type models an arbitrary value of an arbitrary type. Typically, a selection of types are defined in form of an :ref:`open type ` . Technically, the ANY value is a serialised representation of some other ASN.1 object. .. automethod:: pyasn1.type.univ.Any.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1') .. automethod:: pyasn1.type.univ.Any.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/bitstring.rst0000644000175000017500000000165114525242621023353 0ustar00spichugispichugi .. _univ.BitString: .. |ASN.1| replace:: BitString |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.BitString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, asInteger, asNumbers, asOctets, asBinary, fromHexString, fromBinaryString, fromOctetString .. note:: The |ASN.1| type models an arbitrary sequence of bits. .. automethod:: pyasn1.type.univ.BitString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) .. automethod:: pyasn1.type.univ.BitString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), , namedValues=NamedValues(),binValue=NoValue(), hexValue=NoValue()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/boolean.rst0000644000175000017500000000121014525242621022754 0ustar00spichugispichugi .. _univ.Boolean: .. |ASN.1| replace:: Boolean |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Boolean(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec .. note:: The |ASN.1| type models a BOOLEAN that can be either TRUE or FALSE. .. automethod:: pyasn1.type.univ.Boolean.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.Boolean.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/choice.rst0000644000175000017500000000162214525242621022576 0ustar00spichugispichugi .. _univ.Choice: .. |ASN.1| replace:: Choice |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Choice(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, getComponentByType, setComponentByType, getName, getComponent, isInconsistent .. note:: The |ASN.1| type can only hold a single component at a time belonging to the list of allowed types. .. automethod:: pyasn1.type.univ.Choice.clone(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.Choice.subtype(componentType=None, implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/contents.rst0000644000175000017500000000164514525242621023206 0ustar00spichugispichugi .. _type.univ: Universal types --------------- The ASN.1 language defines a collection of core data types also known as *universal* types. Some of these types behave like a scalar (e.g. *simple* types) while the rest are structured types (the standard calls them *constructed*). Example of simple types include :ref:`Integer ` or :ref:`OctetString `. Constructed types like :ref:`Sequence ` embed other types, both simple and constructed. .. toctree:: :maxdepth: 2 /pyasn1/type/univ/integer /pyasn1/type/univ/boolean /pyasn1/type/univ/bitstring /pyasn1/type/univ/octetstring /pyasn1/type/univ/null /pyasn1/type/univ/objectidentifier /pyasn1/type/univ/real /pyasn1/type/univ/enumerated /pyasn1/type/univ/any /pyasn1/type/univ/setof /pyasn1/type/univ/sequenceof /pyasn1/type/univ/set /pyasn1/type/univ/sequence /pyasn1/type/univ/choice ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/enumerated.rst0000644000175000017500000000145714525242621023503 0ustar00spichugispichugi .. _univ.Enumerated: .. |ASN.1| replace:: Enumerated |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Enumerated(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, namedValues .. note:: The |ASN.1| type models bounded set of named integer values. Other than that, it is identical to the *Integer* class. .. automethod:: pyasn1.type.univ.Enumerated.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) .. automethod:: pyasn1.type.univ.Enumerated.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/integer.rst0000644000175000017500000000147314525242621023005 0ustar00spichugispichugi .. _univ.Integer: .. |ASN.1| replace:: Integer |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Integer(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, namedValues .. note:: The |ASN.1| type models an arbitrary integer. INTEGER values can be positive, negative, or zero, and can have any magnitude. .. automethod:: pyasn1.type.univ.Integer.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) .. automethod:: pyasn1.type.univ.Integer.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(), namedValues=NamedValues()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/null.rst0000644000175000017500000000074414525242621022322 0ustar00spichugispichugi .. _univ.Null: .. |ASN.1| replace:: Null |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Null(value=NoValue(), tagSet=TagSet()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec .. note:: The |ASN.1| type models ASN.1 NULL. .. automethod:: pyasn1.type.univ.Null.clone(value=NoValue(), tagSet=TagSet()) .. automethod:: pyasn1.type.univ.Null.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/objectidentifier.rst0000644000175000017500000000132014525242621024650 0ustar00spichugispichugi .. _univ.ObjectIdentifier: .. |ASN.1| replace:: ObjectIdentifier |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.ObjectIdentifier(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isPrefixOf .. note:: The |ASN.1| type models ASN.1 OBJECT IDENTIFIER as a sequence of integer numbers. .. automethod:: pyasn1.type.univ.ObjectIdentifier.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.ObjectIdentifier.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/octetstring.rst0000644000175000017500000000155614525242621023717 0ustar00spichugispichugi .. _univ.OctetString: .. |ASN.1| replace:: OctetString .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.OctetString(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1', binValue=NoValue(),hexValue=NoValue()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, fromHexString, fromBinaryString .. note:: The |ASN.1| type models an arbitrary string of octets (eight-bit numbers), not printable text string. .. automethod:: pyasn1.type.univ.OctetString.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='iso-8859-1') .. automethod:: pyasn1.type.univ.OctetString.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection(),encoding='iso-8859-1') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/real.rst0000644000175000017500000000122514525242621022266 0ustar00spichugispichugi .. _univ.Real: .. |ASN.1| replace:: Real |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Real(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isInf, isPlusInf, isMinusInf .. note:: The |ASN.1| type models a rational number of arbitrary precision. .. automethod:: pyasn1.type.univ.Real.clone(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.Real.subtype(value=NoValue(), implicitTag=Tag(), explicitTag=Tag(), subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/sequence.rst0000644000175000017500000000165214525242621023157 0ustar00spichugispichugi .. _univ.Sequence: .. |ASN.1| replace:: Sequence |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Sequence(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, clear, reset, isInconsistent .. note:: The |ASN.1| type models a collection of named ASN.1 components. Ordering of the components **is** preserved upon de/serialisation. .. automethod:: pyasn1.type.univ.Sequence.clone(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.Sequence.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/sequenceof.rst0000644000175000017500000000155714525242621023510 0ustar00spichugispichugi .. _univ.SequenceOf: .. |ASN.1| replace:: SequenceOf |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.SequenceOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent .. note:: The |ASN.1| type models a collection of elements of a single ASN.1 type. Ordering of the components **is** preserved upon de/serialisation. .. automethod:: pyasn1.type.univ.SequenceOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.SequenceOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/set.rst0000644000175000017500000000167514525242621022147 0ustar00spichugispichugi .. _univ.Set: .. |ASN.1| replace:: Set |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.Set(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, getComponentByType, setComponentByType, clear, reset, isInconsistent .. note:: The |ASN.1| type models a collection of named ASN.1 components. Ordering of the components **is not** preserved upon de/serialisation. .. automethod:: pyasn1.type.univ.Set.clone(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.Set.subtype(componentType=NamedTypes(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/univ/setof.rst0000644000175000017500000000152514525242621022466 0ustar00spichugispichugi .. _univ.SetOf: .. |ASN.1| replace:: SetOf |ASN.1| type ------------ .. autoclass:: pyasn1.type.univ.SetOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec,  getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent .. note:: The |ASN.1| type models a collection of elements of a single ASN.1 type. Ordering of the components **is not** preserved upon de/serialisation. .. automethod:: pyasn1.type.univ.SetOf.clone(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection()) .. automethod:: pyasn1.type.univ.SetOf.subtype(componentType=NoValue(), implicitTag=Tag(), explicitTag=Tag(),subtypeSpec=ConstraintsIntersection()) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2834315 pyasn1-0.6.1/docs/source/pyasn1/type/useful/0000755000175000017500000000000014670145404021135 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/useful/contents.rst0000644000175000017500000000042714525242621023525 0ustar00spichugispichugi .. _type.useful: Useful types ------------ Some assorted utility ASN.1 types belong to the *useful* group. These types are all scalar. .. toctree:: :maxdepth: 2 /pyasn1/type/useful/objectdescriptor /pyasn1/type/useful/generalizedtime /pyasn1/type/useful/utctime ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/useful/generalizedtime.rst0000644000175000017500000000274214525242621025042 0ustar00spichugispichugi .. _useful.GeneralizedTime: .. |ASN.1| replace:: GeneralizedTime .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.useful.GeneralizedTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime .. note:: The |ASN.1| type models a character string representing date and time in many different formats. Formal syntax for the *GeneralizedTime* value is: * **YYYYMMDDhh[mm[ss[(.|,)ffff]]]** standing for a local time, four digits for the year, two for the month, two for the day and two for the hour, followed by two digits for the minutes and two for the seconds if required, then a dot (or a comma), and a number for the fractions of second or * a string as above followed by the letter “Z” (denoting a UTC time) or * a string as above followed by a string **(+|-)hh[mm]** denoting time zone offset relative to UTC For example, *20170126120000Z* stands for YYYYMMDDHHMMSSZ. .. automethod:: pyasn1.type.useful.GeneralizedTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.useful.GeneralizedTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/useful/objectdescriptor.rst0000644000175000017500000000155214525242621025235 0ustar00spichugispichugi .. _useful.ObjectDescriptor: .. |ASN.1| replace:: ObjectDescriptor .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.useful.ObjectDescriptor(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet .. note:: The |ASN.1| type models a character string that can accompany the *ObjectIdentifier* type to serve as a human-friendly annotation for an OBJECT IDENTIFIER. .. automethod:: pyasn1.type.useful.ObjectDescriptor.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.useful.ObjectDescriptor.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/docs/source/pyasn1/type/useful/utctime.rst0000644000175000017500000000246014525242621023341 0ustar00spichugispichugi .. _useful.UTCTime: .. |ASN.1| replace:: UTCTime .. |encoding| replace:: iso-8859-1 |ASN.1| type ------------ .. autoclass:: pyasn1.type.useful.UTCTime(value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, asDateTime, fromDateTime .. note:: The |ASN.1| type models a character string representing date and time. Formal syntax for the *UTCTime* value is: * **YYMMDDhhmm[ss]** standing for UTC time, two digits for the year, two for the month, two for the day and two for the hour, followed by two digits for the minutes and two for the seconds if required or * a string as above followed by the letter “Z” (denoting a UTC time) or * a string as above followed by a string **(+|-)hhmm** denoting time zone offset relative to UTC For example, *170126120000Z* which stands for YYMMDDHHMMSSZ. .. automethod:: pyasn1.type.useful.UTCTime.clone(self, value=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') .. automethod:: pyasn1.type.useful.UTCTime.subtype(self, value=NoValue(), implicitTag=TagSet(), explicitTag=TagSet(),subtypeSpec=ConstraintsIntersection(), encoding='us-ascii') ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2834315 pyasn1-0.6.1/pyasn1/0000755000175000017500000000000014670145404014421 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726005917.0 pyasn1-0.6.1/pyasn1/__init__.py0000644000175000017500000000010214670141235016521 0ustar00spichugispichugi# https://www.python.org/dev/peps/pep-0396/ __version__ = '0.6.1' ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2844317 pyasn1-0.6.1/pyasn1/codec/0000755000175000017500000000000014670145404015476 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/__init__.py0000644000175000017500000000007314525242621017605 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2854316 pyasn1-0.6.1/pyasn1/codec/ber/0000755000175000017500000000000014670145404016246 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/ber/__init__.py0000644000175000017500000000007314525242621020355 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/ber/decoder.py0000644000175000017500000023253014670137102020226 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # 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 __all__ = ['StreamingDecoder', 'Decoder', 'decode'] LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) noValue = base.noValue SubstrateUnderrunError = error.SubstrateUnderrunError 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? @staticmethod def _passAsn1Object(asn1Object, options): if 'asn1Object' not in options: options['asn1Object'] = asn1Object return options class AbstractSimplePayloadDecoder(AbstractPayloadDecoder): @staticmethod def substrateCollector(asn1Object, substrate, length, options): for chunk in readFromStream(substrate, length, options): yield chunk def _createComponent(self, asn1Spec, tagSet, value, **options): if options.get('native'): return value elif asn1Spec is None: return self.protoComponent.clone(value, tagSet=tagSet) elif value is noValue: return asn1Spec else: return asn1Spec.clone(value) class RawPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.Any('') def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: asn1Object = self._createComponent(asn1Spec, tagSet, '', **options) for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return for value in decodeFun(substrate, asn1Spec, tagSet, length, **options): yield value def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: asn1Object = self._createComponent(asn1Spec, tagSet, '', **options) for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return while True: for value in decodeFun( substrate, asn1Spec, tagSet, length, allowEoo=True, **options): if value is eoo.endOfOctets: return yield value rawPayloadDecoder = RawPayloadDecoder() class IntegerPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.Integer(0) def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk if chunk: value = int.from_bytes(bytes(chunk), 'big', signed=True) else: value = 0 yield self._createComponent(asn1Spec, tagSet, value, **options) class BooleanPayloadDecoder(IntegerPayloadDecoder): protoComponent = univ.Boolean(0) def _createComponent(self, asn1Spec, tagSet, value, **options): return IntegerPayloadDecoder._createComponent( self, asn1Spec, tagSet, value and 1 or 0, **options) class BitStringPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.BitString(()) supportConstructedForm = True def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return if not length: raise error.PyAsn1Error('Empty BIT STRING substrate') for chunk in isEndOfStream(substrate): if isinstance(chunk, SubstrateUnderrunError): yield chunk if chunk: raise error.PyAsn1Error('Empty BIT STRING substrate') if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? for trailingBits in readFromStream(substrate, 1, options): if isinstance(trailingBits, SubstrateUnderrunError): yield trailingBits trailingBits = ord(trailingBits) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) for chunk in readFromStream(substrate, length - 1, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk value = self.protoComponent.fromOctetString( chunk, internalFormat=True, padding=trailingBits) yield self._createComponent(asn1Spec, tagSet, value, **options) return if not self.supportConstructedForm: raise error.PyAsn1Error('Constructed encoding form prohibited ' 'at %s' % self.__class__.__name__) if LOG: LOG('assembling constructed serialization') # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector bitString = self.protoComponent.fromOctetString(b'', internalFormat=True) current_position = substrate.tell() while substrate.tell() - current_position < length: for component in decodeFun( substrate, self.protoComponent, substrateFun=substrateFun, **options): if isinstance(component, SubstrateUnderrunError): yield component trailingBits = component[0] if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) bitString = self.protoComponent.fromOctetString( component[1:], internalFormat=True, prepend=bitString, padding=trailingBits ) yield self._createComponent(asn1Spec, tagSet, bitString, **options) def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector bitString = self.protoComponent.fromOctetString(b'', internalFormat=True) while True: # loop over fragments for component in decodeFun( substrate, self.protoComponent, substrateFun=substrateFun, allowEoo=True, **options): if component is eoo.endOfOctets: break if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break trailingBits = component[0] if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) bitString = self.protoComponent.fromOctetString( component[1:], internalFormat=True, prepend=bitString, padding=trailingBits ) yield self._createComponent(asn1Spec, tagSet, bitString, **options) class OctetStringPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.OctetString('') supportConstructedForm = True def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) 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 yield self._createComponent(asn1Spec, tagSet, chunk, **options) return if not self.supportConstructedForm: raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__) if LOG: LOG('assembling constructed serialization') # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector header = b'' original_position = substrate.tell() # head = popSubstream(substrate, length) while substrate.tell() - original_position < length: for component in decodeFun( substrate, self.protoComponent, substrateFun=substrateFun, **options): if isinstance(component, SubstrateUnderrunError): yield component header += component yield self._createComponent(asn1Spec, tagSet, header, **options) def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun and substrateFun is not self.substrateCollector: asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options) for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector header = b'' while True: # loop over fragments for component in decodeFun( substrate, self.protoComponent, substrateFun=substrateFun, allowEoo=True, **options): if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break if component is eoo.endOfOctets: break header += component yield self._createComponent(asn1Spec, tagSet, header, **options) class NullPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.Null('') def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk component = self._createComponent(asn1Spec, tagSet, '', **options) if chunk: raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length) yield component class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.ObjectIdentifier(()) def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk if not chunk: raise error.PyAsn1Error('Empty substrate') 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 if 0 <= oid[0] <= 39: oid = (0,) + oid elif 40 <= 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]) yield self._createComponent(asn1Spec, tagSet, oid, **options) class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.RelativeOID(()) def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk if not chunk: raise error.PyAsn1Error('Empty substrate') reloid = () index = 0 substrateLen = len(chunk) while index < substrateLen: subId = chunk[index] index += 1 if subId < 128: reloid += (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' % (reloid,) ) nextSubId = chunk[index] index += 1 reloid += ((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 RELATIVE-OID encoding') yield self._createComponent(asn1Spec, tagSet, reloid, **options) class RealPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.Real() def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk if not chunk: yield self._createComponent(asn1Spec, tagSet, 0.0, **options) return fo = chunk[0] chunk = chunk[1:] if fo & 0x80: # binary encoding if not chunk: raise error.PyAsn1Error("Incomplete floating-point value") if LOG: LOG('decoding binary encoded REAL') n = (fo & 0x03) + 1 if n == 4: n = chunk[0] chunk = chunk[1:] eo, chunk = chunk[:n], chunk[n:] if not eo or not chunk: raise error.PyAsn1Error('Real exponent screwed') e = eo[0] & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= eo[0] eo = eo[1:] b = fo >> 4 & 0x03 # base bits if b > 2: raise error.PyAsn1Error('Illegal Real base') if b == 1: # encbase = 8 e *= 3 elif b == 2: # encbase = 16 e *= 4 p = 0 while chunk: # value p <<= 8 p |= chunk[0] chunk = chunk[1:] if fo & 0x40: # sign bit p = -p sf = fo >> 2 & 0x03 # scale bits p *= 2 ** sf value = (p, 2, e) elif fo & 0x40: # infinite value if LOG: LOG('decoding infinite REAL') value = fo & 0x01 and '-inf' or 'inf' elif fo & 0xc0 == 0: # character encoding if not chunk: raise error.PyAsn1Error("Incomplete floating-point value") if LOG: LOG('decoding character encoded REAL') try: if fo & 0x3 == 0x1: # NR1 value = (int(chunk), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(chunk) elif fo & 0x3 == 0x3: # NR3 value = float(chunk) else: raise error.SubstrateUnderrunError( 'Unknown NR (tag %s)' % fo ) except ValueError: raise error.SubstrateUnderrunError( 'Bad character Real syntax' ) else: raise error.SubstrateUnderrunError( 'Unknown encoding (tag %s)' % fo ) yield self._createComponent(asn1Spec, tagSet, value, **options) class AbstractConstructedPayloadDecoder(AbstractPayloadDecoder): protoComponent = None class ConstructedPayloadDecoderBase(AbstractConstructedPayloadDecoder): protoRecordComponent = None protoSequenceComponent = None def _getComponentTagMap(self, asn1Object, idx): raise NotImplementedError def _getComponentPositionByType(self, asn1Object, tagSet, idx): raise NotImplementedError def _decodeComponentsSchemaless( self, substrate, tagSet=None, decodeFun=None, length=None, **options): asn1Object = None components = [] componentTypes = set() original_position = substrate.tell() while length == -1 or substrate.tell() < original_position + length: for component in decodeFun(substrate, **options): if isinstance(component, SubstrateUnderrunError): yield component if length == -1 and component is eoo.endOfOctets: break components.append(component) componentTypes.add(component.tagSet) # 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 else: protoComponent = self.protoSequenceComponent 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 is not None: asn1Object = asn1Spec.clone() elif self.protoComponent is not None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = self.protoRecordComponent, self.protoSequenceComponent for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return if asn1Spec is None: 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 LOG('Unused trailing %d octets encountered: %s' % ( len(trailing), debug.hexdump(trailing))) yield asn1Object return asn1Object = asn1Spec.clone() asn1Object.clear() options = self._passAsn1Object(asn1Object, options) if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): namedTypes = asn1Spec.componentType isSetType = asn1Spec.typeId == univ.Set.typeId isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault if LOG: LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( not isDeterministic and 'non-' or '', isSetType and 'SET' or '', asn1Spec)) seenIndices = set() idx = 0 while substrate.tell() - original_position < length: if not namedTypes: componentType = None elif isSetType: componentType = namedTypes.tagMapUnique else: try: if isDeterministic: componentType = namedTypes[idx].asn1Object elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: componentType = namedTypes.getTagMapNearPosition(idx) else: componentType = namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error( 'Excessive components decoded at %r' % (asn1Spec,) ) for component in decodeFun(substrate, componentType, **options): if isinstance(component, SubstrateUnderrunError): yield component if not isDeterministic and namedTypes: if isSetType: idx = namedTypes.getPositionByType(component.effectiveTagSet) elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) seenIndices.add(idx) idx += 1 if LOG: LOG('seen component indices %s' % seenIndices) if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error( 'ASN.1 object %s has uninitialized ' 'components' % asn1Object.__class__.__name__) if namedTypes.hasOpenTypes: openTypes = options.get('openTypes', {}) if LOG: LOG('user-specified open types map:') for k, v in openTypes.items(): LOG('%s -> %r' % (k, v)) if openTypes or options.get('decodeOpenTypes', False): for idx, namedType in enumerate(namedTypes.namedTypes): if not namedType.openType: continue if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: continue governingValue = asn1Object.getComponentByName( namedType.openType.name ) try: openType = openTypes[governingValue] except KeyError: 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)) try: openType = namedType.openType[governingValue] except KeyError: if LOG: LOG('failed to resolve open type by governing ' 'value %r' % (governingValue,)) continue if LOG: LOG('resolved open type %r by governing ' 'value %r' % (openType, governingValue)) containerValue = asn1Object.getComponentByPosition(idx) if containerValue.typeId in ( univ.SetOf.typeId, univ.SequenceOf.typeId): for pos, containerElement in enumerate( containerValue): stream = asSeekableStream(containerValue[pos].asOctets()) for component in decodeFun(stream, asn1Spec=openType, **options): if isinstance(component, SubstrateUnderrunError): yield component containerValue[pos] = component else: stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets()) 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 asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) idx += 1 yield asn1Object def indefLenValueDecoder(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') if substrateFun is not None: if asn1Spec is not None: asn1Object = asn1Spec.clone() elif self.protoComponent is not None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = self.protoRecordComponent, self.protoSequenceComponent for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return if asn1Spec is None: for asn1Object in self._decodeComponentsSchemaless( substrate, tagSet=tagSet, decodeFun=decodeFun, length=length, **dict(options, allowEoo=True)): if isinstance(asn1Object, SubstrateUnderrunError): yield asn1Object yield asn1Object return asn1Object = asn1Spec.clone() asn1Object.clear() options = self._passAsn1Object(asn1Object, options) if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId): namedTypes = asn1Object.componentType isSetType = asn1Object.typeId == univ.Set.typeId isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault if LOG: LOG('decoding %sdeterministic %s type %r chosen by type ID' % ( not isDeterministic and 'non-' or '', isSetType and 'SET' or '', asn1Spec)) seenIndices = set() idx = 0 while True: # loop over components if len(namedTypes) <= idx: asn1Spec = None elif isSetType: asn1Spec = namedTypes.tagMapUnique else: try: if isDeterministic: asn1Spec = namedTypes[idx].asn1Object elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: asn1Spec = namedTypes.getTagMapNearPosition(idx) else: asn1Spec = namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error( 'Excessive components decoded at %r' % (asn1Object,) ) for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options): if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break if component is eoo.endOfOctets: break if not isDeterministic and namedTypes: if isSetType: idx = namedTypes.getPositionByType(component.effectiveTagSet) elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted: idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) seenIndices.add(idx) idx += 1 if LOG: LOG('seen component indices %s' % seenIndices) if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error( 'ASN.1 object %s has uninitialized ' 'components' % asn1Object.__class__.__name__) if namedTypes.hasOpenTypes: openTypes = options.get('openTypes', {}) if LOG: LOG('user-specified open types map:') for k, v in openTypes.items(): LOG('%s -> %r' % (k, v)) if openTypes or options.get('decodeOpenTypes', False): for idx, namedType in enumerate(namedTypes.namedTypes): if not namedType.openType: continue if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue: continue governingValue = asn1Object.getComponentByName( namedType.openType.name ) try: openType = openTypes[governingValue] except KeyError: 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)) try: openType = namedType.openType[governingValue] except KeyError: if LOG: LOG('failed to resolve open type by governing ' 'value %r' % (governingValue,)) continue if LOG: LOG('resolved open type %r by governing ' 'value %r' % (openType, governingValue)) containerValue = asn1Object.getComponentByPosition(idx) if containerValue.typeId in ( univ.SetOf.typeId, univ.SequenceOf.typeId): for pos, containerElement in enumerate( containerValue): stream = asSeekableStream(containerValue[pos].asOctets()) 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 while True: for component in decodeFun( substrate, componentType, allowEoo=True, **options): if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break if component is eoo.endOfOctets: break asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) idx += 1 yield asn1Object class SequenceOrSequenceOfPayloadDecoder(ConstructedPayloadDecoderBase): protoRecordComponent = univ.Sequence() protoSequenceComponent = univ.SequenceOf() class SequencePayloadDecoder(SequenceOrSequenceOfPayloadDecoder): protoComponent = univ.Sequence() class SequenceOfPayloadDecoder(SequenceOrSequenceOfPayloadDecoder): protoComponent = univ.SequenceOf() class SetOrSetOfPayloadDecoder(ConstructedPayloadDecoderBase): protoRecordComponent = univ.Set() protoSequenceComponent = univ.SetOf() class SetPayloadDecoder(SetOrSetOfPayloadDecoder): protoComponent = univ.Set() class SetOfPayloadDecoder(SetOrSetOfPayloadDecoder): protoComponent = univ.SetOf() class ChoicePayloadDecoder(ConstructedPayloadDecoderBase): protoComponent = univ.Choice() def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if asn1Spec is None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = asn1Spec.clone() if substrateFun: for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return options = self._passAsn1Object(asn1Object, options) 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)) asn1Object.setComponentByType( effectiveTagSet, component, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=False ) yield asn1Object def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if asn1Spec is None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = asn1Spec.clone() if substrateFun: for chunk in substrateFun(asn1Object, substrate, length, options): yield chunk return options = self._passAsn1Object(asn1Object, options) isTagged = asn1Object.tagSet == tagSet if LOG: LOG('decoding %s as %stagged CHOICE' % ( tagSet, isTagged and 'explicitly ' or 'un')) while True: if isTagged: iterator = decodeFun( substrate, asn1Object.componentType.tagMapUnique, **dict(options, allowEoo=True)) else: iterator = decodeFun( substrate, asn1Object.componentType.tagMapUnique, tagSet, length, state, **dict(options, allowEoo=True)) for component in iterator: if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break effectiveTagSet = component.effectiveTagSet if LOG: LOG('decoded component %s, effective tag set ' '%s' % (component, effectiveTagSet)) asn1Object.setComponentByType( effectiveTagSet, component, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=False ) if not isTagged: break if not isTagged or component is eoo.endOfOctets: break yield asn1Object class AnyPayloadDecoder(AbstractSimplePayloadDecoder): protoComponent = univ.Any() def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if asn1Spec is None: isUntagged = True elif asn1Spec.__class__ is tagmap.TagMap: isUntagged = tagSet not in asn1Spec.tagMap else: isUntagged = tagSet != asn1Spec.tagSet if isUntagged: fullPosition = substrate.markedPosition currentPosition = substrate.tell() substrate.seek(fullPosition, os.SEEK_SET) length += currentPosition - fullPosition 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 yield self._createComponent(asn1Spec, tagSet, chunk, **options) def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if asn1Spec is None: isTagged = False 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 is not 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 while True: # loop over fragments for component in decodeFun( substrate, asn1Spec, substrateFun=substrateFun, allowEoo=True, **options): if isinstance(component, SubstrateUnderrunError): yield component if component is eoo.endOfOctets: break if component is eoo.endOfOctets: break chunk += component if substrateFun: yield chunk # TODO: Weird else: yield self._createComponent(asn1Spec, tagSet, chunk, **options) # character string types class UTF8StringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.UTF8String() class NumericStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.NumericString() class PrintableStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.PrintableString() class TeletexStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.TeletexString() class VideotexStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.VideotexString() class IA5StringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.IA5String() class GraphicStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.GraphicString() class VisibleStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.VisibleString() class GeneralStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.GeneralString() class UniversalStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.UniversalString() class BMPStringPayloadDecoder(OctetStringPayloadDecoder): protoComponent = char.BMPString() # "useful" types class ObjectDescriptorPayloadDecoder(OctetStringPayloadDecoder): protoComponent = useful.ObjectDescriptor() class GeneralizedTimePayloadDecoder(OctetStringPayloadDecoder): protoComponent = useful.GeneralizedTime() class UTCTimePayloadDecoder(OctetStringPayloadDecoder): protoComponent = useful.UTCTime() TAG_MAP = { univ.Integer.tagSet: IntegerPayloadDecoder(), univ.Boolean.tagSet: BooleanPayloadDecoder(), univ.BitString.tagSet: BitStringPayloadDecoder(), univ.OctetString.tagSet: OctetStringPayloadDecoder(), univ.Null.tagSet: NullPayloadDecoder(), univ.ObjectIdentifier.tagSet: ObjectIdentifierPayloadDecoder(), univ.RelativeOID.tagSet: RelativeOIDPayloadDecoder(), univ.Enumerated.tagSet: IntegerPayloadDecoder(), univ.Real.tagSet: RealPayloadDecoder(), univ.Sequence.tagSet: SequenceOrSequenceOfPayloadDecoder(), # conflicts with SequenceOf univ.Set.tagSet: SetOrSetOfPayloadDecoder(), # conflicts with SetOf univ.Choice.tagSet: ChoicePayloadDecoder(), # conflicts with Any # character string types char.UTF8String.tagSet: UTF8StringPayloadDecoder(), char.NumericString.tagSet: NumericStringPayloadDecoder(), char.PrintableString.tagSet: PrintableStringPayloadDecoder(), char.TeletexString.tagSet: TeletexStringPayloadDecoder(), char.VideotexString.tagSet: VideotexStringPayloadDecoder(), char.IA5String.tagSet: IA5StringPayloadDecoder(), char.GraphicString.tagSet: GraphicStringPayloadDecoder(), char.VisibleString.tagSet: VisibleStringPayloadDecoder(), char.GeneralString.tagSet: GeneralStringPayloadDecoder(), char.UniversalString.tagSet: UniversalStringPayloadDecoder(), char.BMPString.tagSet: BMPStringPayloadDecoder(), # useful types useful.ObjectDescriptor.tagSet: ObjectDescriptorPayloadDecoder(), useful.GeneralizedTime.tagSet: GeneralizedTimePayloadDecoder(), useful.UTCTime.tagSet: UTCTimePayloadDecoder() } # Type-to-codec map for ambiguous ASN.1 types TYPE_MAP = { univ.Set.typeId: SetPayloadDecoder(), univ.SetOf.typeId: SetOfPayloadDecoder(), univ.Sequence.typeId: SequencePayloadDecoder(), univ.SequenceOf.typeId: SequenceOfPayloadDecoder(), univ.Choice.typeId: ChoicePayloadDecoder(), univ.Any.typeId: AnyPayloadDecoder() } # Put in non-ambiguous types for faster codec lookup for typeDecoder in TAG_MAP.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in TYPE_MAP: TYPE_MAP[typeId] = typeDecoder (stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec, stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue, stDumpRawValue, stErrorCondition, stStop) = [x for x in range(10)] EOO_SENTINEL = bytes((0, 0)) class SingleItemDecoder(object): defaultErrorState = stErrorCondition #defaultErrorState = stDumpRawValue defaultRawDecoder = AnyPayloadDecoder() supportIndefLength = True TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored): self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP # Tag & TagSet objects caches self._tagCache = {} self._tagSetCache = {} def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, decodeFun=None, substrateFun=None, **options): allowEoo = options.pop('allowEoo', False) if LOG: LOG('decoder called at scope %s with state %d, working with up ' 'to %s octets of substrate: ' '%s' % (debug.scope, state, length, substrate)) # Look for end-of-octets sentinel if allowEoo and self.supportIndefLength: for eoo_candidate in readFromStream(substrate, 2, options): if isinstance(eoo_candidate, SubstrateUnderrunError): yield eoo_candidate if eoo_candidate == EOO_SENTINEL: if LOG: LOG('end-of-octets sentinel found') yield eoo.endOfOctets return else: substrate.seek(-2, os.SEEK_CUR) tagMap = self._tagMap typeMap = self._typeMap tagCache = self._tagCache tagSetCache = self._tagSetCache value = noValue substrate.markedPosition = substrate.tell() while state is not stStop: if state is stDecodeTag: # Decode tag isShortTag = True for firstByte in readFromStream(substrate, 1, options): if isinstance(firstByte, SubstrateUnderrunError): yield firstByte firstOctet = ord(firstByte) try: lastTag = tagCache[firstOctet] except KeyError: integerTag = firstOctet tagClass = integerTag & 0xC0 tagFormat = integerTag & 0x20 tagId = integerTag & 0x1F if tagId == 0x1F: isShortTag = False lengthOctetIdx = 0 tagId = 0 while True: for integerByte in readFromStream(substrate, 1, options): if isinstance(integerByte, SubstrateUnderrunError): yield integerByte if not integerByte: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding' ) integerTag = ord(integerByte) lengthOctetIdx += 1 tagId <<= 7 tagId |= (integerTag & 0x7F) if not integerTag & 0x80: break lastTag = tag.Tag( tagClass=tagClass, tagFormat=tagFormat, tagId=tagId ) if isShortTag: # cache short tags tagCache[firstOctet] = lastTag if tagSet is None: 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 == -1 and not 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 is None: 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 "", state is stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(concreteDecoder is None and '?' 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 is None and '' 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 is not None: 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 "", state is stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) if state is stDecodeValue: if not options.get('recursiveFlag', True) and not 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 in 0.1.4 as 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 if not 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 "", 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: 1 2 3 Decode BER serialisation with ASN.1 schema .. code-block:: pycon >>> stream = io.BytesIO( ... b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') >>> >>> schema = SequenceOf(componentType=Integer()) >>> >>> decoder = StreamingDecoder(stream, asn1Spec=schema) >>> for asn1Object in decoder: ... print(asn1Object) >>> SequenceOf: 1 2 3 """ SINGLE_ITEM_DECODER = SingleItemDecoder def __init__(self, substrate, asn1Spec=None, **options): self._singleItemDecoder = self.SINGLE_ITEM_DECODER(**options) self._substrate = asSeekableStream(substrate) self._asn1Spec = asn1Spec self._options = options def __iter__(self): while True: for asn1Object in self._singleItemDecoder( self._substrate, self._asn1Spec, **self._options): yield asn1Object for chunk in isEndOfStream(self._substrate): if isinstance(chunk, SubstrateUnderrunError): yield break if chunk: break class Decoder(object): """Create a BER decoder object. Parse BER/CER/DER octet-stream into one, possibly nested, ASN.1 object. """ STREAMING_DECODER = StreamingDecoder @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 as 1st argument, the uninterpreted payload as 2nd argument, and the length of the uninterpreted payload as 3rd argument. The streaming variant will additionally receive the decode(..., **options) kwargs as 4th argument. The non-streaming variant shall return an object that will be propagated as decode() return value as 1st item, and the remainig payload for further decode passes as 2nd 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 .. code-block:: pycon >>> s, unprocessed = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03') >>> str(s) SequenceOf: 1 2 3 Decode BER/CER/DER serialisation with ASN.1 schema .. code-block:: pycon >>> seq = SequenceOf(componentType=Integer()) >>> s, unprocessed = decode( b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq) >>> str(s) SequenceOf: 1 2 3 """ substrate = asSeekableStream(substrate) if "substrateFun" in options: origSubstrateFun = options["substrateFun"] def substrateFunWrapper(asn1Object, substrate, length, options=None): """Support both 0.4 and 0.5 style APIs. substrateFun API has changed in 0.5 for use with streaming decoders. To stay backwards compatible, we first try if 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 options["substrateFun"] = substrateFunWrapper streamingDecoder = cls.STREAMING_DECODER( substrate, asn1Spec, **options) for asn1Object in streamingDecoder: if isinstance(asn1Object, SubstrateUnderrunError): raise error.SubstrateUnderrunError('Short substrate on input') try: tail = next(readFromStream(substrate)) except error.EndOfStreamError: tail = b'' return asn1Object, tail @staticmethod def _callSubstrateFunV4asV5(substrateFunV4, asn1Object, substrate, length): substrate_bytes = substrate.read() if length == -1: length = len(substrate_bytes) value, nextSubstrate = substrateFunV4(asn1Object, substrate_bytes, length) nbytes = substrate.write(nextSubstrate) substrate.truncate() substrate.seek(-nbytes, os.SEEK_CUR) 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/ber/encoder.py0000644000175000017500000007214414670137102020243 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import warnings from pyasn1 import debug from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.compat import _MISSING from pyasn1.compat.integer import to_bytes from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import univ from pyasn1.type import useful __all__ = ['Encoder', 'encode'] LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER) class AbstractItemEncoder(object): supportIndefLenMode = True # An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)` eooIntegerSubstrate = (0, 0) eooOctetsSubstrate = bytes(eooIntegerSubstrate) # noinspection PyMethodMayBeStatic def encodeTag(self, singleTag, isConstructed): tagClass, tagFormat, tagId = singleTag encodedTag = tagClass | tagFormat if isConstructed: encodedTag |= tag.tagFormatConstructed if tagId < 31: return encodedTag | tagId, else: substrate = tagId & 0x7f, tagId >>= 7 while tagId: substrate = (0x80 | (tagId & 0x7f),) + substrate tagId >>= 7 return (encodedTag | 0x1F,) + substrate def encodeLength(self, length, defMode): if not defMode and self.supportIndefLenMode: return (0x80,) if length < 0x80: return length, else: substrate = () while length: substrate = (length & 0xff,) + substrate length >>= 8 substrateLen = len(substrate) if substrateLen > 126: raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen) return (0x80 | substrateLen,) + substrate def encodeValue(self, value, asn1Spec, encodeFun, **options): raise error.PyAsn1Error('Not implemented') def encode(self, value, asn1Spec=None, encodeFun=None, **options): if asn1Spec is None: tagSet = value.tagSet else: tagSet = asn1Spec.tagSet # untagged item? if not tagSet: substrate, isConstructed, isOctets = self.encodeValue( value, asn1Spec, encodeFun, **options ) return substrate defMode = options.get('defMode', True) substrate = b'' for idx, singleTag in enumerate(tagSet.superTags): defModeOverride = defMode # base tag? if not idx: try: substrate, isConstructed, isOctets = self.encodeValue( value, asn1Spec, encodeFun, **options ) except error.PyAsn1Error as exc: raise error.PyAsn1Error( 'Error encoding %r: %s' % (value, exc)) if LOG: LOG('encoded %svalue %s into %s' % ( isConstructed and 'constructed ' or '', value, substrate )) if not substrate and isConstructed and options.get('ifNotEmpty', False): return substrate if not isConstructed: defModeOverride = True if LOG: LOG('overridden encoding mode into definitive for primitive type') header = self.encodeTag(singleTag, isConstructed) if LOG: LOG('encoded %stag %s into %s' % ( isConstructed and 'constructed ' or '', singleTag, debug.hexdump(bytes(header)))) header += self.encodeLength(len(substrate), defModeOverride) if LOG: LOG('encoded %s octets (tag + payload) into %s' % ( len(substrate), debug.hexdump(bytes(header)))) if isOctets: substrate = bytes(header) + substrate if not defModeOverride: substrate += self.eooOctetsSubstrate else: substrate = header + substrate if not defModeOverride: substrate += self.eooIntegerSubstrate if not isOctets: substrate = bytes(substrate) return substrate class EndOfOctetsEncoder(AbstractItemEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): return b'', False, True class BooleanEncoder(AbstractItemEncoder): supportIndefLenMode = False def encodeValue(self, value, asn1Spec, encodeFun, **options): return value and (1,) or (0,), False, False class IntegerEncoder(AbstractItemEncoder): supportIndefLenMode = False supportCompactZero = False def encodeValue(self, value, asn1Spec, encodeFun, **options): if value == 0: if LOG: LOG('encoding %spayload for zero INTEGER' % ( self.supportCompactZero and 'no ' or '' )) # de-facto way to encode zero if self.supportCompactZero: return (), False, False else: return (0,), False, False return to_bytes(int(value), signed=True), False, True class BitStringEncoder(AbstractItemEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: # TODO: try to avoid ASN.1 schema instantiation value = asn1Spec.clone(value) valueLength = len(value) if valueLength % 8: alignedValue = value << (8 - valueLength % 8) else: alignedValue = value maxChunkSize = options.get('maxChunkSize', 0) if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8: substrate = alignedValue.asOctets() return bytes((len(substrate) * 8 - valueLength,)) + substrate, False, True if LOG: LOG('encoding into up to %s-octet chunks' % maxChunkSize) baseTag = value.tagSet.baseTag # strip off explicit tags if baseTag: tagSet = tag.TagSet(baseTag, baseTag) else: tagSet = tag.TagSet() alignedValue = alignedValue.clone(tagSet=tagSet) stop = 0 substrate = b'' while stop < valueLength: start = stop stop = min(start + maxChunkSize * 8, valueLength) substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options) return substrate, True, True class OctetStringEncoder(AbstractItemEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: substrate = value.asOctets() elif not isinstance(value, bytes): substrate = asn1Spec.clone(value).asOctets() else: substrate = value maxChunkSize = options.get('maxChunkSize', 0) if not maxChunkSize or len(substrate) <= maxChunkSize: return substrate, False, True if LOG: LOG('encoding into up to %s-octet chunks' % maxChunkSize) # strip off explicit tags for inner chunks if asn1Spec is None: baseTag = value.tagSet.baseTag # strip off explicit tags if baseTag: tagSet = tag.TagSet(baseTag, baseTag) else: tagSet = tag.TagSet() asn1Spec = value.clone(tagSet=tagSet) elif not isinstance(value, bytes): baseTag = asn1Spec.tagSet.baseTag # strip off explicit tags if baseTag: tagSet = tag.TagSet(baseTag, baseTag) else: tagSet = tag.TagSet() asn1Spec = asn1Spec.clone(tagSet=tagSet) pos = 0 substrate = b'' while True: chunk = value[pos:pos + maxChunkSize] if not chunk: break substrate += encodeFun(chunk, asn1Spec, **options) pos += maxChunkSize return substrate, True, True class NullEncoder(AbstractItemEncoder): supportIndefLenMode = False def encodeValue(self, value, asn1Spec, encodeFun, **options): return b'', False, True class ObjectIdentifierEncoder(AbstractItemEncoder): supportIndefLenMode = False def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: value = asn1Spec.clone(value) oid = value.asTuple() # Build the first pair try: first = oid[0] second = oid[1] except IndexError: raise error.PyAsn1Error('Short OID %s' % (value,)) if 0 <= second <= 39: if first == 1: oid = (second + 40,) + oid[2:] elif first == 0: oid = (second,) + oid[2:] elif first == 2: oid = (second + 80,) + oid[2:] else: raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,)) elif first == 2: oid = (second + 80,) + oid[2:] else: raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,)) octets = () # Cycle through subIds for subOid in oid: if 0 <= subOid <= 127: # Optimize for the common case octets += (subOid,) elif subOid > 127: # Pack large Sub-Object IDs res = (subOid & 0x7f,) subOid >>= 7 while subOid: res = (0x80 | (subOid & 0x7f),) + res subOid >>= 7 # Add packed Sub-Object ID to resulted Object ID octets += res else: raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value)) return octets, False, False class RelativeOIDEncoder(AbstractItemEncoder): supportIndefLenMode = False def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: value = asn1Spec.clone(value) octets = () # Cycle through subIds for subOid in value.asTuple(): if 0 <= subOid <= 127: # Optimize for the common case octets += (subOid,) elif subOid > 127: # Pack large Sub-Object IDs res = (subOid & 0x7f,) subOid >>= 7 while subOid: res = (0x80 | (subOid & 0x7f),) + res subOid >>= 7 # Add packed Sub-Object ID to resulted RELATIVE-OID octets += res else: raise error.PyAsn1Error('Negative RELATIVE-OID arc %s at %s' % (subOid, value)) return octets, False, False class RealEncoder(AbstractItemEncoder): supportIndefLenMode = False binEncBase = 2 # set to None to choose encoding base automatically @staticmethod def _dropFloatingPoint(m, encbase, e): ms, es = 1, 1 if m < 0: ms = -1 # mantissa sign if e < 0: es = -1 # exponent sign m *= ms if encbase == 8: m *= 2 ** (abs(e) % 3 * es) e = abs(e) // 3 * es elif encbase == 16: m *= 2 ** (abs(e) % 4 * es) e = abs(e) // 4 * es while True: if int(m) != m: m *= encbase e -= 1 continue break return ms, int(m), encbase, e def _chooseEncBase(self, value): m, b, e = value encBase = [2, 8, 16] if value.binEncBase in encBase: return self._dropFloatingPoint(m, value.binEncBase, e) elif self.binEncBase in encBase: return self._dropFloatingPoint(m, self.binEncBase, e) # auto choosing base 2/8/16 mantissa = [m, m, m] exponent = [e, e, e] sign = 1 encbase = 2 e = float('inf') for i in range(3): (sign, mantissa[i], encBase[i], exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i]) if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m): e = exponent[i] m = int(mantissa[i]) encbase = encBase[i] if LOG: LOG('automatically chosen REAL encoding base %s, sign %s, mantissa %s, ' 'exponent %s' % (encbase, sign, m, e)) return sign, m, encbase, e def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is not None: value = asn1Spec.clone(value) if value.isPlusInf: return (0x40,), False, False if value.isMinusInf: return (0x41,), False, False m, b, e = value if not m: return b'', False, True if b == 10: if LOG: LOG('encoding REAL into character form') return b'\x03%dE%s%d' % (m, e == 0 and b'+' or b'', e), False, True elif b == 2: fo = 0x80 # binary encoding ms, m, encbase, e = self._chooseEncBase(value) if ms < 0: # mantissa sign fo |= 0x40 # sign bit # exponent & mantissa normalization if encbase == 2: while m & 0x1 == 0: m >>= 1 e += 1 elif encbase == 8: while m & 0x7 == 0: m >>= 3 e += 1 fo |= 0x10 else: # encbase = 16 while m & 0xf == 0: m >>= 4 e += 1 fo |= 0x20 sf = 0 # scale factor while m & 0x1 == 0: m >>= 1 sf += 1 if sf > 3: raise error.PyAsn1Error('Scale factor overflow') # bug if raised fo |= sf << 2 eo = b'' if e == 0 or e == -1: eo = bytes((e & 0xff,)) else: while e not in (0, -1): eo = bytes((e & 0xff,)) + eo e >>= 8 if e == 0 and eo and eo[0] & 0x80: eo = bytes((0,)) + eo if e == -1 and eo and not (eo[0] & 0x80): eo = bytes((0xff,)) + eo n = len(eo) if n > 0xff: raise error.PyAsn1Error('Real exponent overflow') if n == 1: pass elif n == 2: fo |= 1 elif n == 3: fo |= 2 else: fo |= 3 eo = bytes((n & 0xff,)) + eo po = b'' while m: po = bytes((m & 0xff,)) + po m >>= 8 substrate = bytes((fo,)) + eo + po return substrate, False, True else: raise error.PyAsn1Error('Prohibited Real base %s' % b) class SequenceEncoder(AbstractItemEncoder): omitEmptyOptionals = False # TODO: handling three flavors of input is too much -- split over codecs def encodeValue(self, value, asn1Spec, encodeFun, **options): substrate = b'' omitEmptyOptionals = options.get( 'omitEmptyOptionals', self.omitEmptyOptionals) if LOG: LOG('%sencoding empty OPTIONAL components' % ( omitEmptyOptionals and 'not ' or '')) if asn1Spec is None: # instance of ASN.1 schema inconsistency = value.isInconsistent if inconsistency: raise error.PyAsn1Error( f"ASN.1 object {value.__class__.__name__} is inconsistent") namedTypes = value.componentType for idx, component in enumerate(value.values()): if namedTypes: namedType = namedTypes[idx] if namedType.isOptional and not component.isValue: if LOG: LOG('not encoding OPTIONAL component %r' % (namedType,)) continue if namedType.isDefaulted and component == namedType.asn1Object: if LOG: LOG('not encoding DEFAULT component %r' % (namedType,)) continue if omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) # wrap open type blob if needed if namedTypes and namedType.openType: wrapType = namedType.asn1Object if wrapType.typeId in ( univ.SetOf.typeId, univ.SequenceOf.typeId): substrate += encodeFun( component, asn1Spec, **dict(options, wrapType=wrapType.componentType)) else: chunk = encodeFun(component, asn1Spec, **options) if wrapType.isSameTypeWith(component): substrate += chunk else: substrate += encodeFun(chunk, wrapType, **options) if LOG: LOG('wrapped with wrap type %r' % (wrapType,)) else: substrate += encodeFun(component, asn1Spec, **options) else: # bare Python value + ASN.1 schema for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): try: component = value[namedType.name] except KeyError: raise error.PyAsn1Error('Component name "%s" not found in %r' % ( namedType.name, value)) if namedType.isOptional and namedType.name not in value: if LOG: LOG('not encoding OPTIONAL component %r' % (namedType,)) continue if namedType.isDefaulted and component == namedType.asn1Object: if LOG: LOG('not encoding DEFAULT component %r' % (namedType,)) continue if omitEmptyOptionals: options.update(ifNotEmpty=namedType.isOptional) componentSpec = namedType.asn1Object # wrap open type blob if needed if namedType.openType: if componentSpec.typeId in ( univ.SetOf.typeId, univ.SequenceOf.typeId): substrate += encodeFun( component, componentSpec, **dict(options, wrapType=componentSpec.componentType)) else: chunk = encodeFun(component, componentSpec, **options) if componentSpec.isSameTypeWith(component): substrate += chunk else: substrate += encodeFun(chunk, componentSpec, **options) if LOG: LOG('wrapped with wrap type %r' % (componentSpec,)) else: substrate += encodeFun(component, componentSpec, **options) return substrate, True, True class SequenceOfEncoder(AbstractItemEncoder): def _encodeComponents(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: inconsistency = value.isInconsistent if inconsistency: raise error.PyAsn1Error( f"ASN.1 object {value.__class__.__name__} is inconsistent") else: asn1Spec = asn1Spec.componentType chunks = [] wrapType = options.pop('wrapType', None) for idx, component in enumerate(value): chunk = encodeFun(component, asn1Spec, **options) if (wrapType is not None and not wrapType.isSameTypeWith(component)): # wrap encoded value with wrapper container (e.g. ANY) chunk = encodeFun(chunk, wrapType, **options) if LOG: LOG('wrapped with wrap type %r' % (wrapType,)) chunks.append(chunk) return chunks def encodeValue(self, value, asn1Spec, encodeFun, **options): chunks = self._encodeComponents( value, asn1Spec, encodeFun, **options) return b''.join(chunks), True, True class ChoiceEncoder(AbstractItemEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: component = value.getComponent() else: names = [namedType.name for namedType in asn1Spec.componentType.namedTypes if namedType.name in value] if len(names) != 1: raise error.PyAsn1Error('%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value)) name = names[0] component = value[name] asn1Spec = asn1Spec[name] return encodeFun(component, asn1Spec, **options), True, True class AnyEncoder(OctetStringEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: value = value.asOctets() elif not isinstance(value, bytes): value = asn1Spec.clone(value).asOctets() return value, not options.get('defMode', True), True TAG_MAP = { eoo.endOfOctets.tagSet: EndOfOctetsEncoder(), univ.Boolean.tagSet: BooleanEncoder(), univ.Integer.tagSet: IntegerEncoder(), univ.BitString.tagSet: BitStringEncoder(), univ.OctetString.tagSet: OctetStringEncoder(), univ.Null.tagSet: NullEncoder(), univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(), univ.RelativeOID.tagSet: RelativeOIDEncoder(), univ.Enumerated.tagSet: IntegerEncoder(), univ.Real.tagSet: RealEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.SequenceOf.tagSet: SequenceOfEncoder(), univ.SetOf.tagSet: SequenceOfEncoder(), univ.Choice.tagSet: ChoiceEncoder(), # character string types char.UTF8String.tagSet: OctetStringEncoder(), char.NumericString.tagSet: OctetStringEncoder(), char.PrintableString.tagSet: OctetStringEncoder(), char.TeletexString.tagSet: OctetStringEncoder(), char.VideotexString.tagSet: OctetStringEncoder(), char.IA5String.tagSet: OctetStringEncoder(), char.GraphicString.tagSet: OctetStringEncoder(), char.VisibleString.tagSet: OctetStringEncoder(), char.GeneralString.tagSet: OctetStringEncoder(), char.UniversalString.tagSet: OctetStringEncoder(), char.BMPString.tagSet: OctetStringEncoder(), # useful types useful.ObjectDescriptor.tagSet: OctetStringEncoder(), useful.GeneralizedTime.tagSet: OctetStringEncoder(), useful.UTCTime.tagSet: OctetStringEncoder() } # Put in ambiguous & non-ambiguous types for faster codec lookup TYPE_MAP = { univ.Boolean.typeId: BooleanEncoder(), univ.Integer.typeId: IntegerEncoder(), univ.BitString.typeId: BitStringEncoder(), univ.OctetString.typeId: OctetStringEncoder(), univ.Null.typeId: NullEncoder(), univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(), univ.RelativeOID.typeId: RelativeOIDEncoder(), univ.Enumerated.typeId: IntegerEncoder(), univ.Real.typeId: RealEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.Set.typeId: SequenceEncoder(), univ.SetOf.typeId: SequenceOfEncoder(), univ.Sequence.typeId: SequenceEncoder(), univ.SequenceOf.typeId: SequenceOfEncoder(), univ.Choice.typeId: ChoiceEncoder(), univ.Any.typeId: AnyEncoder(), # character string types char.UTF8String.typeId: OctetStringEncoder(), char.NumericString.typeId: OctetStringEncoder(), char.PrintableString.typeId: OctetStringEncoder(), char.TeletexString.typeId: OctetStringEncoder(), char.VideotexString.typeId: OctetStringEncoder(), char.IA5String.typeId: OctetStringEncoder(), char.GraphicString.typeId: OctetStringEncoder(), char.VisibleString.typeId: OctetStringEncoder(), char.GeneralString.typeId: OctetStringEncoder(), char.UniversalString.typeId: OctetStringEncoder(), char.BMPString.typeId: OctetStringEncoder(), # useful types useful.ObjectDescriptor.typeId: OctetStringEncoder(), useful.GeneralizedTime.typeId: OctetStringEncoder(), useful.UTCTime.typeId: OctetStringEncoder() } class SingleItemEncoder(object): fixedDefLengthMode = None fixedChunkSize = None TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored): self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP def __call__(self, value, asn1Spec=None, **options): try: if asn1Spec is None: typeId = value.typeId else: typeId = asn1Spec.typeId except AttributeError: raise error.PyAsn1Error('Value %r is not ASN.1 type instance ' 'and "asn1Spec" not given' % (value,)) if LOG: LOG('encoder called in %sdef mode, chunk size %s for type %s, ' 'value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value)) if self.fixedDefLengthMode is not None: options.update(defMode=self.fixedDefLengthMode) if self.fixedChunkSize is not None: options.update(maxChunkSize=self.fixedChunkSize) try: concreteEncoder = self._typeMap[typeId] if LOG: LOG('using value codec %s chosen by type ID ' '%s' % (concreteEncoder.__class__.__name__, typeId)) except KeyError: if asn1Spec is None: tagSet = value.tagSet else: tagSet = asn1Spec.tagSet # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag) try: concreteEncoder = self._tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet)) if LOG: LOG('using value codec %s chosen by tagSet ' '%s' % (concreteEncoder.__class__.__name__, tagSet)) substrate = concreteEncoder.encode(value, asn1Spec, self, **options) if LOG: LOG('codec %s built %s octets of substrate: %s\nencoder ' 'completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate))) return substrate class Encoder(object): SINGLE_ITEM_ENCODER = SingleItemEncoder def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **options): self._singleItemEncoder = self.SINGLE_ITEM_ENCODER( tagMap=tagMap, typeMap=typeMap, **options ) def __call__(self, pyObject, asn1Spec=None, **options): return self._singleItemEncoder( pyObject, asn1Spec=asn1Spec, **options) #: Turns ASN.1 object into BER octet stream. #: #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: walks all its components recursively and produces a BER octet stream. #: #: Parameters #: ---------- #: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` #: parameter is required to guide the encoding process. #: #: Keyword Args #: ------------ #: asn1Spec: #: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: #: defMode: :py:class:`bool` #: If :obj:`False`, produces indefinite length encoding #: #: maxChunkSize: :py:class:`int` #: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size) #: #: Returns #: ------- #: : :py:class:`bytes` #: Given ASN.1 object encoded into BER octetstream #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error #: On encoding errors #: #: Examples #: -------- #: Encode Python value into BER with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> encode([1, 2, 3], asn1Spec=seq) #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' #: #: Encode ASN.1 value object into BER #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> seq.extend([1, 2, 3]) #: >>> encode(seq) #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' #: encode = Encoder() 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/ber/eoo.py0000644000175000017500000000117714525242621017406 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from pyasn1.type import base from pyasn1.type import tag __all__ = ['endOfOctets'] class EndOfOctets(base.SimpleAsn1Type): defaultValue = 0 tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x00) ) _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance endOfOctets = EndOfOctets() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2854316 pyasn1-0.6.1/pyasn1/codec/cer/0000755000175000017500000000000014670145404016247 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/cer/__init__.py0000644000175000017500000000007314525242621020356 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/cer/decoder.py0000644000175000017500000001075514670137102020232 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import warnings from pyasn1 import error from pyasn1.codec.streaming import readFromStream from pyasn1.codec.ber import decoder from pyasn1.type import univ __all__ = ['decode', 'StreamingDecoder'] SubstrateUnderrunError = error.SubstrateUnderrunError class BooleanPayloadDecoder(decoder.AbstractSimplePayloadDecoder): protoComponent = univ.Boolean(0) def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if length != 1: raise error.PyAsn1Error('Not single-octet Boolean payload') for chunk in readFromStream(substrate, length, options): if isinstance(chunk, SubstrateUnderrunError): yield chunk byte = chunk[0] # CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while # BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1 # in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf if byte == 0xff: value = 1 elif byte == 0x00: value = 0 else: raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte) yield self._createComponent(asn1Spec, tagSet, value, **options) # TODO: prohibit non-canonical encoding BitStringPayloadDecoder = decoder.BitStringPayloadDecoder OctetStringPayloadDecoder = decoder.OctetStringPayloadDecoder RealPayloadDecoder = decoder.RealPayloadDecoder TAG_MAP = decoder.TAG_MAP.copy() TAG_MAP.update( {univ.Boolean.tagSet: BooleanPayloadDecoder(), univ.BitString.tagSet: BitStringPayloadDecoder(), univ.OctetString.tagSet: OctetStringPayloadDecoder(), univ.Real.tagSet: RealPayloadDecoder()} ) TYPE_MAP = decoder.TYPE_MAP.copy() # Put in non-ambiguous types for faster codec lookup for typeDecoder in TAG_MAP.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in TYPE_MAP: TYPE_MAP[typeId] = typeDecoder class SingleItemDecoder(decoder.SingleItemDecoder): __doc__ = decoder.SingleItemDecoder.__doc__ TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP class StreamingDecoder(decoder.StreamingDecoder): __doc__ = decoder.StreamingDecoder.__doc__ SINGLE_ITEM_DECODER = SingleItemDecoder class Decoder(decoder.Decoder): __doc__ = decoder.Decoder.__doc__ STREAMING_DECODER = StreamingDecoder #: Turns CER octet stream into an ASN.1 object. #: #: Takes CER 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` #: CER 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 CER 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 #: #: Examples #: -------- #: Decode CER serialisation without ASN.1 schema #: #: .. code-block:: pycon #: #: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00') #: >>> str(s) #: SequenceOf: #: 1 2 3 #: #: Decode CER serialisation with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00', 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/cer/encoder.py0000644000175000017500000002315614670137102020243 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import warnings from pyasn1 import error from pyasn1.codec.ber import encoder from pyasn1.type import univ from pyasn1.type import useful __all__ = ['Encoder', 'encode'] class BooleanEncoder(encoder.IntegerEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if value == 0: substrate = (0,) else: substrate = (255,) return substrate, False, False class RealEncoder(encoder.RealEncoder): def _chooseEncBase(self, value): m, b, e = value return self._dropFloatingPoint(m, b, e) # specialized GeneralStringEncoder here class TimeEncoderMixIn(object): Z_CHAR = ord('Z') PLUS_CHAR = ord('+') MINUS_CHAR = ord('-') COMMA_CHAR = ord(',') DOT_CHAR = ord('.') ZERO_CHAR = ord('0') MIN_LENGTH = 12 MAX_LENGTH = 19 def encodeValue(self, value, asn1Spec, encodeFun, **options): # CER encoding constraints: # - minutes are mandatory, seconds are optional # - sub-seconds must NOT be zero / no meaningless zeros # - no hanging fraction dot # - time in UTC (Z) # - only dot is allowed for fractions if asn1Spec is not None: value = asn1Spec.clone(value) numbers = value.asNumbers() if self.PLUS_CHAR in numbers or self.MINUS_CHAR in numbers: raise error.PyAsn1Error('Must be UTC time: %r' % value) if numbers[-1] != self.Z_CHAR: raise error.PyAsn1Error('Missing "Z" time zone specifier: %r' % value) if self.COMMA_CHAR in numbers: raise error.PyAsn1Error('Comma in fractions disallowed: %r' % value) if self.DOT_CHAR in numbers: isModified = False numbers = list(numbers) searchIndex = min(numbers.index(self.DOT_CHAR) + 4, len(numbers) - 1) while numbers[searchIndex] != self.DOT_CHAR: if numbers[searchIndex] == self.ZERO_CHAR: del numbers[searchIndex] isModified = True searchIndex -= 1 searchIndex += 1 if searchIndex < len(numbers): if numbers[searchIndex] == self.Z_CHAR: # drop hanging comma del numbers[searchIndex - 1] isModified = True if isModified: value = value.clone(numbers) if not self.MIN_LENGTH < len(numbers) < self.MAX_LENGTH: raise error.PyAsn1Error('Length constraint violated: %r' % value) options.update(maxChunkSize=1000) return encoder.OctetStringEncoder.encodeValue( self, value, asn1Spec, encodeFun, **options ) class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): MIN_LENGTH = 12 MAX_LENGTH = 20 class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): MIN_LENGTH = 10 MAX_LENGTH = 14 class SetOfEncoder(encoder.SequenceOfEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): chunks = self._encodeComponents( value, asn1Spec, encodeFun, **options) # sort by serialised and padded components if len(chunks) > 1: zero = b'\x00' maxLen = max(map(len, chunks)) paddedChunks = [ (x.ljust(maxLen, zero), x) for x in chunks ] paddedChunks.sort(key=lambda x: x[0]) chunks = [x[1] for x in paddedChunks] return b''.join(chunks), True, True class SequenceOfEncoder(encoder.SequenceOfEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): if options.get('ifNotEmpty', False) and not len(value): return b'', True, True chunks = self._encodeComponents( value, asn1Spec, encodeFun, **options) return b''.join(chunks), True, True class SetEncoder(encoder.SequenceEncoder): @staticmethod def _componentSortKey(componentAndType): """Sort SET components by tag Sort regardless of the Choice value (static sort) """ component, asn1Spec = componentAndType if asn1Spec is None: asn1Spec = component if asn1Spec.typeId == univ.Choice.typeId and not asn1Spec.tagSet: if asn1Spec.tagSet: return asn1Spec.tagSet else: return asn1Spec.componentType.minTagSet else: return asn1Spec.tagSet def encodeValue(self, value, asn1Spec, encodeFun, **options): substrate = b'' comps = [] compsMap = {} if asn1Spec is None: # instance of ASN.1 schema inconsistency = value.isInconsistent if inconsistency: raise error.PyAsn1Error( f"ASN.1 object {value.__class__.__name__} is inconsistent") namedTypes = value.componentType for idx, component in enumerate(value.values()): if namedTypes: namedType = namedTypes[idx] if namedType.isOptional and not component.isValue: continue if namedType.isDefaulted and component == namedType.asn1Object: continue compsMap[id(component)] = namedType else: compsMap[id(component)] = None comps.append((component, asn1Spec)) else: # bare Python value + ASN.1 schema for idx, namedType in enumerate(asn1Spec.componentType.namedTypes): try: component = value[namedType.name] except KeyError: raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value)) if namedType.isOptional and namedType.name not in value: continue if namedType.isDefaulted and component == namedType.asn1Object: continue compsMap[id(component)] = namedType comps.append((component, asn1Spec[idx])) for comp, compType in sorted(comps, key=self._componentSortKey): namedType = compsMap[id(comp)] if namedType: options.update(ifNotEmpty=namedType.isOptional) chunk = encodeFun(comp, compType, **options) # wrap open type blob if needed if namedType and namedType.openType: wrapType = namedType.asn1Object if wrapType.tagSet and not wrapType.isSameTypeWith(comp): chunk = encodeFun(chunk, wrapType, **options) substrate += chunk return substrate, True, True class SequenceEncoder(encoder.SequenceEncoder): omitEmptyOptionals = True TAG_MAP = encoder.TAG_MAP.copy() TAG_MAP.update({ univ.Boolean.tagSet: BooleanEncoder(), univ.Real.tagSet: RealEncoder(), useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(), useful.UTCTime.tagSet: UTCTimeEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.SetOf.tagSet: SetOfEncoder(), univ.Sequence.typeId: SequenceEncoder() }) TYPE_MAP = encoder.TYPE_MAP.copy() TYPE_MAP.update({ univ.Boolean.typeId: BooleanEncoder(), univ.Real.typeId: RealEncoder(), useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(), useful.UTCTime.typeId: UTCTimeEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.Set.typeId: SetEncoder(), univ.SetOf.typeId: SetOfEncoder(), univ.Sequence.typeId: SequenceEncoder(), univ.SequenceOf.typeId: SequenceOfEncoder() }) class SingleItemEncoder(encoder.SingleItemEncoder): fixedDefLengthMode = False fixedChunkSize = 1000 TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP class Encoder(encoder.Encoder): SINGLE_ITEM_ENCODER = SingleItemEncoder #: Turns ASN.1 object into CER octet stream. #: #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: walks all its components recursively and produces a CER octet stream. #: #: Parameters #: ---------- #: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` #: parameter is required to guide the encoding process. #: #: Keyword Args #: ------------ #: asn1Spec: #: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: #: Returns #: ------- #: : :py:class:`bytes` #: Given ASN.1 object encoded into BER octet-stream #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error #: On encoding errors #: #: Examples #: -------- #: Encode Python value into CER with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> encode([1, 2, 3], asn1Spec=seq) #: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00' #: #: Encode ASN.1 value object into CER #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> seq.extend([1, 2, 3]) #: >>> encode(seq) #: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00' #: encode = Encoder() # EncoderFactory queries class instance and builds a map of tags -> encoders 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2864316 pyasn1-0.6.1/pyasn1/codec/der/0000755000175000017500000000000014670145404016250 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/der/__init__.py0000644000175000017500000000007314525242621020357 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/der/decoder.py0000644000175000017500000000654414670137102020234 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import warnings from pyasn1.codec.cer import decoder from pyasn1.type import univ __all__ = ['decode', 'StreamingDecoder'] class BitStringPayloadDecoder(decoder.BitStringPayloadDecoder): supportConstructedForm = False class OctetStringPayloadDecoder(decoder.OctetStringPayloadDecoder): supportConstructedForm = False # TODO: prohibit non-canonical encoding RealPayloadDecoder = decoder.RealPayloadDecoder TAG_MAP = decoder.TAG_MAP.copy() TAG_MAP.update( {univ.BitString.tagSet: BitStringPayloadDecoder(), univ.OctetString.tagSet: OctetStringPayloadDecoder(), univ.Real.tagSet: RealPayloadDecoder()} ) TYPE_MAP = decoder.TYPE_MAP.copy() # Put in non-ambiguous types for faster codec lookup for typeDecoder in TAG_MAP.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in TYPE_MAP: TYPE_MAP[typeId] = typeDecoder class SingleItemDecoder(decoder.SingleItemDecoder): __doc__ = decoder.SingleItemDecoder.__doc__ TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP supportIndefLength = False class StreamingDecoder(decoder.StreamingDecoder): __doc__ = decoder.StreamingDecoder.__doc__ SINGLE_ITEM_DECODER = SingleItemDecoder class Decoder(decoder.Decoder): __doc__ = decoder.Decoder.__doc__ STREAMING_DECODER = StreamingDecoder #: Turns DER octet stream into an ASN.1 object. #: #: Takes DER 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` #: DER 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 DER 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 #: #: Examples #: -------- #: Decode DER 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 DER 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/der/encoder.py0000644000175000017500000000662714670137102020250 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import warnings from pyasn1 import error from pyasn1.codec.cer import encoder from pyasn1.type import univ __all__ = ['Encoder', 'encode'] class SetEncoder(encoder.SetEncoder): @staticmethod def _componentSortKey(componentAndType): """Sort SET components by tag Sort depending on the actual Choice value (dynamic sort) """ component, asn1Spec = componentAndType if asn1Spec is None: compType = component else: compType = asn1Spec if compType.typeId == univ.Choice.typeId and not compType.tagSet: if asn1Spec is None: return component.getComponent().tagSet else: # TODO: move out of sorting key function names = [namedType.name for namedType in asn1Spec.componentType.namedTypes if namedType.name in component] if len(names) != 1: raise error.PyAsn1Error( '%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', component)) # TODO: support nested CHOICE ordering return asn1Spec[names[0]].tagSet else: return compType.tagSet TAG_MAP = encoder.TAG_MAP.copy() TAG_MAP.update({ # Set & SetOf have same tags univ.Set.tagSet: SetEncoder() }) TYPE_MAP = encoder.TYPE_MAP.copy() TYPE_MAP.update({ # Set & SetOf have same tags univ.Set.typeId: SetEncoder() }) class SingleItemEncoder(encoder.SingleItemEncoder): fixedDefLengthMode = True fixedChunkSize = 0 TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP class Encoder(encoder.Encoder): SINGLE_ITEM_ENCODER = SingleItemEncoder #: Turns ASN.1 object into DER octet stream. #: #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: walks all its components recursively and produces a DER octet stream. #: #: Parameters #: ---------- #: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: A Python or pyasn1 object to encode. If Python object is given, `asnSpec` #: parameter is required to guide the encoding process. #: #: Keyword Args #: ------------ #: asn1Spec: #: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: #: Returns #: ------- #: : :py:class:`bytes` #: Given ASN.1 object encoded into BER octet-stream #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error #: On encoding errors #: #: Examples #: -------- #: Encode Python value into DER with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> encode([1, 2, 3], asn1Spec=seq) #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' #: #: Encode ASN.1 value object into DER #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> seq.extend([1, 2, 3]) #: >>> encode(seq) #: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03' #: encode = Encoder() 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) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2864316 pyasn1-0.6.1/pyasn1/codec/native/0000755000175000017500000000000014670145404016764 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/codec/native/__init__.py0000644000175000017500000000007314525242621021073 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/native/decoder.py0000644000175000017500000002163614670137102020747 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import warnings from pyasn1 import debug from pyasn1 import error from pyasn1.compat import _MISSING from pyasn1.type import base from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import univ from pyasn1.type import useful __all__ = ['decode'] LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) class AbstractScalarPayloadDecoder(object): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(pyObject) class BitStringPayloadDecoder(AbstractScalarPayloadDecoder): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject)) class SequenceOrSetPayloadDecoder(object): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() componentsTypes = asn1Spec.componentType for field in asn1Value: if field in pyObject: asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) return asn1Value class SequenceOfOrSetOfPayloadDecoder(object): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() for pyValue in pyObject: asn1Value.append(decodeFun(pyValue, asn1Spec.componentType), **options) return asn1Value class ChoicePayloadDecoder(object): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() componentsTypes = asn1Spec.componentType for field in pyObject: if field in componentsTypes: asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) break return asn1Value TAG_MAP = { univ.Integer.tagSet: AbstractScalarPayloadDecoder(), univ.Boolean.tagSet: AbstractScalarPayloadDecoder(), univ.BitString.tagSet: BitStringPayloadDecoder(), univ.OctetString.tagSet: AbstractScalarPayloadDecoder(), univ.Null.tagSet: AbstractScalarPayloadDecoder(), univ.ObjectIdentifier.tagSet: AbstractScalarPayloadDecoder(), univ.RelativeOID.tagSet: AbstractScalarPayloadDecoder(), univ.Enumerated.tagSet: AbstractScalarPayloadDecoder(), univ.Real.tagSet: AbstractScalarPayloadDecoder(), univ.Sequence.tagSet: SequenceOrSetPayloadDecoder(), # conflicts with SequenceOf univ.Set.tagSet: SequenceOrSetPayloadDecoder(), # conflicts with SetOf univ.Choice.tagSet: ChoicePayloadDecoder(), # conflicts with Any # character string types char.UTF8String.tagSet: AbstractScalarPayloadDecoder(), char.NumericString.tagSet: AbstractScalarPayloadDecoder(), char.PrintableString.tagSet: AbstractScalarPayloadDecoder(), char.TeletexString.tagSet: AbstractScalarPayloadDecoder(), char.VideotexString.tagSet: AbstractScalarPayloadDecoder(), char.IA5String.tagSet: AbstractScalarPayloadDecoder(), char.GraphicString.tagSet: AbstractScalarPayloadDecoder(), char.VisibleString.tagSet: AbstractScalarPayloadDecoder(), char.GeneralString.tagSet: AbstractScalarPayloadDecoder(), char.UniversalString.tagSet: AbstractScalarPayloadDecoder(), char.BMPString.tagSet: AbstractScalarPayloadDecoder(), # useful types useful.ObjectDescriptor.tagSet: AbstractScalarPayloadDecoder(), useful.GeneralizedTime.tagSet: AbstractScalarPayloadDecoder(), useful.UTCTime.tagSet: AbstractScalarPayloadDecoder() } # Put in ambiguous & non-ambiguous types for faster codec lookup TYPE_MAP = { univ.Integer.typeId: AbstractScalarPayloadDecoder(), univ.Boolean.typeId: AbstractScalarPayloadDecoder(), univ.BitString.typeId: BitStringPayloadDecoder(), univ.OctetString.typeId: AbstractScalarPayloadDecoder(), univ.Null.typeId: AbstractScalarPayloadDecoder(), univ.ObjectIdentifier.typeId: AbstractScalarPayloadDecoder(), univ.RelativeOID.typeId: AbstractScalarPayloadDecoder(), univ.Enumerated.typeId: AbstractScalarPayloadDecoder(), univ.Real.typeId: AbstractScalarPayloadDecoder(), # ambiguous base types univ.Set.typeId: SequenceOrSetPayloadDecoder(), univ.SetOf.typeId: SequenceOfOrSetOfPayloadDecoder(), univ.Sequence.typeId: SequenceOrSetPayloadDecoder(), univ.SequenceOf.typeId: SequenceOfOrSetOfPayloadDecoder(), univ.Choice.typeId: ChoicePayloadDecoder(), univ.Any.typeId: AbstractScalarPayloadDecoder(), # character string types char.UTF8String.typeId: AbstractScalarPayloadDecoder(), char.NumericString.typeId: AbstractScalarPayloadDecoder(), char.PrintableString.typeId: AbstractScalarPayloadDecoder(), char.TeletexString.typeId: AbstractScalarPayloadDecoder(), char.VideotexString.typeId: AbstractScalarPayloadDecoder(), char.IA5String.typeId: AbstractScalarPayloadDecoder(), char.GraphicString.typeId: AbstractScalarPayloadDecoder(), char.VisibleString.typeId: AbstractScalarPayloadDecoder(), char.GeneralString.typeId: AbstractScalarPayloadDecoder(), char.UniversalString.typeId: AbstractScalarPayloadDecoder(), char.BMPString.typeId: AbstractScalarPayloadDecoder(), # useful types useful.ObjectDescriptor.typeId: AbstractScalarPayloadDecoder(), useful.GeneralizedTime.typeId: AbstractScalarPayloadDecoder(), useful.UTCTime.typeId: AbstractScalarPayloadDecoder() } class SingleItemDecoder(object): TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored): self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP def __call__(self, pyObject, asn1Spec, **options): if LOG: debug.scope.push(type(pyObject).__name__) LOG('decoder called at scope %s, working with ' 'type %s' % (debug.scope, type(pyObject).__name__)) if asn1Spec is None or not isinstance(asn1Spec, base.Asn1Item): raise error.PyAsn1Error( 'asn1Spec is not valid (should be an instance of an ASN.1 ' 'Item, not %s)' % asn1Spec.__class__.__name__) try: valueDecoder = self._typeMap[asn1Spec.typeId] except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag) try: valueDecoder = self._tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('Unknown ASN.1 tag %s' % asn1Spec.tagSet) if LOG: LOG('calling decoder %s on Python type %s ' '<%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject))) value = valueDecoder(pyObject, asn1Spec, self, **options) if LOG: LOG('decoder %s produced ASN.1 type %s ' '<%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value))) debug.scope.pop() return value class Decoder(object): SINGLE_ITEM_DECODER = SingleItemDecoder def __init__(self, **options): self._singleItemDecoder = self.SINGLE_ITEM_DECODER(**options) def __call__(self, pyObject, asn1Spec=None, **kwargs): return self._singleItemDecoder(pyObject, asn1Spec=asn1Spec, **kwargs) #: Turns Python objects of built-in types into ASN.1 objects. #: #: Takes Python objects of built-in types and turns them into a tree of #: ASN.1 objects (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which #: may be a scalar or an arbitrary nested structure. #: #: Parameters #: ---------- #: pyObject: :py:class:`object` #: A scalar or nested Python objects #: #: 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. It is required #: for successful interpretation of Python objects mapping into their ASN.1 #: representations. #: #: Returns #: ------- #: : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: A scalar or constructed pyasn1 object #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error #: On decoding errors #: #: Examples #: -------- #: Decode native Python object into ASN.1 objects with ASN.1 schema #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> s, _ = decode([1, 2, 3], 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/native/encoder.py0000644000175000017500000002174014670137102020755 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from collections import OrderedDict import warnings from pyasn1 import debug from pyasn1 import error from pyasn1.compat import _MISSING from pyasn1.type import base from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import univ from pyasn1.type import useful __all__ = ['encode'] LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_ENCODER) class AbstractItemEncoder(object): def encode(self, value, encodeFun, **options): raise error.PyAsn1Error('Not implemented') class BooleanEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return bool(value) class IntegerEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return int(value) class BitStringEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return str(value) class OctetStringEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return value.asOctets() class TextStringEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return str(value) class NullEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return None class ObjectIdentifierEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return str(value) class RelativeOIDEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return str(value) class RealEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return float(value) class SetEncoder(AbstractItemEncoder): protoDict = dict def encode(self, value, encodeFun, **options): inconsistency = value.isInconsistent if inconsistency: raise error.PyAsn1Error( f"ASN.1 object {value.__class__.__name__} is inconsistent") namedTypes = value.componentType substrate = self.protoDict() for idx, (key, subValue) in enumerate(value.items()): if namedTypes and namedTypes[idx].isOptional and not value[idx].isValue: continue substrate[key] = encodeFun(subValue, **options) return substrate class SequenceEncoder(SetEncoder): protoDict = OrderedDict class SequenceOfEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): inconsistency = value.isInconsistent if inconsistency: raise error.PyAsn1Error( f"ASN.1 object {value.__class__.__name__} is inconsistent") return [encodeFun(x, **options) for x in value] class ChoiceEncoder(SequenceEncoder): pass class AnyEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return value.asOctets() TAG_MAP = { univ.Boolean.tagSet: BooleanEncoder(), univ.Integer.tagSet: IntegerEncoder(), univ.BitString.tagSet: BitStringEncoder(), univ.OctetString.tagSet: OctetStringEncoder(), univ.Null.tagSet: NullEncoder(), univ.ObjectIdentifier.tagSet: ObjectIdentifierEncoder(), univ.RelativeOID.tagSet: RelativeOIDEncoder(), univ.Enumerated.tagSet: IntegerEncoder(), univ.Real.tagSet: RealEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.SequenceOf.tagSet: SequenceOfEncoder(), univ.SetOf.tagSet: SequenceOfEncoder(), univ.Choice.tagSet: ChoiceEncoder(), # character string types char.UTF8String.tagSet: TextStringEncoder(), char.NumericString.tagSet: TextStringEncoder(), char.PrintableString.tagSet: TextStringEncoder(), char.TeletexString.tagSet: TextStringEncoder(), char.VideotexString.tagSet: TextStringEncoder(), char.IA5String.tagSet: TextStringEncoder(), char.GraphicString.tagSet: TextStringEncoder(), char.VisibleString.tagSet: TextStringEncoder(), char.GeneralString.tagSet: TextStringEncoder(), char.UniversalString.tagSet: TextStringEncoder(), char.BMPString.tagSet: TextStringEncoder(), # useful types useful.ObjectDescriptor.tagSet: OctetStringEncoder(), useful.GeneralizedTime.tagSet: OctetStringEncoder(), useful.UTCTime.tagSet: OctetStringEncoder() } # Put in ambiguous & non-ambiguous types for faster codec lookup TYPE_MAP = { univ.Boolean.typeId: BooleanEncoder(), univ.Integer.typeId: IntegerEncoder(), univ.BitString.typeId: BitStringEncoder(), univ.OctetString.typeId: OctetStringEncoder(), univ.Null.typeId: NullEncoder(), univ.ObjectIdentifier.typeId: ObjectIdentifierEncoder(), univ.RelativeOID.typeId: RelativeOIDEncoder(), univ.Enumerated.typeId: IntegerEncoder(), univ.Real.typeId: RealEncoder(), # Sequence & Set have same tags as SequenceOf & SetOf univ.Set.typeId: SetEncoder(), univ.SetOf.typeId: SequenceOfEncoder(), univ.Sequence.typeId: SequenceEncoder(), univ.SequenceOf.typeId: SequenceOfEncoder(), univ.Choice.typeId: ChoiceEncoder(), univ.Any.typeId: AnyEncoder(), # character string types char.UTF8String.typeId: OctetStringEncoder(), char.NumericString.typeId: OctetStringEncoder(), char.PrintableString.typeId: OctetStringEncoder(), char.TeletexString.typeId: OctetStringEncoder(), char.VideotexString.typeId: OctetStringEncoder(), char.IA5String.typeId: OctetStringEncoder(), char.GraphicString.typeId: OctetStringEncoder(), char.VisibleString.typeId: OctetStringEncoder(), char.GeneralString.typeId: OctetStringEncoder(), char.UniversalString.typeId: OctetStringEncoder(), char.BMPString.typeId: OctetStringEncoder(), # useful types useful.ObjectDescriptor.typeId: OctetStringEncoder(), useful.GeneralizedTime.typeId: OctetStringEncoder(), useful.UTCTime.typeId: OctetStringEncoder() } class SingleItemEncoder(object): TAG_MAP = TAG_MAP TYPE_MAP = TYPE_MAP def __init__(self, tagMap=_MISSING, typeMap=_MISSING, **ignored): self._tagMap = tagMap if tagMap is not _MISSING else self.TAG_MAP self._typeMap = typeMap if typeMap is not _MISSING else self.TYPE_MAP def __call__(self, value, **options): if not isinstance(value, base.Asn1Item): raise error.PyAsn1Error( 'value is not valid (should be an instance of an ASN.1 Item)') if LOG: debug.scope.push(type(value).__name__) LOG('encoder called for type %s ' '<%s>' % (type(value).__name__, value.prettyPrint())) tagSet = value.tagSet try: concreteEncoder = self._typeMap[value.typeId] except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet( value.tagSet.baseTag, value.tagSet.baseTag) try: concreteEncoder = self._tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %s' % (value,)) if LOG: LOG('using value codec %s chosen by ' '%s' % (concreteEncoder.__class__.__name__, tagSet)) pyObject = concreteEncoder.encode(value, self, **options) if LOG: LOG('encoder %s produced: ' '%s' % (type(concreteEncoder).__name__, repr(pyObject))) debug.scope.pop() return pyObject class Encoder(object): SINGLE_ITEM_ENCODER = SingleItemEncoder def __init__(self, **options): self._singleItemEncoder = self.SINGLE_ITEM_ENCODER(**options) def __call__(self, pyObject, asn1Spec=None, **options): return self._singleItemEncoder( pyObject, asn1Spec=asn1Spec, **options) #: Turns ASN.1 object into a Python built-in type object(s). #: #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: walks all its components recursively and produces a Python built-in type or a tree #: of those. #: #: One exception is that instead of :py:class:`dict`, the :py:class:`OrderedDict` #: is used to preserve ordering of the components in ASN.1 SEQUENCE. #: #: Parameters #: ---------- # asn1Value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) #: pyasn1 object to encode (or a tree of them) #: #: Returns #: ------- #: : :py:class:`object` #: Python built-in type instance (or a tree of them) #: #: Raises #: ------ #: ~pyasn1.error.PyAsn1Error #: On encoding errors #: #: Examples #: -------- #: Encode ASN.1 value object into native Python types #: #: .. code-block:: pycon #: #: >>> seq = SequenceOf(componentType=Integer()) #: >>> seq.extend([1, 2, 3]) #: >>> encode(seq) #: [1, 2, 3] #: encode = SingleItemEncoder() 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) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/codec/streaming.py0000644000175000017500000001435114670137102020041 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import io import os from pyasn1 import error from pyasn1.type import univ class CachingStreamWrapper(io.IOBase): """Wrapper around non-seekable streams. Note that the implementation is tied to the decoder, not checking for dangerous arguments for the sake of performance. The read bytes are kept in an internal cache until setting _markedPosition which may reset the cache. """ def __init__(self, raw): self._raw = raw self._cache = io.BytesIO() self._markedPosition = 0 def peek(self, n): result = self.read(n) self._cache.seek(-len(result), os.SEEK_CUR) return result def seekable(self): return True def seek(self, n=-1, whence=os.SEEK_SET): # Note that this not safe for seeking forward. return self._cache.seek(n, whence) def read(self, n=-1): read_from_cache = self._cache.read(n) if n != -1: n -= len(read_from_cache) if not n: # 0 bytes left to read return read_from_cache read_from_raw = self._raw.read(n) self._cache.write(read_from_raw) return read_from_cache + read_from_raw @property def markedPosition(self): """Position where the currently processed element starts. This is used for back-tracking in SingleItemDecoder.__call__ and (indefLen)ValueDecoder and should not be used for other purposes. The client is not supposed to ever seek before this position. """ return self._markedPosition @markedPosition.setter def markedPosition(self, value): # By setting the value, we ensure we won't seek back before it. # `value` should be the same as the current position # We don't check for this for performance reasons. self._markedPosition = value # Whenever we set _marked_position, we know for sure # that we will not return back, and thus it is # safe to drop all cached data. if self._cache.tell() > io.DEFAULT_BUFFER_SIZE: self._cache = io.BytesIO(self._cache.read()) self._markedPosition = 0 def tell(self): return self._cache.tell() def asSeekableStream(substrate): """Convert object to seekable byte-stream. Parameters ---------- substrate: :py:class:`bytes` or :py:class:`io.IOBase` or :py:class:`univ.OctetString` Returns ------- : :py:class:`io.IOBase` Raises ------ : :py:class:`~pyasn1.error.PyAsn1Error` If the supplied substrate cannot be converted to a seekable stream. """ if isinstance(substrate, io.BytesIO): return substrate elif isinstance(substrate, bytes): return io.BytesIO(substrate) elif isinstance(substrate, univ.OctetString): return io.BytesIO(substrate.asOctets()) try: if substrate.seekable(): # Will fail for most invalid types return substrate else: return CachingStreamWrapper(substrate) except AttributeError: raise error.UnsupportedSubstrateError( "Cannot convert " + substrate.__class__.__name__ + " to a seekable bit stream.") def isEndOfStream(substrate): """Check whether we have reached the end of a stream. Although it is more effective to read and catch exceptions, this function Parameters ---------- substrate: :py:class:`IOBase` Stream to check Returns ------- : :py:class:`bool` """ if isinstance(substrate, io.BytesIO): cp = substrate.tell() substrate.seek(0, os.SEEK_END) result = substrate.tell() == cp substrate.seek(cp, os.SEEK_SET) yield result else: received = substrate.read(1) if received is None: yield if received: substrate.seek(-1, os.SEEK_CUR) yield not received def peekIntoStream(substrate, size=-1): """Peek into stream. Parameters ---------- substrate: :py:class:`IOBase` Stream to read from. size: :py:class:`int` How many bytes to peek (-1 = all available) Returns ------- : :py:class:`bytes` or :py:class:`str` The return type depends on Python major version """ if hasattr(substrate, "peek"): received = substrate.peek(size) if received is None: yield while len(received) < size: yield yield received else: current_position = substrate.tell() try: for chunk in readFromStream(substrate, size): yield chunk finally: substrate.seek(current_position) def readFromStream(substrate, size=-1, context=None): """Read from the stream. Parameters ---------- substrate: :py:class:`IOBase` Stream to read from. Keyword parameters ------------------ size: :py:class:`int` How many bytes to read (-1 = all available) context: :py:class:`dict` Opaque caller context will be attached to exception objects created by this function. Yields ------ : :py:class:`bytes` or :py:class:`str` or :py:class:`SubstrateUnderrunError` Read data or :py:class:`~pyasn1.error.SubstrateUnderrunError` object if no `size` bytes is readily available in the stream. The data type depends on Python major version Raises ------ : :py:class:`~pyasn1.error.EndOfStreamError` Input stream is exhausted """ while True: # this will block unless stream is non-blocking received = substrate.read(size) if received is None: # non-blocking stream can do this yield error.SubstrateUnderrunError(context=context) elif not received and size != 0: # end-of-stream raise error.EndOfStreamError(context=context) elif len(received) < size: substrate.seek(-len(received), os.SEEK_CUR) # behave like a non-blocking stream yield error.SubstrateUnderrunError(context=context) else: break yield received ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2874317 pyasn1-0.6.1/pyasn1/compat/0000755000175000017500000000000014670145404015704 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/compat/__init__.py0000644000175000017500000000016014525242621020010 0ustar00spichugispichugi# This file is necessary to make this directory a package. # sentinal for missing argument _MISSING = object() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/compat/integer.py0000644000175000017500000000062414670137102017711 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # def to_bytes(value, signed=False, length=0): length = max(value.bit_length(), length) if signed and length % 8 == 0: length += 1 return value.to_bytes(length // 8 + (length % 8 and 1 or 0), 'big', signed=signed) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/debug.py0000644000175000017500000000664614670137102016071 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import logging import sys from pyasn1 import __version__ from pyasn1 import error __all__ = ['Debug', 'setLogger', 'hexdump'] DEBUG_NONE = 0x0000 DEBUG_ENCODER = 0x0001 DEBUG_DECODER = 0x0002 DEBUG_ALL = 0xffff FLAG_MAP = { 'none': DEBUG_NONE, 'encoder': DEBUG_ENCODER, 'decoder': DEBUG_DECODER, 'all': DEBUG_ALL } LOGGEE_MAP = {} class Printer(object): # noinspection PyShadowingNames def __init__(self, logger=None, handler=None, formatter=None): if logger is None: logger = logging.getLogger('pyasn1') logger.setLevel(logging.DEBUG) if handler is None: handler = logging.StreamHandler() if formatter is None: formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s') handler.setFormatter(formatter) handler.setLevel(logging.DEBUG) logger.addHandler(handler) self.__logger = logger def __call__(self, msg): self.__logger.debug(msg) def __str__(self): return '' class Debug(object): defaultPrinter = Printer() def __init__(self, *flags, **options): self._flags = DEBUG_NONE if 'loggerName' in options: # route our logs to parent logger self._printer = Printer( logger=logging.getLogger(options['loggerName']), handler=logging.NullHandler() ) elif 'printer' in options: self._printer = options.get('printer') else: self._printer = self.defaultPrinter self._printer('running pyasn1 %s, debug flags %s' % (__version__, ', '.join(flags))) for flag in flags: inverse = flag and flag[0] in ('!', '~') if inverse: flag = flag[1:] try: if inverse: self._flags &= ~FLAG_MAP[flag] else: self._flags |= FLAG_MAP[flag] except KeyError: raise error.PyAsn1Error('bad debug flag %s' % flag) self._printer("debug category '%s' %s" % (flag, inverse and 'disabled' or 'enabled')) def __str__(self): return 'logger %s, flags %x' % (self._printer, self._flags) def __call__(self, msg): self._printer(msg) def __and__(self, flag): return self._flags & flag def __rand__(self, flag): return flag & self._flags _LOG = DEBUG_NONE def setLogger(userLogger): global _LOG if userLogger: _LOG = userLogger else: _LOG = DEBUG_NONE # Update registered logging clients for module, (name, flags) in LOGGEE_MAP.items(): setattr(module, name, _LOG & flags and _LOG or DEBUG_NONE) def registerLoggee(module, name='LOG', flags=DEBUG_NONE): LOGGEE_MAP[sys.modules[module]] = name, flags setLogger(_LOG) return _LOG def hexdump(octets): return ' '.join( ['%s%.2X' % (n % 16 == 0 and ('\n%.5d: ' % n) or '', x) for n, x in zip(range(len(octets)), octets)] ) class Scope(object): def __init__(self): self._list = [] def __str__(self): return '.'.join(self._list) def push(self, token): self._list.append(token) def pop(self): return self._list.pop() scope = Scope() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/error.py0000644000175000017500000000627214525242621016131 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # class PyAsn1Error(Exception): """Base pyasn1 exception `PyAsn1Error` is the base exception class (based on :class:`Exception`) that represents all possible ASN.1 related errors. Parameters ---------- args: Opaque positional parameters Keyword Args ------------ kwargs: Opaque keyword parameters """ def __init__(self, *args, **kwargs): self._args = args self._kwargs = kwargs @property def context(self): """Return exception context When exception object is created, the caller can supply some opaque context for the upper layers to better understand the cause of the exception. Returns ------- : :py:class:`dict` Dict holding context specific data """ return self._kwargs.get('context', {}) class ValueConstraintError(PyAsn1Error): """ASN.1 type constraints violation exception The `ValueConstraintError` exception indicates an ASN.1 value constraint violation. It might happen on value object instantiation (for scalar types) or on serialization (for constructed types). """ class SubstrateUnderrunError(PyAsn1Error): """ASN.1 data structure deserialization error The `SubstrateUnderrunError` exception indicates insufficient serialised data on input of a de-serialization codec. """ class EndOfStreamError(SubstrateUnderrunError): """ASN.1 data structure deserialization error The `EndOfStreamError` exception indicates the condition of the input stream has been closed. """ class UnsupportedSubstrateError(PyAsn1Error): """Unsupported substrate type to parse as ASN.1 data.""" class PyAsn1UnicodeError(PyAsn1Error, UnicodeError): """Unicode text processing error The `PyAsn1UnicodeError` exception is a base class for errors relating to unicode text de/serialization. Apart from inheriting from :class:`PyAsn1Error`, it also inherits from :class:`UnicodeError` to help the caller catching unicode-related errors. """ def __init__(self, message, unicode_error=None): if isinstance(unicode_error, UnicodeError): UnicodeError.__init__(self, *unicode_error.args) PyAsn1Error.__init__(self, message) class PyAsn1UnicodeDecodeError(PyAsn1UnicodeError, UnicodeDecodeError): """Unicode text decoding error The `PyAsn1UnicodeDecodeError` exception represents a failure to deserialize unicode text. Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits from :class:`UnicodeDecodeError` to help the caller catching unicode-related errors. """ class PyAsn1UnicodeEncodeError(PyAsn1UnicodeError, UnicodeEncodeError): """Unicode text encoding error The `PyAsn1UnicodeEncodeError` exception represents a failure to serialize unicode text. Apart from inheriting from :class:`PyAsn1UnicodeError`, it also inherits from :class:`UnicodeEncodeError` to help the caller catching unicode-related errors. """ ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2894316 pyasn1-0.6.1/pyasn1/type/0000755000175000017500000000000014670145404015402 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/type/__init__.py0000644000175000017500000000007314525242621017511 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/base.py0000644000175000017500000005304214670137102016666 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys from pyasn1 import error from pyasn1.type import constraint from pyasn1.type import tag from pyasn1.type import tagmap __all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type', 'ConstructedAsn1Type'] class Asn1Item(object): @classmethod def getTypeId(cls, increment=1): try: Asn1Item._typeCounter += increment except AttributeError: Asn1Item._typeCounter = increment return Asn1Item._typeCounter class Asn1Type(Asn1Item): """Base class for all classes representing ASN.1 types. In the user code, |ASN.1| class is normally used only for telling ASN.1 objects from others. Note ---- For as long as ASN.1 is concerned, a way to compare ASN.1 types is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. """ #: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing #: ASN.1 tag(s) associated with |ASN.1| type. tagSet = tag.TagSet() #: Default :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` #: object imposing constraints on initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Disambiguation ASN.1 types identification typeId = None def __init__(self, **kwargs): readOnly = { 'tagSet': self.tagSet, 'subtypeSpec': self.subtypeSpec } readOnly.update(kwargs) self.__dict__.update(readOnly) self._readOnly = readOnly def __setattr__(self, name, value): if name[0] != '_' and name in self._readOnly: raise error.PyAsn1Error('read-only instance attribute "%s"' % name) self.__dict__[name] = value def __str__(self): return self.prettyPrint() @property def readOnly(self): return self._readOnly @property def effectiveTagSet(self): """For |ASN.1| type is equivalent to *tagSet* """ return self.tagSet # used by untagged types @property def tagMap(self): """Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects within callee object. """ return tagmap.TagMap({self.tagSet: self}) def isSameTypeWith(self, other, matchTags=True, matchConstraints=True): """Examine |ASN.1| type for equality with other ASN.1 type. ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints (:py:mod:`~pyasn1.type.constraint`) are examined when carrying out ASN.1 types comparison. Python class inheritance relationship is NOT considered. Parameters ---------- other: a pyasn1 type object Class instance representing ASN.1 type. Returns ------- : :class:`bool` :obj:`True` if *other* is |ASN.1| type, :obj:`False` otherwise. """ return (self is other or (not matchTags or self.tagSet == other.tagSet) and (not matchConstraints or self.subtypeSpec == other.subtypeSpec)) def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True): """Examine |ASN.1| type for subtype relationship with other ASN.1 type. ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints (:py:mod:`~pyasn1.type.constraint`) are examined when carrying out ASN.1 types comparison. Python class inheritance relationship is NOT considered. Parameters ---------- other: a pyasn1 type object Class instance representing ASN.1 type. Returns ------- : :class:`bool` :obj:`True` if *other* is a subtype of |ASN.1| type, :obj:`False` otherwise. """ return (not matchTags or (self.tagSet.isSuperTagSetOf(other.tagSet)) and (not matchConstraints or self.subtypeSpec.isSuperTypeOf(other.subtypeSpec))) @staticmethod def isNoValue(*values): for value in values: if value is not noValue: return False return True def prettyPrint(self, scope=0): raise NotImplementedError # backward compatibility def getTagSet(self): return self.tagSet def getEffectiveTagSet(self): return self.effectiveTagSet def getTagMap(self): return self.tagMap def getSubtypeSpec(self): return self.subtypeSpec # backward compatibility def hasValue(self): return self.isValue # Backward compatibility Asn1ItemBase = Asn1Type class NoValue(object): """Create a singleton instance of NoValue class. The *NoValue* sentinel object represents an instance of ASN.1 schema object as opposed to ASN.1 value object. Only ASN.1 schema-related operations can be performed on ASN.1 schema objects. Warning ------- Any operation attempted on the *noValue* object will raise the *PyAsn1Error* exception. """ skipMethods = { '__slots__', # attributes '__getattribute__', '__getattr__', '__setattr__', '__delattr__', # class instance '__class__', '__init__', '__del__', '__new__', '__repr__', '__qualname__', '__objclass__', 'im_class', '__sizeof__', # pickle protocol '__reduce__', '__reduce_ex__', '__getnewargs__', '__getinitargs__', '__getstate__', '__setstate__', } _instance = None def __new__(cls): if cls._instance is None: def getPlug(name): def plug(self, *args, **kw): raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name) return plug op_names = [name for typ in (str, int, list, dict) for name in dir(typ) if (name not in cls.skipMethods and name.startswith('__') and name.endswith('__') and callable(getattr(typ, name)))] for name in set(op_names): setattr(cls, name, getPlug(name)) cls._instance = object.__new__(cls) return cls._instance def __getattr__(self, attr): if attr in self.skipMethods: raise AttributeError('Attribute %s not present' % attr) raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr) def __repr__(self): return '<%s object>' % self.__class__.__name__ noValue = NoValue() class SimpleAsn1Type(Asn1Type): """Base class for all simple classes representing ASN.1 types. ASN.1 distinguishes types by their ability to hold other objects. Scalar types are known as *simple* in ASN.1. In the user code, |ASN.1| class is normally used only for telling ASN.1 objects from others. Note ---- For as long as ASN.1 is concerned, a way to compare ASN.1 types is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. """ #: Default payload value defaultValue = noValue def __init__(self, value=noValue, **kwargs): Asn1Type.__init__(self, **kwargs) if value is noValue: value = self.defaultValue else: value = self.prettyIn(value) try: self.subtypeSpec(value) except error.PyAsn1Error as exValue: raise type(exValue)('%s at %s' % (exValue, self.__class__.__name__)) self._value = value def __repr__(self): representation = '%s %s object' % ( self.__class__.__name__, self.isValue and 'value' or 'schema') for attr, value in self.readOnly.items(): if value: representation += ', %s %s' % (attr, value) if self.isValue: value = self.prettyPrint() if len(value) > 32: value = value[:16] + '...' + value[-16:] representation += ', payload [%s]' % value return '<%s>' % representation def __eq__(self, other): if self is other: return True return self._value == other def __ne__(self, other): return self._value != other def __lt__(self, other): return self._value < other def __le__(self, other): return self._value <= other def __gt__(self, other): return self._value > other def __ge__(self, other): return self._value >= other def __bool__(self): return bool(self._value) def __hash__(self): return hash(self._value) @property def isValue(self): """Indicate that |ASN.1| object represents ASN.1 value. If *isValue* is :obj:`False` then this object represents just ASN.1 schema. If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, this object can also be used like a Python built-in object (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). Returns ------- : :class:`bool` :obj:`False` if object represents just ASN.1 schema. :obj:`True` if object represents ASN.1 schema and can be used as a normal value. Note ---- There is an important distinction between PyASN1 schema and value objects. The PyASN1 schema objects can only participate in ASN.1 schema-related operations (e.g. defining or testing the structure of the data). Most obvious uses of ASN.1 schema is to guide serialisation codecs whilst encoding/decoding serialised ASN.1 contents. The PyASN1 value objects can **additionally** participate in many operations involving regular Python objects (e.g. arithmetic, comprehension etc). """ return self._value is not noValue def clone(self, value=noValue, **kwargs): """Create a modified version of |ASN.1| schema or value object. The `clone()` method accepts the same set arguments as |ASN.1| class takes on instantiation except that all arguments of the `clone()` method are optional. Whatever arguments are supplied, they are used to create a copy of `self` taking precedence over the ones used to instantiate `self`. Note ---- Due to the immutable nature of the |ASN.1| object, if no arguments are supplied, no new |ASN.1| object will be created and `self` will be returned instead. """ if value is noValue: if not kwargs: return self value = self._value initializers = self.readOnly.copy() initializers.update(kwargs) return self.__class__(value, **initializers) def subtype(self, value=noValue, **kwargs): """Create a specialization of |ASN.1| schema or value object. The subtype relationship between ASN.1 types has no correlation with subtype relationship between Python types. ASN.1 type is mainly identified by its tag(s) (:py:class:`~pyasn1.type.tag.TagSet`) and value range constraints (:py:class:`~pyasn1.type.constraint.ConstraintsIntersection`). These ASN.1 type properties are implemented as |ASN.1| attributes. The `subtype()` method accepts the same set arguments as |ASN.1| class takes on instantiation except that all parameters of the `subtype()` method are optional. With the exception of the arguments described below, the rest of supplied arguments they are used to create a copy of `self` taking precedence over the ones used to instantiate `self`. The following arguments to `subtype()` create a ASN.1 subtype out of |ASN.1| type: Other Parameters ---------------- implicitTag: :py:class:`~pyasn1.type.tag.Tag` Implicitly apply given ASN.1 tag object to `self`'s :py:class:`~pyasn1.type.tag.TagSet`, then use the result as new object's ASN.1 tag(s). explicitTag: :py:class:`~pyasn1.type.tag.Tag` Explicitly apply given ASN.1 tag object to `self`'s :py:class:`~pyasn1.type.tag.TagSet`, then use the result as new object's ASN.1 tag(s). subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Add ASN.1 constraints object to one of the `self`'s, then use the result as new object's ASN.1 constraints. Returns ------- : new instance of |ASN.1| schema or value object Note ---- Due to the immutable nature of the |ASN.1| object, if no arguments are supplied, no new |ASN.1| object will be created and `self` will be returned instead. """ if value is noValue: if not kwargs: return self value = self._value initializers = self.readOnly.copy() implicitTag = kwargs.pop('implicitTag', None) if implicitTag is not None: initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag) explicitTag = kwargs.pop('explicitTag', None) if explicitTag is not None: initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag) for arg, option in kwargs.items(): initializers[arg] += option return self.__class__(value, **initializers) def prettyIn(self, value): return value def prettyOut(self, value): return str(value) def prettyPrint(self, scope=0): return self.prettyOut(self._value) def prettyPrintType(self, scope=0): return '%s -> %s' % (self.tagSet, self.__class__.__name__) # Backward compatibility AbstractSimpleAsn1Item = SimpleAsn1Type # # Constructed types: # * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice # * ASN1 types and values are represened by Python class instances # * Value initialization is made for defaulted components only # * Primary method of component addressing is by-position. Data model for base # type is Python sequence. Additional type-specific addressing methods # may be implemented for particular types. # * SequenceOf and SetOf types do not implement any additional methods # * Sequence, Set and Choice types also implement by-identifier addressing # * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing # * Sequence and Set types may include optional and defaulted # components # * Constructed types hold a reference to component types used for value # verification and ordering. # * Component type is a scalar type for SequenceOf/SetOf types and a list # of types for Sequence/Set/Choice. # class ConstructedAsn1Type(Asn1Type): """Base class for all constructed classes representing ASN.1 types. ASN.1 distinguishes types by their ability to hold other objects. Those "nesting" types are known as *constructed* in ASN.1. In the user code, |ASN.1| class is normally used only for telling ASN.1 objects from others. Note ---- For as long as ASN.1 is concerned, a way to compare ASN.1 types is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. """ #: If :obj:`True`, requires exact component type matching, #: otherwise subtype relation is only enforced strictConstraints = False componentType = None # backward compatibility, unused sizeSpec = constraint.ConstraintsIntersection() def __init__(self, **kwargs): readOnly = { 'componentType': self.componentType, # backward compatibility, unused 'sizeSpec': self.sizeSpec } # backward compatibility: preserve legacy sizeSpec support kwargs = self._moveSizeSpec(**kwargs) readOnly.update(kwargs) Asn1Type.__init__(self, **readOnly) def _moveSizeSpec(self, **kwargs): # backward compatibility, unused sizeSpec = kwargs.pop('sizeSpec', self.sizeSpec) if sizeSpec: subtypeSpec = kwargs.pop('subtypeSpec', self.subtypeSpec) if subtypeSpec: subtypeSpec = sizeSpec else: subtypeSpec += sizeSpec kwargs['subtypeSpec'] = subtypeSpec return kwargs def __repr__(self): representation = '%s %s object' % ( self.__class__.__name__, self.isValue and 'value' or 'schema' ) for attr, value in self.readOnly.items(): if value is not noValue: representation += ', %s=%r' % (attr, value) if self.isValue and self.components: representation += ', payload [%s]' % ', '.join( [repr(x) for x in self.components]) return '<%s>' % representation def __eq__(self, other): return self is other or self.components == other def __ne__(self, other): return self.components != other def __lt__(self, other): return self.components < other def __le__(self, other): return self.components <= other def __gt__(self, other): return self.components > other def __ge__(self, other): return self.components >= other def __bool__(self): return bool(self.components) @property def components(self): raise error.PyAsn1Error('Method not implemented') def _cloneComponentValues(self, myClone, cloneValueFlag): pass def clone(self, **kwargs): """Create a modified version of |ASN.1| schema object. The `clone()` method accepts the same set arguments as |ASN.1| class takes on instantiation except that all arguments of the `clone()` method are optional. Whatever arguments are supplied, they are used to create a copy of `self` taking precedence over the ones used to instantiate `self`. Possible values of `self` are never copied over thus `clone()` can only create a new schema object. Returns ------- : new instance of |ASN.1| type/value Note ---- Due to the mutable nature of the |ASN.1| object, even if no arguments are supplied, a new |ASN.1| object will be created and returned. """ cloneValueFlag = kwargs.pop('cloneValueFlag', False) initializers = self.readOnly.copy() initializers.update(kwargs) clone = self.__class__(**initializers) if cloneValueFlag: self._cloneComponentValues(clone, cloneValueFlag) return clone def subtype(self, **kwargs): """Create a specialization of |ASN.1| schema object. The `subtype()` method accepts the same set arguments as |ASN.1| class takes on instantiation except that all parameters of the `subtype()` method are optional. With the exception of the arguments described below, the rest of supplied arguments they are used to create a copy of `self` taking precedence over the ones used to instantiate `self`. The following arguments to `subtype()` create a ASN.1 subtype out of |ASN.1| type. Other Parameters ---------------- implicitTag: :py:class:`~pyasn1.type.tag.Tag` Implicitly apply given ASN.1 tag object to `self`'s :py:class:`~pyasn1.type.tag.TagSet`, then use the result as new object's ASN.1 tag(s). explicitTag: :py:class:`~pyasn1.type.tag.Tag` Explicitly apply given ASN.1 tag object to `self`'s :py:class:`~pyasn1.type.tag.TagSet`, then use the result as new object's ASN.1 tag(s). subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Add ASN.1 constraints object to one of the `self`'s, then use the result as new object's ASN.1 constraints. Returns ------- : new instance of |ASN.1| type/value Note ---- Due to the mutable nature of the |ASN.1| object, even if no arguments are supplied, a new |ASN.1| object will be created and returned. """ initializers = self.readOnly.copy() cloneValueFlag = kwargs.pop('cloneValueFlag', False) implicitTag = kwargs.pop('implicitTag', None) if implicitTag is not None: initializers['tagSet'] = self.tagSet.tagImplicitly(implicitTag) explicitTag = kwargs.pop('explicitTag', None) if explicitTag is not None: initializers['tagSet'] = self.tagSet.tagExplicitly(explicitTag) for arg, option in kwargs.items(): initializers[arg] += option clone = self.__class__(**initializers) if cloneValueFlag: self._cloneComponentValues(clone, cloneValueFlag) return clone def getComponentByPosition(self, idx): raise error.PyAsn1Error('Method not implemented') def setComponentByPosition(self, idx, value, verifyConstraints=True): raise error.PyAsn1Error('Method not implemented') def setComponents(self, *args, **kwargs): for idx, value in enumerate(args): self[idx] = value for k in kwargs: self[k] = kwargs[k] return self # backward compatibility def setDefaultComponents(self): pass def getComponentType(self): return self.componentType # backward compatibility, unused def verifySizeSpec(self): self.subtypeSpec(self) # Backward compatibility AbstractConstructedAsn1Item = ConstructedAsn1Type ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/char.py0000644000175000017500000002233614670137102016673 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys from pyasn1 import error from pyasn1.type import tag from pyasn1.type import univ __all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString', 'IA5String', 'GraphicString', 'VisibleString', 'ISO646String', 'GeneralString', 'UniversalString', 'BMPString', 'UTF8String'] NoValue = univ.NoValue noValue = univ.noValue class AbstractCharacterString(univ.OctetString): """Creates |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type :class:`bytes`. When used in octet-stream context, |ASN.1| type assumes "|encoding|" encoding. Keyword Args ------------ value: :class:`str`, :class:`bytes` or |ASN.1| object :class:`str`, alternatively :class:`bytes` representing octet-stream of serialised unicode string (note `encoding` parameter) or |ASN.1| class instance. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. encoding: :py:class:`str` Unicode codec ID to encode/decode :class:`str` the payload when |ASN.1| object is used in octet-stream context. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. """ def __str__(self): return str(self._value) def __bytes__(self): try: return self._value.encode(self.encoding) except UnicodeEncodeError as exc: raise error.PyAsn1UnicodeEncodeError( "Can't encode string '%s' with codec " "%s" % (self._value, self.encoding), exc ) def prettyIn(self, value): try: if isinstance(value, str): return value elif isinstance(value, bytes): return value.decode(self.encoding) elif isinstance(value, (tuple, list)): return self.prettyIn(bytes(value)) elif isinstance(value, univ.OctetString): return value.asOctets().decode(self.encoding) else: return str(value) except (UnicodeDecodeError, LookupError) as exc: raise error.PyAsn1UnicodeDecodeError( "Can't decode string '%s' with codec " "%s" % (value, self.encoding), exc ) def asOctets(self, padding=True): return bytes(self) def asNumbers(self, padding=True): return tuple(bytes(self)) # # See OctetString.prettyPrint() for the explanation # def prettyOut(self, value): return value def prettyPrint(self, scope=0): # first see if subclass has its own .prettyOut() value = self.prettyOut(self._value) if value is not self._value: return value return AbstractCharacterString.__str__(self) def __reversed__(self): return reversed(self._value) class NumericString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 18) ) encoding = 'us-ascii' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class PrintableString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 19) ) encoding = 'us-ascii' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class TeletexString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 20) ) encoding = 'iso-8859-1' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class T61String(TeletexString): __doc__ = TeletexString.__doc__ # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class VideotexString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 21) ) encoding = 'iso-8859-1' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class IA5String(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 22) ) encoding = 'us-ascii' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class GraphicString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 25) ) encoding = 'iso-8859-1' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class VisibleString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 26) ) encoding = 'us-ascii' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class ISO646String(VisibleString): __doc__ = VisibleString.__doc__ # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class GeneralString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 27) ) encoding = 'iso-8859-1' # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class UniversalString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 28) ) encoding = "utf-32-be" # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class BMPString(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 30) ) encoding = "utf-16-be" # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() class UTF8String(AbstractCharacterString): __doc__ = AbstractCharacterString.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = AbstractCharacterString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ) encoding = "utf-8" # Optimization for faster codec lookup typeId = AbstractCharacterString.getTypeId() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/constraint.py0000644000175000017500000005263314670137102020145 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # # Original concept and code by Mike C. Fletcher. # import sys from pyasn1.type import error __all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint', 'ValueRangeConstraint', 'ValueSizeConstraint', 'PermittedAlphabetConstraint', 'InnerTypeConstraint', 'ConstraintsExclusion', 'ConstraintsIntersection', 'ConstraintsUnion'] class AbstractConstraint(object): def __init__(self, *values): self._valueMap = set() self._setValues(values) self.__hash = hash((self.__class__.__name__, self._values)) def __call__(self, value, idx=None): if not self._values: return try: self._testValue(value, idx) except error.ValueConstraintError as exc: raise error.ValueConstraintError( '%s failed at: %r' % (self, exc) ) def __repr__(self): representation = '%s object' % (self.__class__.__name__) if self._values: representation += ', consts %s' % ', '.join( [repr(x) for x in self._values]) return '<%s>' % representation def __eq__(self, other): if self is other: return True return self._values == other def __ne__(self, other): return self._values != other def __lt__(self, other): return self._values < other def __le__(self, other): return self._values <= other def __gt__(self, other): return self._values > other def __ge__(self, other): return self._values >= other def __bool__(self): return bool(self._values) def __hash__(self): return self.__hash def _setValues(self, values): self._values = values def _testValue(self, value, idx): raise error.ValueConstraintError(value) # Constraints derivation logic def getValueMap(self): return self._valueMap def isSuperTypeOf(self, otherConstraint): # TODO: fix possible comparison of set vs scalars here return (otherConstraint is self or not self._values or otherConstraint == self or self in otherConstraint.getValueMap()) def isSubTypeOf(self, otherConstraint): return (otherConstraint is self or not self or otherConstraint == self or otherConstraint in self._valueMap) class SingleValueConstraint(AbstractConstraint): """Create a SingleValueConstraint object. The SingleValueConstraint satisfies any value that is present in the set of permitted values. Objects of this type are iterable (emitting constraint values) and can act as operands for some arithmetic operations e.g. addition and subtraction. The latter can be used for combining multiple SingleValueConstraint objects into one. The SingleValueConstraint object can be applied to any ASN.1 type. Parameters ---------- *values: :class:`int` Full set of values permitted by this constraint object. Examples -------- .. code-block:: python class DivisorOfSix(Integer): ''' ASN.1 specification: Divisor-Of-6 ::= INTEGER (1 | 2 | 3 | 6) ''' subtypeSpec = SingleValueConstraint(1, 2, 3, 6) # this will succeed divisor_of_six = DivisorOfSix(1) # this will raise ValueConstraintError divisor_of_six = DivisorOfSix(7) """ def _setValues(self, values): self._values = values self._set = set(values) def _testValue(self, value, idx): if value not in self._set: raise error.ValueConstraintError(value) # Constrains can be merged or reduced def __contains__(self, item): return item in self._set def __iter__(self): return iter(self._set) def __add__(self, constraint): return self.__class__(*(self._set.union(constraint))) def __sub__(self, constraint): return self.__class__(*(self._set.difference(constraint))) class ContainedSubtypeConstraint(AbstractConstraint): """Create a ContainedSubtypeConstraint object. The ContainedSubtypeConstraint satisfies any value that is present in the set of permitted values and also satisfies included constraints. The ContainedSubtypeConstraint object can be applied to any ASN.1 type. Parameters ---------- *values: Full set of values and constraint objects permitted by this constraint object. Examples -------- .. code-block:: python class DivisorOfEighteen(Integer): ''' ASN.1 specification: Divisors-of-18 ::= INTEGER (INCLUDES Divisors-of-6 | 9 | 18) ''' subtypeSpec = ContainedSubtypeConstraint( SingleValueConstraint(1, 2, 3, 6), 9, 18 ) # this will succeed divisor_of_eighteen = DivisorOfEighteen(9) # this will raise ValueConstraintError divisor_of_eighteen = DivisorOfEighteen(10) """ def _testValue(self, value, idx): for constraint in self._values: if isinstance(constraint, AbstractConstraint): constraint(value, idx) elif value not in self._set: raise error.ValueConstraintError(value) class ValueRangeConstraint(AbstractConstraint): """Create a ValueRangeConstraint object. The ValueRangeConstraint satisfies any value that falls in the range of permitted values. The ValueRangeConstraint object can only be applied to :class:`~pyasn1.type.univ.Integer` and :class:`~pyasn1.type.univ.Real` types. Parameters ---------- start: :class:`int` Minimum permitted value in the range (inclusive) end: :class:`int` Maximum permitted value in the range (inclusive) Examples -------- .. code-block:: python class TeenAgeYears(Integer): ''' ASN.1 specification: TeenAgeYears ::= INTEGER (13 .. 19) ''' subtypeSpec = ValueRangeConstraint(13, 19) # this will succeed teen_year = TeenAgeYears(18) # this will raise ValueConstraintError teen_year = TeenAgeYears(20) """ def _testValue(self, value, idx): if value < self.start or value > self.stop: raise error.ValueConstraintError(value) def _setValues(self, values): if len(values) != 2: raise error.PyAsn1Error( '%s: bad constraint values' % (self.__class__.__name__,) ) self.start, self.stop = values if self.start > self.stop: raise error.PyAsn1Error( '%s: screwed constraint values (start > stop): %s > %s' % ( self.__class__.__name__, self.start, self.stop ) ) AbstractConstraint._setValues(self, values) class ValueSizeConstraint(ValueRangeConstraint): """Create a ValueSizeConstraint object. The ValueSizeConstraint satisfies any value for as long as its size falls within the range of permitted sizes. The ValueSizeConstraint object can be applied to :class:`~pyasn1.type.univ.BitString`, :class:`~pyasn1.type.univ.OctetString` (including all :ref:`character ASN.1 types `), :class:`~pyasn1.type.univ.SequenceOf` and :class:`~pyasn1.type.univ.SetOf` types. Parameters ---------- minimum: :class:`int` Minimum permitted size of the value (inclusive) maximum: :class:`int` Maximum permitted size of the value (inclusive) Examples -------- .. code-block:: python class BaseballTeamRoster(SetOf): ''' ASN.1 specification: BaseballTeamRoster ::= SET SIZE (1..25) OF PlayerNames ''' componentType = PlayerNames() subtypeSpec = ValueSizeConstraint(1, 25) # this will succeed team = BaseballTeamRoster() team.extend(['Jan', 'Matej']) encode(team) # this will raise ValueConstraintError team = BaseballTeamRoster() team.extend(['Jan'] * 26) encode(team) Note ---- Whenever ValueSizeConstraint is applied to mutable types (e.g. :class:`~pyasn1.type.univ.SequenceOf`, :class:`~pyasn1.type.univ.SetOf`), constraint validation only happens at the serialisation phase rather than schema instantiation phase (as it is with immutable types). """ def _testValue(self, value, idx): valueSize = len(value) if valueSize < self.start or valueSize > self.stop: raise error.ValueConstraintError(value) class PermittedAlphabetConstraint(SingleValueConstraint): """Create a PermittedAlphabetConstraint object. The PermittedAlphabetConstraint satisfies any character string for as long as all its characters are present in the set of permitted characters. Objects of this type are iterable (emitting constraint values) and can act as operands for some arithmetic operations e.g. addition and subtraction. The PermittedAlphabetConstraint object can only be applied to the :ref:`character ASN.1 types ` such as :class:`~pyasn1.type.char.IA5String`. Parameters ---------- *alphabet: :class:`str` Full set of characters permitted by this constraint object. Example ------- .. code-block:: python class BooleanValue(IA5String): ''' ASN.1 specification: BooleanValue ::= IA5String (FROM ('T' | 'F')) ''' subtypeSpec = PermittedAlphabetConstraint('T', 'F') # this will succeed truth = BooleanValue('T') truth = BooleanValue('TF') # this will raise ValueConstraintError garbage = BooleanValue('TAF') ASN.1 `FROM ... EXCEPT ...` clause can be modelled by combining multiple PermittedAlphabetConstraint objects into one: Example ------- .. code-block:: python class Lipogramme(IA5String): ''' ASN.1 specification: Lipogramme ::= IA5String (FROM (ALL EXCEPT ("e"|"E"))) ''' subtypeSpec = ( PermittedAlphabetConstraint(*string.printable) - PermittedAlphabetConstraint('e', 'E') ) # this will succeed lipogramme = Lipogramme('A work of fiction?') # this will raise ValueConstraintError lipogramme = Lipogramme('Eel') Note ---- Although `ConstraintsExclusion` object could seemingly be used for this purpose, practically, for it to work, it needs to represent its operand constraints as sets and intersect one with the other. That would require the insight into the constraint values (and their types) that are otherwise hidden inside the constraint object. Therefore it's more practical to model `EXCEPT` clause at `PermittedAlphabetConstraint` level instead. """ def _setValues(self, values): self._values = values self._set = set(values) def _testValue(self, value, idx): if not self._set.issuperset(value): raise error.ValueConstraintError(value) class ComponentPresentConstraint(AbstractConstraint): """Create a ComponentPresentConstraint object. The ComponentPresentConstraint is only satisfied when the value is not `None`. The ComponentPresentConstraint object is typically used with `WithComponentsConstraint`. Examples -------- .. code-block:: python present = ComponentPresentConstraint() # this will succeed present('whatever') # this will raise ValueConstraintError present(None) """ def _setValues(self, values): self._values = ('',) if values: raise error.PyAsn1Error('No arguments expected') def _testValue(self, value, idx): if value is None: raise error.ValueConstraintError( 'Component is not present:') class ComponentAbsentConstraint(AbstractConstraint): """Create a ComponentAbsentConstraint object. The ComponentAbsentConstraint is only satisfied when the value is `None`. The ComponentAbsentConstraint object is typically used with `WithComponentsConstraint`. Examples -------- .. code-block:: python absent = ComponentAbsentConstraint() # this will succeed absent(None) # this will raise ValueConstraintError absent('whatever') """ def _setValues(self, values): self._values = ('',) if values: raise error.PyAsn1Error('No arguments expected') def _testValue(self, value, idx): if value is not None: raise error.ValueConstraintError( 'Component is not absent: %r' % value) class WithComponentsConstraint(AbstractConstraint): """Create a WithComponentsConstraint object. The `WithComponentsConstraint` satisfies any mapping object that has constrained fields present or absent, what is indicated by `ComponentPresentConstraint` and `ComponentAbsentConstraint` objects respectively. The `WithComponentsConstraint` object is typically applied to :class:`~pyasn1.type.univ.Set` or :class:`~pyasn1.type.univ.Sequence` types. Parameters ---------- *fields: :class:`tuple` Zero or more tuples of (`field`, `constraint`) indicating constrained fields. Notes ----- On top of the primary use of `WithComponentsConstraint` (ensuring presence or absence of particular components of a :class:`~pyasn1.type.univ.Set` or :class:`~pyasn1.type.univ.Sequence`), it is also possible to pass any other constraint objects or their combinations. In case of scalar fields, these constraints will be verified in addition to the constraints belonging to scalar components themselves. However, formally, these additional constraints do not change the type of these ASN.1 objects. Examples -------- .. code-block:: python class Item(Sequence): # Set is similar ''' ASN.1 specification: Item ::= SEQUENCE { id INTEGER OPTIONAL, name OCTET STRING OPTIONAL } WITH COMPONENTS id PRESENT, name ABSENT | id ABSENT, name PRESENT ''' componentType = NamedTypes( OptionalNamedType('id', Integer()), OptionalNamedType('name', OctetString()) ) withComponents = ConstraintsUnion( WithComponentsConstraint( ('id', ComponentPresentConstraint()), ('name', ComponentAbsentConstraint()) ), WithComponentsConstraint( ('id', ComponentAbsentConstraint()), ('name', ComponentPresentConstraint()) ) ) item = Item() # This will succeed item['id'] = 1 # This will succeed item.reset() item['name'] = 'John' # This will fail (on encoding) item.reset() descr['id'] = 1 descr['name'] = 'John' """ def _testValue(self, value, idx): for field, constraint in self._values: constraint(value.get(field)) def _setValues(self, values): AbstractConstraint._setValues(self, values) # This is a bit kludgy, meaning two op modes within a single constraint class InnerTypeConstraint(AbstractConstraint): """Value must satisfy the type and presence constraints""" def _testValue(self, value, idx): if self.__singleTypeConstraint: self.__singleTypeConstraint(value) elif self.__multipleTypeConstraint: if idx not in self.__multipleTypeConstraint: raise error.ValueConstraintError(value) constraint, status = self.__multipleTypeConstraint[idx] if status == 'ABSENT': # XXX presence is not checked! raise error.ValueConstraintError(value) constraint(value) def _setValues(self, values): self.__multipleTypeConstraint = {} self.__singleTypeConstraint = None for v in values: if isinstance(v, tuple): self.__multipleTypeConstraint[v[0]] = v[1], v[2] else: self.__singleTypeConstraint = v AbstractConstraint._setValues(self, values) # Logic operations on constraints class ConstraintsExclusion(AbstractConstraint): """Create a ConstraintsExclusion logic operator object. The ConstraintsExclusion logic operator succeeds when the value does *not* satisfy the operand constraint. The ConstraintsExclusion object can be applied to any constraint and logic operator object. Parameters ---------- *constraints: Constraint or logic operator objects. Examples -------- .. code-block:: python class LuckyNumber(Integer): subtypeSpec = ConstraintsExclusion( SingleValueConstraint(13) ) # this will succeed luckyNumber = LuckyNumber(12) # this will raise ValueConstraintError luckyNumber = LuckyNumber(13) Note ---- The `FROM ... EXCEPT ...` ASN.1 clause should be modeled by combining constraint objects into one. See `PermittedAlphabetConstraint` for more information. """ def _testValue(self, value, idx): for constraint in self._values: try: constraint(value, idx) except error.ValueConstraintError: continue raise error.ValueConstraintError(value) def _setValues(self, values): AbstractConstraint._setValues(self, values) class AbstractConstraintSet(AbstractConstraint): def __getitem__(self, idx): return self._values[idx] def __iter__(self): return iter(self._values) def __add__(self, value): return self.__class__(*(self._values + (value,))) def __radd__(self, value): return self.__class__(*((value,) + self._values)) def __len__(self): return len(self._values) # Constraints inclusion in sets def _setValues(self, values): self._values = values for constraint in values: if constraint: self._valueMap.add(constraint) self._valueMap.update(constraint.getValueMap()) class ConstraintsIntersection(AbstractConstraintSet): """Create a ConstraintsIntersection logic operator object. The ConstraintsIntersection logic operator only succeeds if *all* its operands succeed. The ConstraintsIntersection object can be applied to any constraint and logic operator objects. The ConstraintsIntersection object duck-types the immutable container object like Python :py:class:`tuple`. Parameters ---------- *constraints: Constraint or logic operator objects. Examples -------- .. code-block:: python class CapitalAndSmall(IA5String): ''' ASN.1 specification: CapitalAndSmall ::= IA5String (FROM ("A".."Z"|"a".."z")) ''' subtypeSpec = ConstraintsIntersection( PermittedAlphabetConstraint('A', 'Z'), PermittedAlphabetConstraint('a', 'z') ) # this will succeed capital_and_small = CapitalAndSmall('Hello') # this will raise ValueConstraintError capital_and_small = CapitalAndSmall('hello') """ def _testValue(self, value, idx): for constraint in self._values: constraint(value, idx) class ConstraintsUnion(AbstractConstraintSet): """Create a ConstraintsUnion logic operator object. The ConstraintsUnion logic operator succeeds if *at least* a single operand succeeds. The ConstraintsUnion object can be applied to any constraint and logic operator objects. The ConstraintsUnion object duck-types the immutable container object like Python :py:class:`tuple`. Parameters ---------- *constraints: Constraint or logic operator objects. Examples -------- .. code-block:: python class CapitalOrSmall(IA5String): ''' ASN.1 specification: CapitalOrSmall ::= IA5String (FROM ("A".."Z") | FROM ("a".."z")) ''' subtypeSpec = ConstraintsUnion( PermittedAlphabetConstraint('A', 'Z'), PermittedAlphabetConstraint('a', 'z') ) # this will succeed capital_or_small = CapitalAndSmall('Hello') # this will raise ValueConstraintError capital_or_small = CapitalOrSmall('hello!') """ def _testValue(self, value, idx): for constraint in self._values: try: constraint(value, idx) except error.ValueConstraintError: pass else: return raise error.ValueConstraintError( 'all of %s failed for "%s"' % (self._values, value) ) # TODO: # refactor InnerTypeConstraint # add tests for type check # implement other constraint types # make constraint validation easy to skip ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/type/error.py0000644000175000017500000000040314525242621017100 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from pyasn1.error import PyAsn1Error class ValueConstraintError(PyAsn1Error): pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/namedtype.py0000644000175000017500000003746314670137102017753 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys from pyasn1 import error from pyasn1.type import tag from pyasn1.type import tagmap __all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes'] class NamedType(object): """Create named field object for a constructed ASN.1 type. The |NamedType| object represents a single name and ASN.1 type of a constructed ASN.1 type. |NamedType| objects are immutable and duck-type Python :class:`tuple` objects holding *name* and *asn1Object* components. Parameters ---------- name: :py:class:`str` Field name asn1Object: ASN.1 type object """ isOptional = False isDefaulted = False def __init__(self, name, asn1Object, openType=None): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object self.__openType = openType def __repr__(self): representation = '%s=%r' % (self.name, self.asn1Object) if self.openType: representation += ', open type %r' % self.openType return '<%s object, type %s>' % ( self.__class__.__name__, representation) def __eq__(self, other): return self.__nameAndType == other def __ne__(self, other): return self.__nameAndType != other def __lt__(self, other): return self.__nameAndType < other def __le__(self, other): return self.__nameAndType <= other def __gt__(self, other): return self.__nameAndType > other def __ge__(self, other): return self.__nameAndType >= other def __hash__(self): return hash(self.__nameAndType) def __getitem__(self, idx): return self.__nameAndType[idx] def __iter__(self): return iter(self.__nameAndType) @property def name(self): return self.__name @property def asn1Object(self): return self.__type @property def openType(self): return self.__openType # Backward compatibility def getName(self): return self.name def getType(self): return self.asn1Object class OptionalNamedType(NamedType): __doc__ = NamedType.__doc__ isOptional = True class DefaultedNamedType(NamedType): __doc__ = NamedType.__doc__ isDefaulted = True class NamedTypes(object): """Create a collection of named fields for a constructed ASN.1 type. The NamedTypes object represents a collection of named fields of a constructed ASN.1 type. *NamedTypes* objects are immutable and duck-type Python :class:`dict` objects holding *name* as keys and ASN.1 type object as values. Parameters ---------- *namedTypes: :class:`~pyasn1.type.namedtype.NamedType` Examples -------- .. code-block:: python class Description(Sequence): ''' ASN.1 specification: Description ::= SEQUENCE { surname IA5String, first-name IA5String OPTIONAL, age INTEGER DEFAULT 40 } ''' componentType = NamedTypes( NamedType('surname', IA5String()), OptionalNamedType('first-name', IA5String()), DefaultedNamedType('age', Integer(40)) ) descr = Description() descr['surname'] = 'Smith' descr['first-name'] = 'John' """ def __init__(self, *namedTypes, **kwargs): self.__namedTypes = namedTypes self.__namedTypesLen = len(self.__namedTypes) self.__minTagSet = self.__computeMinTagSet() self.__nameToPosMap = self.__computeNameToPosMap() self.__tagToPosMap = self.__computeTagToPosMap() self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {} self.__uniqueTagMap = self.__computeTagMaps(unique=True) self.__nonUniqueTagMap = self.__computeTagMaps(unique=False) self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes if namedType.isDefaulted or namedType.isOptional]) self.__hasOpenTypes = any([True for namedType in self.__namedTypes if namedType.openType]) self.__requiredComponents = frozenset( [idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted] ) self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) def __repr__(self): representation = ', '.join(['%r' % x for x in self.__namedTypes]) return '<%s object, types %s>' % ( self.__class__.__name__, representation) def __eq__(self, other): return self.__namedTypes == other def __ne__(self, other): return self.__namedTypes != other def __lt__(self, other): return self.__namedTypes < other def __le__(self, other): return self.__namedTypes <= other def __gt__(self, other): return self.__namedTypes > other def __ge__(self, other): return self.__namedTypes >= other def __hash__(self): return hash(self.__namedTypes) def __getitem__(self, idx): try: return self.__namedTypes[idx] except TypeError: return self.__namedTypes[self.__nameToPosMap[idx]] def __contains__(self, key): return key in self.__nameToPosMap def __iter__(self): return (x[0] for x in self.__namedTypes) def __bool__(self): return self.__namedTypesLen > 0 def __len__(self): return self.__namedTypesLen # Python dict protocol def values(self): return self.__values def keys(self): return self.__keys def items(self): return self.__items def clone(self): return self.__class__(*self.__namedTypes) class PostponedError(object): def __init__(self, errorMsg): self.__errorMsg = errorMsg def __getitem__(self, item): raise error.PyAsn1Error(self.__errorMsg) def __computeTagToPosMap(self): tagToPosMap = {} for idx, namedType in enumerate(self.__namedTypes): tagMap = namedType.asn1Object.tagMap if isinstance(tagMap, NamedTypes.PostponedError): return tagMap if not tagMap: continue for _tagSet in tagMap.presentTypes: if _tagSet in tagToPosMap: return NamedTypes.PostponedError('Duplicate component tag %s at %s' % (_tagSet, namedType)) tagToPosMap[_tagSet] = idx return tagToPosMap def __computeNameToPosMap(self): nameToPosMap = {} for idx, namedType in enumerate(self.__namedTypes): if namedType.name in nameToPosMap: return NamedTypes.PostponedError('Duplicate component name %s at %s' % (namedType.name, namedType)) nameToPosMap[namedType.name] = idx return nameToPosMap def __computeAmbiguousTypes(self): ambiguousTypes = {} partialAmbiguousTypes = () for idx, namedType in reversed(tuple(enumerate(self.__namedTypes))): if namedType.isOptional or namedType.isDefaulted: partialAmbiguousTypes = (namedType,) + partialAmbiguousTypes else: partialAmbiguousTypes = (namedType,) if len(partialAmbiguousTypes) == len(self.__namedTypes): ambiguousTypes[idx] = self else: ambiguousTypes[idx] = NamedTypes(*partialAmbiguousTypes, **dict(terminal=True)) return ambiguousTypes def getTypeByPosition(self, idx): """Return ASN.1 type object by its position in fields set. Parameters ---------- idx: :py:class:`int` Field index Returns ------- : ASN.1 type Raises ------ ~pyasn1.error.PyAsn1Error If given position is out of fields range """ try: return self.__namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error('Type position out of range') def getPositionByType(self, tagSet): """Return field position by its ASN.1 type. Parameters ---------- tagSet: :class:`~pysnmp.type.tag.TagSet` ASN.1 tag set distinguishing one ASN.1 type from others. Returns ------- : :py:class:`int` ASN.1 type position in fields set Raises ------ ~pyasn1.error.PyAsn1Error If *tagSet* is not present or ASN.1 types are not unique within callee *NamedTypes* """ try: return self.__tagToPosMap[tagSet] except KeyError: raise error.PyAsn1Error('Type %s not found' % (tagSet,)) def getNameByPosition(self, idx): """Return field name by its position in fields set. Parameters ---------- idx: :py:class:`idx` Field index Returns ------- : :py:class:`str` Field name Raises ------ ~pyasn1.error.PyAsn1Error If given field name is not present in callee *NamedTypes* """ try: return self.__namedTypes[idx].name except IndexError: raise error.PyAsn1Error('Type position out of range') def getPositionByName(self, name): """Return field position by filed name. Parameters ---------- name: :py:class:`str` Field name Returns ------- : :py:class:`int` Field position in fields set Raises ------ ~pyasn1.error.PyAsn1Error If *name* is not present or not unique within callee *NamedTypes* """ try: return self.__nameToPosMap[name] except KeyError: raise error.PyAsn1Error('Name %s not found' % (name,)) def getTagMapNearPosition(self, idx): """Return ASN.1 types that are allowed at or past given field position. Some ASN.1 serialisation allow for skipping optional and defaulted fields. Some constructed ASN.1 types allow reordering of the fields. When recovering such objects it may be important to know which types can possibly be present at any given position in the field sets. Parameters ---------- idx: :py:class:`int` Field index Returns ------- : :class:`~pyasn1.type.tagmap.TagMap` Map if ASN.1 types allowed at given field position Raises ------ ~pyasn1.error.PyAsn1Error If given position is out of fields range """ try: return self.__ambiguousTypes[idx].tagMap except KeyError: raise error.PyAsn1Error('Type position out of range') def getPositionNearType(self, tagSet, idx): """Return the closest field position where given ASN.1 type is allowed. Some ASN.1 serialisation allow for skipping optional and defaulted fields. Some constructed ASN.1 types allow reordering of the fields. When recovering such objects it may be important to know at which field position, in field set, given *tagSet* is allowed at or past *idx* position. Parameters ---------- tagSet: :class:`~pyasn1.type.tag.TagSet` ASN.1 type which field position to look up idx: :py:class:`int` Field position at or past which to perform ASN.1 type look up Returns ------- : :py:class:`int` Field position in fields set Raises ------ ~pyasn1.error.PyAsn1Error If *tagSet* is not present or not unique within callee *NamedTypes* or *idx* is out of fields range """ try: return idx + self.__ambiguousTypes[idx].getPositionByType(tagSet) except KeyError: raise error.PyAsn1Error('Type position out of range') def __computeMinTagSet(self): minTagSet = None for namedType in self.__namedTypes: asn1Object = namedType.asn1Object try: tagSet = asn1Object.minTagSet except AttributeError: tagSet = asn1Object.tagSet if minTagSet is None or tagSet < minTagSet: minTagSet = tagSet return minTagSet or tag.TagSet() @property def minTagSet(self): """Return the minimal TagSet among ASN.1 type in callee *NamedTypes*. Some ASN.1 types/serialisation protocols require ASN.1 types to be arranged based on their numerical tag value. The *minTagSet* property returns that. Returns ------- : :class:`~pyasn1.type.tagset.TagSet` Minimal TagSet among ASN.1 types in callee *NamedTypes* """ return self.__minTagSet def __computeTagMaps(self, unique): presentTypes = {} skipTypes = {} defaultType = None for namedType in self.__namedTypes: tagMap = namedType.asn1Object.tagMap if isinstance(tagMap, NamedTypes.PostponedError): return tagMap for tagSet in tagMap: if unique and tagSet in presentTypes: return NamedTypes.PostponedError('Non-unique tagSet %s of %s at %s' % (tagSet, namedType, self)) presentTypes[tagSet] = namedType.asn1Object skipTypes.update(tagMap.skipTypes) if defaultType is None: defaultType = tagMap.defaultType elif tagMap.defaultType is not None: return NamedTypes.PostponedError('Duplicate default ASN.1 type at %s' % (self,)) return tagmap.TagMap(presentTypes, skipTypes, defaultType) @property def tagMap(self): """Return a *TagMap* object from tags and types recursively. Return a :class:`~pyasn1.type.tagmap.TagMap` object by combining tags from *TagMap* objects of children types and associating them with their immediate child type. Example ------- .. code-block:: python OuterType ::= CHOICE { innerType INTEGER } Calling *.tagMap* on *OuterType* will yield a map like this: .. code-block:: python Integer.tagSet -> Choice """ return self.__nonUniqueTagMap @property def tagMapUnique(self): """Return a *TagMap* object from unique tags and types recursively. Return a :class:`~pyasn1.type.tagmap.TagMap` object by combining tags from *TagMap* objects of children types and associating them with their immediate child type. Example ------- .. code-block:: python OuterType ::= CHOICE { innerType INTEGER } Calling *.tagMapUnique* on *OuterType* will yield a map like this: .. code-block:: python Integer.tagSet -> Choice Note ---- Duplicate *TagSet* objects found in the tree of children types would cause error. """ return self.__uniqueTagMap @property def hasOptionalOrDefault(self): return self.__hasOptionalOrDefault @property def hasOpenTypes(self): return self.__hasOpenTypes @property def namedTypes(self): return tuple(self.__namedTypes) @property def requiredComponents(self): return self.__requiredComponents ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/type/namedval.py0000644000175000017500000001144314525242621017544 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # # ASN.1 named integers # from pyasn1 import error __all__ = ['NamedValues'] class NamedValues(object): """Create named values object. The |NamedValues| object represents a collection of string names associated with numeric IDs. These objects are used for giving names to otherwise numerical values. |NamedValues| objects are immutable and duck-type Python :class:`dict` object mapping ID to name and vice-versa. Parameters ---------- *args: variable number of two-element :py:class:`tuple` name: :py:class:`str` Value label value: :py:class:`int` Numeric value Keyword Args ------------ name: :py:class:`str` Value label value: :py:class:`int` Numeric value Examples -------- .. code-block:: pycon >>> nv = NamedValues('a', 'b', ('c', 0), d=1) >>> nv >>> {'c': 0, 'd': 1, 'a': 2, 'b': 3} >>> nv[0] 'c' >>> nv['a'] 2 """ def __init__(self, *args, **kwargs): self.__names = {} self.__numbers = {} anonymousNames = [] for namedValue in args: if isinstance(namedValue, (tuple, list)): try: name, number = namedValue except ValueError: raise error.PyAsn1Error('Not a proper attribute-value pair %r' % (namedValue,)) else: anonymousNames.append(namedValue) continue if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) if number in self.__numbers: raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) self.__names[name] = number self.__numbers[number] = name for name, number in kwargs.items(): if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) if number in self.__numbers: raise error.PyAsn1Error('Duplicate number %s=%s' % (name, number)) self.__names[name] = number self.__numbers[number] = name if anonymousNames: number = self.__numbers and max(self.__numbers) + 1 or 0 for name in anonymousNames: if name in self.__names: raise error.PyAsn1Error('Duplicate name %s' % (name,)) self.__names[name] = number self.__numbers[number] = name number += 1 def __repr__(self): representation = ', '.join(['%s=%d' % x for x in self.items()]) if len(representation) > 64: representation = representation[:32] + '...' + representation[-32:] return '<%s object, enums %s>' % ( self.__class__.__name__, representation) def __eq__(self, other): return dict(self) == other def __ne__(self, other): return dict(self) != other def __lt__(self, other): return dict(self) < other def __le__(self, other): return dict(self) <= other def __gt__(self, other): return dict(self) > other def __ge__(self, other): return dict(self) >= other def __hash__(self): return hash(self.items()) # Python dict protocol (read-only) def __getitem__(self, key): try: return self.__numbers[key] except KeyError: return self.__names[key] def __len__(self): return len(self.__names) def __contains__(self, key): return key in self.__names or key in self.__numbers def __iter__(self): return iter(self.__names) def values(self): return iter(self.__numbers) def keys(self): return iter(self.__names) def items(self): for name in self.__names: yield name, self.__names[name] # support merging def __add__(self, namedValues): return self.__class__(*tuple(self.items()) + tuple(namedValues.items())) # XXX clone/subtype? def clone(self, *args, **kwargs): new = self.__class__(*args, **kwargs) return self + new # legacy protocol def getName(self, value): if value in self.__numbers: return self.__numbers[value] def getValue(self, name): if name in self.__names: return self.__names[name] def getValues(self, *names): try: return [self.__names[name] for name in names] except KeyError: raise error.PyAsn1Error( 'Unknown bit identifier(s): %s' % (set(names).difference(self.__names),) ) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/type/opentype.py0000644000175000017500000000545514525242621017626 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # __all__ = ['OpenType'] class OpenType(object): """Create ASN.1 type map indexed by a value The *OpenType* object models an untyped field of a constructed ASN.1 type. In ASN.1 syntax it is usually represented by the `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`, `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically used together with :class:`~pyasn1.type.univ.Any` object. OpenType objects duck-type a read-only Python :class:`dict` objects, however the passed `typeMap` is not copied, but stored by reference. That means the user can manipulate `typeMap` at run time having this reflected on *OpenType* object behavior. The |OpenType| class models an untyped field of a constructed ASN.1 type. In ASN.1 syntax it is usually represented by the `ANY DEFINED BY` for scalars or `SET OF ANY DEFINED BY`, `SEQUENCE OF ANY DEFINED BY` for container types clauses. Typically used with :class:`~pyasn1.type.univ.Any` type. Parameters ---------- name: :py:class:`str` Field name typeMap: :py:class:`dict` A map of value->ASN.1 type. It's stored by reference and can be mutated later to register new mappings. Examples -------- For untyped scalars: .. code-block:: python openType = OpenType( 'id', {1: Integer(), 2: OctetString()} ) Sequence( componentType=NamedTypes( NamedType('id', Integer()), NamedType('blob', Any(), openType=openType) ) ) For untyped `SET OF` or `SEQUENCE OF` vectors: .. code-block:: python openType = OpenType( 'id', {1: Integer(), 2: OctetString()} ) Sequence( componentType=NamedTypes( NamedType('id', Integer()), NamedType('blob', SetOf(componentType=Any()), openType=openType) ) ) """ def __init__(self, name, typeMap=None): self.__name = name if typeMap is None: self.__typeMap = {} else: self.__typeMap = typeMap @property def name(self): return self.__name # Python dict protocol def values(self): return self.__typeMap.values() def keys(self): return self.__typeMap.keys() def items(self): return self.__typeMap.items() def __contains__(self, key): return key in self.__typeMap def __getitem__(self, key): return self.__typeMap[key] def __iter__(self): return iter(self.__typeMap) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/tag.py0000644000175000017500000002243114670137102016525 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from pyasn1 import error __all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext', 'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed', 'tagCategoryImplicit', 'tagCategoryExplicit', 'tagCategoryUntagged', 'Tag', 'TagSet'] #: Identifier for ASN.1 class UNIVERSAL tagClassUniversal = 0x00 #: Identifier for ASN.1 class APPLICATION tagClassApplication = 0x40 #: Identifier for ASN.1 class context-specific tagClassContext = 0x80 #: Identifier for ASN.1 class private tagClassPrivate = 0xC0 #: Identifier for "simple" ASN.1 structure (e.g. scalar) tagFormatSimple = 0x00 #: Identifier for "constructed" ASN.1 structure (e.g. may have inner components) tagFormatConstructed = 0x20 tagCategoryImplicit = 0x01 tagCategoryExplicit = 0x02 tagCategoryUntagged = 0x04 class Tag(object): """Create ASN.1 tag Represents ASN.1 tag that can be attached to a ASN.1 type to make types distinguishable from each other. *Tag* objects are immutable and duck-type Python :class:`tuple` objects holding three integer components of a tag. Parameters ---------- tagClass: :py:class:`int` Tag *class* value tagFormat: :py:class:`int` Tag *format* value tagId: :py:class:`int` Tag ID value """ def __init__(self, tagClass, tagFormat, tagId): if tagId < 0: raise error.PyAsn1Error('Negative tag ID (%s) not allowed' % tagId) self.__tagClass = tagClass self.__tagFormat = tagFormat self.__tagId = tagId self.__tagClassId = tagClass, tagId self.__hash = hash(self.__tagClassId) def __repr__(self): representation = '[%s:%s:%s]' % ( self.__tagClass, self.__tagFormat, self.__tagId) return '<%s object, tag %s>' % ( self.__class__.__name__, representation) def __eq__(self, other): return self.__tagClassId == other def __ne__(self, other): return self.__tagClassId != other def __lt__(self, other): return self.__tagClassId < other def __le__(self, other): return self.__tagClassId <= other def __gt__(self, other): return self.__tagClassId > other def __ge__(self, other): return self.__tagClassId >= other def __hash__(self): return self.__hash def __getitem__(self, idx): if idx == 0: return self.__tagClass elif idx == 1: return self.__tagFormat elif idx == 2: return self.__tagId else: raise IndexError def __iter__(self): yield self.__tagClass yield self.__tagFormat yield self.__tagId def __and__(self, otherTag): return self.__class__(self.__tagClass & otherTag.tagClass, self.__tagFormat & otherTag.tagFormat, self.__tagId & otherTag.tagId) def __or__(self, otherTag): return self.__class__(self.__tagClass | otherTag.tagClass, self.__tagFormat | otherTag.tagFormat, self.__tagId | otherTag.tagId) @property def tagClass(self): """ASN.1 tag class Returns ------- : :py:class:`int` Tag class """ return self.__tagClass @property def tagFormat(self): """ASN.1 tag format Returns ------- : :py:class:`int` Tag format """ return self.__tagFormat @property def tagId(self): """ASN.1 tag ID Returns ------- : :py:class:`int` Tag ID """ return self.__tagId class TagSet(object): """Create a collection of ASN.1 tags Represents a combination of :class:`~pyasn1.type.tag.Tag` objects that can be attached to a ASN.1 type to make types distinguishable from each other. *TagSet* objects are immutable and duck-type Python :class:`tuple` objects holding arbitrary number of :class:`~pyasn1.type.tag.Tag` objects. Parameters ---------- baseTag: :class:`~pyasn1.type.tag.Tag` Base *Tag* object. This tag survives IMPLICIT tagging. *superTags: :class:`~pyasn1.type.tag.Tag` Additional *Tag* objects taking part in subtyping. Examples -------- .. code-block:: python class OrderNumber(NumericString): ''' ASN.1 specification Order-number ::= [APPLICATION 5] IMPLICIT NumericString ''' tagSet = NumericString.tagSet.tagImplicitly( Tag(tagClassApplication, tagFormatSimple, 5) ) orderNumber = OrderNumber('1234') """ def __init__(self, baseTag=(), *superTags): self.__baseTag = baseTag self.__superTags = superTags self.__superTagsClassId = tuple( [(superTag.tagClass, superTag.tagId) for superTag in superTags] ) self.__lenOfSuperTags = len(superTags) self.__hash = hash(self.__superTagsClassId) def __repr__(self): representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId) for x in self.__superTags]) if representation: representation = 'tags ' + representation else: representation = 'untagged' return '<%s object, %s>' % (self.__class__.__name__, representation) def __add__(self, superTag): return self.__class__(self.__baseTag, *self.__superTags + (superTag,)) def __radd__(self, superTag): return self.__class__(self.__baseTag, *(superTag,) + self.__superTags) def __getitem__(self, i): if i.__class__ is slice: return self.__class__(self.__baseTag, *self.__superTags[i]) else: return self.__superTags[i] def __eq__(self, other): return self.__superTagsClassId == other def __ne__(self, other): return self.__superTagsClassId != other def __lt__(self, other): return self.__superTagsClassId < other def __le__(self, other): return self.__superTagsClassId <= other def __gt__(self, other): return self.__superTagsClassId > other def __ge__(self, other): return self.__superTagsClassId >= other def __hash__(self): return self.__hash def __len__(self): return self.__lenOfSuperTags @property def baseTag(self): """Return base ASN.1 tag Returns ------- : :class:`~pyasn1.type.tag.Tag` Base tag of this *TagSet* """ return self.__baseTag @property def superTags(self): """Return ASN.1 tags Returns ------- : :py:class:`tuple` Tuple of :class:`~pyasn1.type.tag.Tag` objects that this *TagSet* contains """ return self.__superTags def tagExplicitly(self, superTag): """Return explicitly tagged *TagSet* Create a new *TagSet* representing callee *TagSet* explicitly tagged with passed tag(s). With explicit tagging mode, new tags are appended to existing tag(s). Parameters ---------- superTag: :class:`~pyasn1.type.tag.Tag` *Tag* object to tag this *TagSet* Returns ------- : :class:`~pyasn1.type.tag.TagSet` New *TagSet* object """ if superTag.tagClass == tagClassUniversal: raise error.PyAsn1Error("Can't tag with UNIVERSAL class tag") if superTag.tagFormat != tagFormatConstructed: superTag = Tag(superTag.tagClass, tagFormatConstructed, superTag.tagId) return self + superTag def tagImplicitly(self, superTag): """Return implicitly tagged *TagSet* Create a new *TagSet* representing callee *TagSet* implicitly tagged with passed tag(s). With implicit tagging mode, new tag(s) replace the last existing tag. Parameters ---------- superTag: :class:`~pyasn1.type.tag.Tag` *Tag* object to tag this *TagSet* Returns ------- : :class:`~pyasn1.type.tag.TagSet` New *TagSet* object """ if self.__superTags: superTag = Tag(superTag.tagClass, self.__superTags[-1].tagFormat, superTag.tagId) return self[:-1] + superTag def isSuperTagSetOf(self, tagSet): """Test type relationship against given *TagSet* The callee is considered to be a supertype of given *TagSet* tag-wise if all tags in *TagSet* are present in the callee and they are in the same order. Parameters ---------- tagSet: :class:`~pyasn1.type.tag.TagSet` *TagSet* object to evaluate against the callee Returns ------- : :py:class:`bool` :obj:`True` if callee is a supertype of *tagSet* """ if len(tagSet) < self.__lenOfSuperTags: return False return self.__superTags == tagSet[:self.__lenOfSuperTags] # Backward compatibility def getBaseTag(self): return self.__baseTag def initTagSet(tag): return TagSet(tag, tag) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/tagmap.py0000644000175000017500000000567014670137102017231 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from pyasn1 import error __all__ = ['TagMap'] class TagMap(object): """Map *TagSet* objects to ASN.1 types Create an object mapping *TagSet* object to ASN.1 type. *TagMap* objects are immutable and duck-type read-only Python :class:`dict` objects holding *TagSet* objects as keys and ASN.1 type objects as values. Parameters ---------- presentTypes: :py:class:`dict` Map of :class:`~pyasn1.type.tag.TagSet` to ASN.1 objects considered as being unconditionally present in the *TagMap*. skipTypes: :py:class:`dict` A collection of :class:`~pyasn1.type.tag.TagSet` objects considered as absent in the *TagMap* even when *defaultType* is present. defaultType: ASN.1 type object An ASN.1 type object callee *TagMap* returns for any *TagSet* key not present in *presentTypes* (unless given key is present in *skipTypes*). """ def __init__(self, presentTypes=None, skipTypes=None, defaultType=None): self.__presentTypes = presentTypes or {} self.__skipTypes = skipTypes or {} self.__defaultType = defaultType def __contains__(self, tagSet): return (tagSet in self.__presentTypes or self.__defaultType is not None and tagSet not in self.__skipTypes) def __getitem__(self, tagSet): try: return self.__presentTypes[tagSet] except KeyError: if self.__defaultType is None: raise elif tagSet in self.__skipTypes: raise error.PyAsn1Error('Key in negative map') else: return self.__defaultType def __iter__(self): return iter(self.__presentTypes) def __repr__(self): representation = '%s object' % self.__class__.__name__ if self.__presentTypes: representation += ', present %s' % repr(self.__presentTypes) if self.__skipTypes: representation += ', skip %s' % repr(self.__skipTypes) if self.__defaultType is not None: representation += ', default %s' % repr(self.__defaultType) return '<%s>' % representation @property def presentTypes(self): """Return *TagSet* to ASN.1 type map present in callee *TagMap*""" return self.__presentTypes @property def skipTypes(self): """Return *TagSet* collection unconditionally absent in callee *TagMap*""" return self.__skipTypes @property def defaultType(self): """Return default ASN.1 type being returned for any missing *TagSet*""" return self.__defaultType # Backward compatibility def getPosMap(self): return self.presentTypes def getNegMap(self): return self.skipTypes def getDef(self): return self.defaultType ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/pyasn1/type/univ.py0000644000175000017500000032523414670137102016742 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import math import sys from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.compat import integer from pyasn1.type import base from pyasn1.type import constraint from pyasn1.type import namedtype from pyasn1.type import namedval from pyasn1.type import tag from pyasn1.type import tagmap NoValue = base.NoValue noValue = NoValue() __all__ = ['Integer', 'Boolean', 'BitString', 'OctetString', 'Null', 'ObjectIdentifier', 'Real', 'Enumerated', 'SequenceOfAndSetOfBase', 'SequenceOf', 'SetOf', 'SequenceAndSetBase', 'Sequence', 'Set', 'Choice', 'Any', 'NoValue', 'noValue'] # "Simple" ASN.1 types (yet incomplete) class Integer(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`int` objects. Keyword Args ------------ value: :class:`int`, :class:`str` or |ASN.1| object Python :class:`int` or :class:`str` literal or |ASN.1| class instance. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` Object representing non-default symbolic aliases for numbers Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class ErrorCode(Integer): ''' ASN.1 specification: ErrorCode ::= INTEGER { disk-full(1), no-disk(-1), disk-not-formatted(2) } error ErrorCode ::= disk-full ''' namedValues = NamedValues( ('disk-full', 1), ('no-disk', -1), ('disk-not-formatted', 2) ) error = ErrorCode('disk-full') """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object #: representing symbolic aliases for numbers namedValues = namedval.NamedValues() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() def __init__(self, value=noValue, **kwargs): if 'namedValues' not in kwargs: kwargs['namedValues'] = self.namedValues base.SimpleAsn1Type.__init__(self, value, **kwargs) def __and__(self, value): return self.clone(self._value & value) def __rand__(self, value): return self.clone(value & self._value) def __or__(self, value): return self.clone(self._value | value) def __ror__(self, value): return self.clone(value | self._value) def __xor__(self, value): return self.clone(self._value ^ value) def __rxor__(self, value): return self.clone(value ^ self._value) def __lshift__(self, value): return self.clone(self._value << value) def __rshift__(self, value): return self.clone(self._value >> value) def __add__(self, value): return self.clone(self._value + value) def __radd__(self, value): return self.clone(value + self._value) def __sub__(self, value): return self.clone(self._value - value) def __rsub__(self, value): return self.clone(value - self._value) def __mul__(self, value): return self.clone(self._value * value) def __rmul__(self, value): return self.clone(value * self._value) def __mod__(self, value): return self.clone(self._value % value) def __rmod__(self, value): return self.clone(value % self._value) def __pow__(self, value, modulo=None): return self.clone(pow(self._value, value, modulo)) def __rpow__(self, value): return self.clone(pow(value, self._value)) def __floordiv__(self, value): return self.clone(self._value // value) def __rfloordiv__(self, value): return self.clone(value // self._value) def __truediv__(self, value): return Real(self._value / value) def __rtruediv__(self, value): return Real(value / self._value) def __divmod__(self, value): return self.clone(divmod(self._value, value)) def __rdivmod__(self, value): return self.clone(divmod(value, self._value)) __hash__ = base.SimpleAsn1Type.__hash__ def __int__(self): return int(self._value) def __float__(self): return float(self._value) def __abs__(self): return self.clone(abs(self._value)) def __index__(self): return int(self._value) def __pos__(self): return self.clone(+self._value) def __neg__(self): return self.clone(-self._value) def __invert__(self): return self.clone(~self._value) def __round__(self, n=0): r = round(self._value, n) if n: return self.clone(r) else: return r def __floor__(self): return math.floor(self._value) def __ceil__(self): return math.ceil(self._value) def __trunc__(self): return self.clone(math.trunc(self._value)) def __lt__(self, value): return self._value < value def __le__(self, value): return self._value <= value def __eq__(self, value): return self._value == value def __ne__(self, value): return self._value != value def __gt__(self, value): return self._value > value def __ge__(self, value): return self._value >= value def prettyIn(self, value): try: return int(value) except ValueError: try: return self.namedValues[value] except KeyError as exc: raise error.PyAsn1Error( 'Can\'t coerce %r into integer: %s' % (value, exc) ) def prettyOut(self, value): try: return str(self.namedValues[value]) except KeyError: return str(value) # backward compatibility def getNamedValues(self): return self.namedValues class Boolean(Integer): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`int` objects. Keyword Args ------------ value: :class:`int`, :class:`str` or |ASN.1| object Python :class:`int` or :class:`str` literal or |ASN.1| class instance. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s).Constraints verification for |ASN.1| type occurs automatically on object instantiation. namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` Object representing non-default symbolic aliases for numbers Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class RoundResult(Boolean): ''' ASN.1 specification: RoundResult ::= BOOLEAN ok RoundResult ::= TRUE ko RoundResult ::= FALSE ''' ok = RoundResult(True) ko = RoundResult(False) """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01), ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = Integer.subtypeSpec + constraint.SingleValueConstraint(0, 1) #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object #: representing symbolic aliases for numbers namedValues = namedval.NamedValues(('False', 0), ('True', 1)) # Optimization for faster codec lookup typeId = Integer.getTypeId() class SizedInteger(int): bitLength = leadingZeroBits = None def setBitLength(self, bitLength): self.bitLength = bitLength self.leadingZeroBits = max(bitLength - self.bit_length(), 0) return self def __len__(self): if self.bitLength is None: self.setBitLength(self.bit_length()) return self.bitLength class BitString(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type both Python :class:`tuple` (as a tuple of bits) and :class:`int` objects. Keyword Args ------------ value: :class:`int`, :class:`str` or |ASN.1| object Python :class:`int` or :class:`str` literal representing binary or hexadecimal number or sequence of integer bits or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` Object representing non-default symbolic aliases for numbers binValue: :py:class:`str` Binary string initializer to use instead of the *value*. Example: '10110011'. hexValue: :py:class:`str` Hexadecimal string initializer to use instead of the *value*. Example: 'DEADBEEF'. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class Rights(BitString): ''' ASN.1 specification: Rights ::= BIT STRING { user-read(0), user-write(1), group-read(2), group-write(3), other-read(4), other-write(5) } group1 Rights ::= { group-read, group-write } group2 Rights ::= '0011'B group3 Rights ::= '3'H ''' namedValues = NamedValues( ('user-read', 0), ('user-write', 1), ('group-read', 2), ('group-write', 3), ('other-read', 4), ('other-write', 5) ) group1 = Rights(('group-read', 'group-write')) group2 = Rights('0011') group3 = Rights(0x3) """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object #: representing symbolic aliases for numbers namedValues = namedval.NamedValues() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() defaultBinValue = defaultHexValue = noValue def __init__(self, value=noValue, **kwargs): if value is noValue: if kwargs: try: value = self.fromBinaryString(kwargs.pop('binValue'), internalFormat=True) except KeyError: pass try: value = self.fromHexString(kwargs.pop('hexValue'), internalFormat=True) except KeyError: pass if value is noValue: if self.defaultBinValue is not noValue: value = self.fromBinaryString(self.defaultBinValue, internalFormat=True) elif self.defaultHexValue is not noValue: value = self.fromHexString(self.defaultHexValue, internalFormat=True) if 'namedValues' not in kwargs: kwargs['namedValues'] = self.namedValues base.SimpleAsn1Type.__init__(self, value, **kwargs) def __str__(self): return self.asBinary() def __eq__(self, other): other = self.prettyIn(other) return self is other or self._value == other and len(self._value) == len(other) def __ne__(self, other): other = self.prettyIn(other) return self._value != other or len(self._value) != len(other) def __lt__(self, other): other = self.prettyIn(other) return len(self._value) < len(other) or len(self._value) == len(other) and self._value < other def __le__(self, other): other = self.prettyIn(other) return len(self._value) <= len(other) or len(self._value) == len(other) and self._value <= other def __gt__(self, other): other = self.prettyIn(other) return len(self._value) > len(other) or len(self._value) == len(other) and self._value > other def __ge__(self, other): other = self.prettyIn(other) return len(self._value) >= len(other) or len(self._value) == len(other) and self._value >= other # Immutable sequence object protocol def __len__(self): return len(self._value) def __getitem__(self, i): if i.__class__ is slice: return self.clone([self[x] for x in range(*i.indices(len(self)))]) else: length = len(self._value) - 1 if i > length or i < 0: raise IndexError('bit index out of range') return (self._value >> (length - i)) & 1 def __iter__(self): length = len(self._value) while length: length -= 1 yield (self._value >> length) & 1 def __reversed__(self): return reversed(tuple(self)) # arithmetic operators def __add__(self, value): value = self.prettyIn(value) return self.clone(SizedInteger(self._value << len(value) | value).setBitLength(len(self._value) + len(value))) def __radd__(self, value): value = self.prettyIn(value) return self.clone(SizedInteger(value << len(self._value) | self._value).setBitLength(len(self._value) + len(value))) def __mul__(self, value): bitString = self._value while value > 1: bitString <<= len(self._value) bitString |= self._value value -= 1 return self.clone(bitString) def __rmul__(self, value): return self * value def __lshift__(self, count): return self.clone(SizedInteger(self._value << count).setBitLength(len(self._value) + count)) def __rshift__(self, count): return self.clone(SizedInteger(self._value >> count).setBitLength(max(0, len(self._value) - count))) def __int__(self): return int(self._value) def __float__(self): return float(self._value) def asNumbers(self): """Get |ASN.1| value as a sequence of 8-bit integers. If |ASN.1| object length is not a multiple of 8, result will be left-padded with zeros. """ return tuple(self.asOctets()) def asOctets(self): """Get |ASN.1| value as a sequence of octets. If |ASN.1| object length is not a multiple of 8, result will be left-padded with zeros. """ return integer.to_bytes(self._value, length=len(self)) def asInteger(self): """Get |ASN.1| value as a single integer value. """ return self._value def asBinary(self): """Get |ASN.1| value as a text string of bits. """ binString = bin(self._value)[2:] return '0' * (len(self._value) - len(binString)) + binString @classmethod def fromHexString(cls, value, internalFormat=False, prepend=None): """Create a |ASN.1| object initialized from the hex string. Parameters ---------- value: :class:`str` Text string like 'DEADBEEF' """ try: value = SizedInteger(value, 16).setBitLength(len(value) * 4) except ValueError as exc: raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, exc)) if prepend is not None: value = SizedInteger( (SizedInteger(prepend) << len(value)) | value ).setBitLength(len(prepend) + len(value)) if not internalFormat: value = cls(value) return value @classmethod def fromBinaryString(cls, value, internalFormat=False, prepend=None): """Create a |ASN.1| object initialized from a string of '0' and '1'. Parameters ---------- value: :class:`str` Text string like '1010111' """ try: value = SizedInteger(value or '0', 2).setBitLength(len(value)) except ValueError as exc: raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, exc)) if prepend is not None: value = SizedInteger( (SizedInteger(prepend) << len(value)) | value ).setBitLength(len(prepend) + len(value)) if not internalFormat: value = cls(value) return value @classmethod def fromOctetString(cls, value, internalFormat=False, prepend=None, padding=0): """Create a |ASN.1| object initialized from a string. Parameters ---------- value: :class:`bytes` Text string like b'\\\\x01\\\\xff' """ value = SizedInteger(int.from_bytes(bytes(value), 'big') >> padding).setBitLength(len(value) * 8 - padding) if prepend is not None: value = SizedInteger( (SizedInteger(prepend) << len(value)) | value ).setBitLength(len(prepend) + len(value)) if not internalFormat: value = cls(value) return value def prettyIn(self, value): if isinstance(value, SizedInteger): return value elif isinstance(value, str): if not value: return SizedInteger(0).setBitLength(0) elif value[0] == '\'': # "'1011'B" -- ASN.1 schema representation (deprecated) if value[-2:] == '\'B': return self.fromBinaryString(value[1:-2], internalFormat=True) elif value[-2:] == '\'H': return self.fromHexString(value[1:-2], internalFormat=True) else: raise error.PyAsn1Error( 'Bad BIT STRING value notation %s' % (value,) ) elif self.namedValues and not value.isdigit(): # named bits like 'Urgent, Active' names = [x.strip() for x in value.split(',')] try: bitPositions = [self.namedValues[name] for name in names] except KeyError: raise error.PyAsn1Error('unknown bit name(s) in %r' % (names,)) rightmostPosition = max(bitPositions) number = 0 for bitPosition in bitPositions: number |= 1 << (rightmostPosition - bitPosition) return SizedInteger(number).setBitLength(rightmostPosition + 1) elif value.startswith('0x'): return self.fromHexString(value[2:], internalFormat=True) elif value.startswith('0b'): return self.fromBinaryString(value[2:], internalFormat=True) else: # assume plain binary string like '1011' return self.fromBinaryString(value, internalFormat=True) elif isinstance(value, (tuple, list)): return self.fromBinaryString(''.join([b and '1' or '0' for b in value]), internalFormat=True) elif isinstance(value, BitString): return SizedInteger(value).setBitLength(len(value)) elif isinstance(value, int): return SizedInteger(value) else: raise error.PyAsn1Error( 'Bad BitString initializer type \'%s\'' % (value,) ) class OctetString(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type :class:`bytes`. When used in Unicode context, |ASN.1| type assumes "|encoding|" serialisation. Keyword Args ------------ value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object :class:`bytes`, alternatively :class:`str` representing character string to be serialised into octets (note `encoding` parameter) or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. encoding: :py:class:`str` Unicode codec ID to encode/decode :class:`str` the payload when |ASN.1| object is used in text string context. binValue: :py:class:`str` Binary string initializer to use instead of the *value*. Example: '10110011'. hexValue: :py:class:`str` Hexadecimal string initializer to use instead of the *value*. Example: 'DEADBEEF'. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class Icon(OctetString): ''' ASN.1 specification: Icon ::= OCTET STRING icon1 Icon ::= '001100010011001000110011'B icon2 Icon ::= '313233'H ''' icon1 = Icon.fromBinaryString('001100010011001000110011') icon2 = Icon.fromHexString('313233') """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() defaultBinValue = defaultHexValue = noValue encoding = 'iso-8859-1' def __init__(self, value=noValue, **kwargs): if kwargs: if value is noValue: try: value = self.fromBinaryString(kwargs.pop('binValue')) except KeyError: pass try: value = self.fromHexString(kwargs.pop('hexValue')) except KeyError: pass if value is noValue: if self.defaultBinValue is not noValue: value = self.fromBinaryString(self.defaultBinValue) elif self.defaultHexValue is not noValue: value = self.fromHexString(self.defaultHexValue) if 'encoding' not in kwargs: kwargs['encoding'] = self.encoding base.SimpleAsn1Type.__init__(self, value, **kwargs) def prettyIn(self, value): if isinstance(value, bytes): return value elif isinstance(value, str): try: return value.encode(self.encoding) except UnicodeEncodeError as exc: raise error.PyAsn1UnicodeEncodeError( "Can't encode string '%s' with '%s' " "codec" % (value, self.encoding), exc ) elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way return value.asOctets() elif isinstance(value, base.SimpleAsn1Type): # this mostly targets Integer objects return self.prettyIn(str(value)) elif isinstance(value, (tuple, list)): return self.prettyIn(bytes(value)) else: return bytes(value) def __str__(self): try: return self._value.decode(self.encoding) except UnicodeDecodeError as exc: raise error.PyAsn1UnicodeDecodeError( "Can't decode string '%s' with '%s' codec at " "'%s'" % (self._value, self.encoding, self.__class__.__name__), exc ) def __bytes__(self): return bytes(self._value) def asOctets(self): return bytes(self._value) def asNumbers(self): return tuple(self._value) # # Normally, `.prettyPrint()` is called from `__str__()`. Historically, # OctetString.prettyPrint() used to return hexified payload # representation in cases when non-printable content is present. At the # same time `str()` used to produce either octet-stream (Py2) or # text (Py3) representations. # # Therefore `OctetString.__str__()` -> `.prettyPrint()` call chain is # reversed to preserve the original behaviour. # # Eventually we should deprecate `.prettyPrint()` / `.prettyOut()` harness # and end up with just `__str__()` producing hexified representation while # both text and octet-stream representation should only be requested via # the `.asOctets()` method. # # Note: ASN.1 OCTET STRING is never mean to contain text! # def prettyOut(self, value): return value def prettyPrint(self, scope=0): # first see if subclass has its own .prettyOut() value = self.prettyOut(self._value) if value is not self._value: return value numbers = self.asNumbers() for x in numbers: # hexify if needed if x < 32 or x > 126: return '0x' + ''.join(('%.2x' % x for x in numbers)) else: # this prevents infinite recursion return OctetString.__str__(self) @staticmethod def fromBinaryString(value): """Create a |ASN.1| object initialized from a string of '0' and '1'. Parameters ---------- value: :class:`str` Text string like '1010111' """ bitNo = 8 byte = 0 r = [] for v in value: if bitNo: bitNo -= 1 else: bitNo = 7 r.append(byte) byte = 0 if v in ('0', '1'): v = int(v) else: raise error.PyAsn1Error( 'Non-binary OCTET STRING initializer %s' % (v,) ) byte |= v << bitNo r.append(byte) return bytes(r) @staticmethod def fromHexString(value): """Create a |ASN.1| object initialized from the hex string. Parameters ---------- value: :class:`str` Text string like 'DEADBEEF' """ r = [] p = [] for v in value: if p: r.append(int(p + v, 16)) p = None else: p = v if p: r.append(int(p + '0', 16)) return bytes(r) # Immutable sequence object protocol def __len__(self): return len(self._value) def __getitem__(self, i): if i.__class__ is slice: return self.clone(self._value[i]) else: return self._value[i] def __iter__(self): return iter(self._value) def __contains__(self, value): return value in self._value def __add__(self, value): return self.clone(self._value + self.prettyIn(value)) def __radd__(self, value): return self.clone(self.prettyIn(value) + self._value) def __mul__(self, value): return self.clone(self._value * value) def __rmul__(self, value): return self * value def __int__(self): return int(self._value) def __float__(self): return float(self._value) def __reversed__(self): return reversed(self._value) class Null(OctetString): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`str` objects (always empty). Keyword Args ------------ value: :class:`str` or |ASN.1| object Python empty :class:`str` literal or any object that evaluates to :obj:`False` If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class Ack(Null): ''' ASN.1 specification: Ack ::= NULL ''' ack = Ack('') """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05) ) subtypeSpec = OctetString.subtypeSpec + constraint.SingleValueConstraint(b'') # Optimization for faster codec lookup typeId = OctetString.getTypeId() def prettyIn(self, value): if value: return value return b'' class ObjectIdentifier(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`tuple` objects (tuple of non-negative integers). Keyword Args ------------ value: :class:`tuple`, :class:`str` or |ASN.1| object Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class ID(ObjectIdentifier): ''' ASN.1 specification: ID ::= OBJECT IDENTIFIER id-edims ID ::= { joint-iso-itu-t mhs-motif(6) edims(7) } id-bp ID ::= { id-edims 11 } ''' id_edims = ID('2.6.7') id_bp = id_edims + (11,) """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() def __add__(self, other): return self.clone(self._value + other) def __radd__(self, other): return self.clone(other + self._value) def asTuple(self): return self._value # Sequence object protocol def __len__(self): return len(self._value) def __getitem__(self, i): if i.__class__ is slice: return self.clone(self._value[i]) else: return self._value[i] def __iter__(self): return iter(self._value) def __contains__(self, value): return value in self._value def index(self, suboid): return self._value.index(suboid) def isPrefixOf(self, other): """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object. Parameters ---------- other: |ASN.1| object |ASN.1| object Returns ------- : :class:`bool` :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object or :obj:`False` otherwise. """ l = len(self) if l <= len(other): if self._value[:l] == other[:l]: return True return False def prettyIn(self, value): if isinstance(value, ObjectIdentifier): return tuple(value) elif isinstance(value, str): if '-' in value: raise error.PyAsn1Error( # sys.exc_info in case prettyIn was called while handling an exception 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) ) try: return tuple([int(subOid) for subOid in value.split('.') if subOid]) except ValueError as exc: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc) ) try: tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) except (ValueError, TypeError) as exc: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, exc) ) if len(tupleOfInts) == len(value): return tupleOfInts raise error.PyAsn1Error('Malformed Object ID %s at %s' % (value, self.__class__.__name__)) def prettyOut(self, value): return '.'.join([str(x) for x in value]) class RelativeOID(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`tuple` objects (tuple of non-negative integers). Keyword Args ------------ value: :class:`tuple`, :class:`str` or |ASN.1| object Python sequence of :class:`int` or :class:`str` literal or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class RelOID(RelativeOID): ''' ASN.1 specification: id-pad-null RELATIVE-OID ::= { 0 } id-pad-once RELATIVE-OID ::= { 5 6 } id-pad-twice RELATIVE-OID ::= { 5 6 7 } ''' id_pad_null = RelOID('0') id_pad_once = RelOID('5.6') id_pad_twice = id_pad_once + (7,) """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() def __add__(self, other): return self.clone(self._value + other) def __radd__(self, other): return self.clone(other + self._value) def asTuple(self): return self._value # Sequence object protocol def __len__(self): return len(self._value) def __getitem__(self, i): if i.__class__ is slice: return self.clone(self._value[i]) else: return self._value[i] def __iter__(self): return iter(self._value) def __contains__(self, value): return value in self._value def index(self, suboid): return self._value.index(suboid) def isPrefixOf(self, other): """Indicate if this |ASN.1| object is a prefix of other |ASN.1| object. Parameters ---------- other: |ASN.1| object |ASN.1| object Returns ------- : :class:`bool` :obj:`True` if this |ASN.1| object is a parent (e.g. prefix) of the other |ASN.1| object or :obj:`False` otherwise. """ l = len(self) if l <= len(other): if self._value[:l] == other[:l]: return True return False def prettyIn(self, value): if isinstance(value, RelativeOID): return tuple(value) elif isinstance(value, str): if '-' in value: raise error.PyAsn1Error( # sys.exc_info in case prettyIn was called while handling an exception 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) ) try: return tuple([int(subOid) for subOid in value.split('.') if subOid]) except ValueError as exc: raise error.PyAsn1Error( 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc) ) try: tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) except (ValueError, TypeError) as exc: raise error.PyAsn1Error( 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, exc) ) if len(tupleOfInts) == len(value): return tupleOfInts raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__)) def prettyOut(self, value): return '.'.join([str(x) for x in value]) class Real(base.SimpleAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`float` objects. Additionally, |ASN.1| objects behave like a :class:`tuple` in which case its elements are mantissa, base and exponent. Keyword Args ------------ value: :class:`tuple`, :class:`float` or |ASN.1| object Python sequence of :class:`int` (representing mantissa, base and exponent) or :class:`float` instance or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class Pi(Real): ''' ASN.1 specification: Pi ::= REAL pi Pi ::= { mantissa 314159, base 10, exponent -5 } ''' pi = Pi((314159, 10, -5)) """ binEncBase = None # binEncBase = 16 is recommended for large numbers try: _plusInf = float('inf') _minusInf = float('-inf') _inf = _plusInf, _minusInf except ValueError: # Infinity support is platform and Python dependent _plusInf = _minusInf = None _inf = () #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Optimization for faster codec lookup typeId = base.SimpleAsn1Type.getTypeId() @staticmethod def __normalizeBase10(value): m, b, e = value while m and m % 10 == 0: m /= 10 e += 1 return m, b, e def prettyIn(self, value): if isinstance(value, tuple) and len(value) == 3: if (not isinstance(value[0], (int, float)) or not isinstance(value[1], int) or not isinstance(value[2], int)): raise error.PyAsn1Error('Lame Real value syntax: %s' % (value,)) if (isinstance(value[0], float) and self._inf and value[0] in self._inf): return value[0] if value[1] not in (2, 10): raise error.PyAsn1Error( 'Prohibited base for Real value: %s' % (value[1],) ) if value[1] == 10: value = self.__normalizeBase10(value) return value elif isinstance(value, int): return self.__normalizeBase10((value, 10, 0)) elif isinstance(value, float) or isinstance(value, str): if isinstance(value, str): try: value = float(value) except ValueError: raise error.PyAsn1Error( 'Bad real value syntax: %s' % (value,) ) if self._inf and value in self._inf: return value else: e = 0 while int(value) != value: value *= 10 e -= 1 return self.__normalizeBase10((int(value), 10, e)) elif isinstance(value, Real): return tuple(value) raise error.PyAsn1Error( 'Bad real value syntax: %s' % (value,) ) def prettyPrint(self, scope=0): try: return self.prettyOut(float(self)) except OverflowError: return '' @property def isPlusInf(self): """Indicate PLUS-INFINITY object value Returns ------- : :class:`bool` :obj:`True` if calling object represents plus infinity or :obj:`False` otherwise. """ return self._value == self._plusInf @property def isMinusInf(self): """Indicate MINUS-INFINITY object value Returns ------- : :class:`bool` :obj:`True` if calling object represents minus infinity or :obj:`False` otherwise. """ return self._value == self._minusInf @property def isInf(self): return self._value in self._inf def __add__(self, value): return self.clone(float(self) + value) def __radd__(self, value): return self + value def __mul__(self, value): return self.clone(float(self) * value) def __rmul__(self, value): return self * value def __sub__(self, value): return self.clone(float(self) - value) def __rsub__(self, value): return self.clone(value - float(self)) def __mod__(self, value): return self.clone(float(self) % value) def __rmod__(self, value): return self.clone(value % float(self)) def __pow__(self, value, modulo=None): return self.clone(pow(float(self), value, modulo)) def __rpow__(self, value): return self.clone(pow(value, float(self))) def __truediv__(self, value): return self.clone(float(self) / value) def __rtruediv__(self, value): return self.clone(value / float(self)) def __divmod__(self, value): return self.clone(float(self) // value) def __rdivmod__(self, value): return self.clone(value // float(self)) def __int__(self): return int(float(self)) def __float__(self): if self._value in self._inf: return self._value else: return float( self._value[0] * pow(self._value[1], self._value[2]) ) def __abs__(self): return self.clone(abs(float(self))) def __pos__(self): return self.clone(+float(self)) def __neg__(self): return self.clone(-float(self)) def __round__(self, n=0): r = round(float(self), n) if n: return self.clone(r) else: return r def __floor__(self): return self.clone(math.floor(float(self))) def __ceil__(self): return self.clone(math.ceil(float(self))) def __trunc__(self): return self.clone(math.trunc(float(self))) def __lt__(self, value): return float(self) < value def __le__(self, value): return float(self) <= value def __eq__(self, value): return float(self) == value def __ne__(self, value): return float(self) != value def __gt__(self, value): return float(self) > value def __ge__(self, value): return float(self) >= value def __bool__(self): return bool(float(self)) __hash__ = base.SimpleAsn1Type.__hash__ def __getitem__(self, idx): if self._value in self._inf: raise error.PyAsn1Error('Invalid infinite value operation') else: return self._value[idx] # compatibility stubs def isPlusInfinity(self): return self.isPlusInf def isMinusInfinity(self): return self.isMinusInf def isInfinity(self): return self.isInf class Enumerated(Integer): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type Python :class:`int` objects. Keyword Args ------------ value: :class:`int`, :class:`str` or |ASN.1| object Python :class:`int` or :class:`str` literal or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. namedValues: :py:class:`~pyasn1.type.namedval.NamedValues` Object representing non-default symbolic aliases for numbers Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class RadioButton(Enumerated): ''' ASN.1 specification: RadioButton ::= ENUMERATED { button1(0), button2(1), button3(2) } selected-by-default RadioButton ::= button1 ''' namedValues = NamedValues( ('button1', 0), ('button2', 1), ('button3', 2) ) selected_by_default = RadioButton('button1') """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0A) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Optimization for faster codec lookup typeId = Integer.getTypeId() #: Default :py:class:`~pyasn1.type.namedval.NamedValues` object #: representing symbolic aliases for numbers namedValues = namedval.NamedValues() # "Structured" ASN.1 types class SequenceOfAndSetOfBase(base.ConstructedAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, its objects are mutable and duck-type Python :class:`list` objects. Keyword Args ------------ componentType : :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A pyasn1 object representing ASN.1 type allowed within |ASN.1| type tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type can only occur on explicit `.isInconsistent` call. Examples -------- .. code-block:: python class LotteryDraw(SequenceOf): # SetOf is similar ''' ASN.1 specification: LotteryDraw ::= SEQUENCE OF INTEGER ''' componentType = Integer() lotteryDraw = LotteryDraw() lotteryDraw.extend([123, 456, 789]) """ def __init__(self, *args, **kwargs): # support positional params for backward compatibility if args: for key, value in zip(('componentType', 'tagSet', 'subtypeSpec'), args): if key in kwargs: raise error.PyAsn1Error('Conflicting positional and keyword params!') kwargs['componentType'] = value self._componentValues = noValue base.ConstructedAsn1Type.__init__(self, **kwargs) # Python list protocol def __getitem__(self, idx): try: return self.getComponentByPosition(idx) except error.PyAsn1Error as exc: raise IndexError(exc) def __setitem__(self, idx, value): try: self.setComponentByPosition(idx, value) except error.PyAsn1Error as exc: raise IndexError(exc) def append(self, value): if self._componentValues is noValue: pos = 0 else: pos = len(self._componentValues) self[pos] = value def count(self, value): return list(self._componentValues.values()).count(value) def extend(self, values): for value in values: self.append(value) if self._componentValues is noValue: self._componentValues = {} def index(self, value, start=0, stop=None): if stop is None: stop = len(self) indices, values = zip(*self._componentValues.items()) # TODO: remove when Py2.5 support is gone values = list(values) try: return indices[values.index(value, start, stop)] except error.PyAsn1Error as exc: raise ValueError(exc) def reverse(self): self._componentValues.reverse() def sort(self, key=None, reverse=False): self._componentValues = dict( enumerate(sorted(self._componentValues.values(), key=key, reverse=reverse))) def __len__(self): if self._componentValues is noValue or not self._componentValues: return 0 return max(self._componentValues) + 1 def __iter__(self): for idx in range(0, len(self)): yield self.getComponentByPosition(idx) def _cloneComponentValues(self, myClone, cloneValueFlag): for idx, componentValue in self._componentValues.items(): if componentValue is not noValue: if isinstance(componentValue, base.ConstructedAsn1Type): myClone.setComponentByPosition( idx, componentValue.clone(cloneValueFlag=cloneValueFlag) ) else: myClone.setComponentByPosition(idx, componentValue.clone()) def getComponentByPosition(self, idx, default=noValue, instantiate=True): """Return |ASN.1| type component value by position. Equivalent to Python sequence subscription operation (e.g. `[]`). Parameters ---------- idx : :class:`int` Component index (zero-based). Must either refer to an existing component or to N+1 component (if *componentType* is set). In the latter case a new component type gets instantiated and appended to the |ASN.1| sequence. Keyword Args ------------ default: :class:`object` If set and requested component is a schema object, return the `default` object instead of the requested component. instantiate: :class:`bool` If :obj:`True` (default), inner component will be automatically instantiated. If :obj:`False` either existing component or the :class:`NoValue` object will be returned. Returns ------- : :py:class:`~pyasn1.type.base.PyAsn1Item` Instantiate |ASN.1| component type or return existing component value Examples -------- .. code-block:: python # can also be SetOf class MySequenceOf(SequenceOf): componentType = OctetString() s = MySequenceOf() # returns component #0 with `.isValue` property False s.getComponentByPosition(0) # returns None s.getComponentByPosition(0, default=None) s.clear() # returns noValue s.getComponentByPosition(0, instantiate=False) # sets component #0 to OctetString() ASN.1 schema # object and returns it s.getComponentByPosition(0, instantiate=True) # sets component #0 to ASN.1 value object s.setComponentByPosition(0, 'ABCD') # returns OctetString('ABCD') value object s.getComponentByPosition(0, instantiate=False) s.clear() # returns noValue s.getComponentByPosition(0, instantiate=False) """ if isinstance(idx, slice): indices = tuple(range(len(self))) return [self.getComponentByPosition(subidx, default, instantiate) for subidx in indices[idx]] if idx < 0: idx = len(self) + idx if idx < 0: raise error.PyAsn1Error( 'SequenceOf/SetOf index is out of range') try: componentValue = self._componentValues[idx] except (KeyError, error.PyAsn1Error): if not instantiate: return default self.setComponentByPosition(idx) componentValue = self._componentValues[idx] if default is noValue or componentValue.isValue: return componentValue else: return default def setComponentByPosition(self, idx, value=noValue, verifyConstraints=True, matchTags=True, matchConstraints=True): """Assign |ASN.1| type component by position. Equivalent to Python sequence item assignment operation (e.g. `[]`) or list.append() (when idx == len(self)). Parameters ---------- idx: :class:`int` Component index (zero-based). Must either refer to existing component or to N+1 component. In the latter case a new component type gets instantiated (if *componentType* is set, or given ASN.1 object is taken otherwise) and appended to the |ASN.1| sequence. Keyword Args ------------ value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A Python value to initialize |ASN.1| component with (if *componentType* is set) or ASN.1 value object to assign to |ASN.1| component. If `value` is not given, schema object will be set as a component. verifyConstraints: :class:`bool` If :obj:`False`, skip constraints validation matchTags: :class:`bool` If :obj:`False`, skip component tags matching matchConstraints: :class:`bool` If :obj:`False`, skip component constraints matching Returns ------- self Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer IndexError When idx > len(self) """ if isinstance(idx, slice): indices = tuple(range(len(self))) startIdx = indices and indices[idx][0] or 0 for subIdx, subValue in enumerate(value): self.setComponentByPosition( startIdx + subIdx, subValue, verifyConstraints, matchTags, matchConstraints) return self if idx < 0: idx = len(self) + idx if idx < 0: raise error.PyAsn1Error( 'SequenceOf/SetOf index is out of range') componentType = self.componentType if self._componentValues is noValue: componentValues = {} else: componentValues = self._componentValues currentValue = componentValues.get(idx, noValue) if value is noValue: if componentType is not None: value = componentType.clone() elif currentValue is noValue: raise error.PyAsn1Error('Component type not defined') elif not isinstance(value, base.Asn1Item): if (componentType is not None and isinstance(componentType, base.SimpleAsn1Type)): value = componentType.clone(value=value) elif (currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type)): value = currentValue.clone(value=value) else: raise error.PyAsn1Error( 'Non-ASN.1 value %r and undefined component' ' type at %r' % (value, self)) elif componentType is not None and (matchTags or matchConstraints): subtypeChecker = ( self.strictConstraints and componentType.isSameTypeWith or componentType.isSuperTypeOf) if not subtypeChecker(value, verifyConstraints and matchTags, verifyConstraints and matchConstraints): # TODO: we should wrap componentType with UnnamedType to carry # additional properties associated with componentType if componentType.typeId != Any.typeId: raise error.PyAsn1Error( 'Component value is tag-incompatible: %r vs ' '%r' % (value, componentType)) componentValues[idx] = value self._componentValues = componentValues return self @property def componentTagMap(self): if self.componentType is not None: return self.componentType.tagMap @property def components(self): return [self._componentValues[idx] for idx in sorted(self._componentValues)] def clear(self): """Remove all components and become an empty |ASN.1| value object. Has the same effect on |ASN.1| object as it does on :class:`list` built-in. """ self._componentValues = {} return self def reset(self): """Remove all components and become a |ASN.1| schema object. See :meth:`isValue` property for more information on the distinction between value and schema objects. """ self._componentValues = noValue return self def prettyPrint(self, scope=0): scope += 1 representation = self.__class__.__name__ + ':\n' if not self.isValue: return representation for idx, componentValue in enumerate(self): representation += ' ' * scope if (componentValue is noValue and self.componentType is not None): representation += '' else: representation += componentValue.prettyPrint(scope) return representation def prettyPrintType(self, scope=0): scope += 1 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) if self.componentType is not None: representation += ' ' * scope representation += self.componentType.prettyPrintType(scope) return representation + '\n' + ' ' * (scope - 1) + '}' @property def isValue(self): """Indicate that |ASN.1| object represents ASN.1 value. If *isValue* is :obj:`False` then this object represents just ASN.1 schema. If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, this object can also be used like a Python built-in object (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). Returns ------- : :class:`bool` :obj:`False` if object represents just ASN.1 schema. :obj:`True` if object represents ASN.1 schema and can be used as a normal value. Note ---- There is an important distinction between PyASN1 schema and value objects. The PyASN1 schema objects can only participate in ASN.1 schema-related operations (e.g. defining or testing the structure of the data). Most obvious uses of ASN.1 schema is to guide serialisation codecs whilst encoding/decoding serialised ASN.1 contents. The PyASN1 value objects can **additionally** participate in many operations involving regular Python objects (e.g. arithmetic, comprehension etc). """ if self._componentValues is noValue: return False if len(self._componentValues) != len(self): return False for componentValue in self._componentValues.values(): if componentValue is noValue or not componentValue.isValue: return False return True @property def isInconsistent(self): """Run necessary checks to ensure |ASN.1| object consistency. Default action is to verify |ASN.1| object against constraints imposed by `subtypeSpec`. Raises ------ :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found """ if self.componentType is noValue or not self.subtypeSpec: return False if self._componentValues is noValue: return True mapping = {} for idx, value in self._componentValues.items(): # Absent fields are not in the mapping if value is noValue: continue mapping[idx] = value try: # Represent SequenceOf/SetOf as a bare dict to constraints chain self.subtypeSpec(mapping) except error.PyAsn1Error as exc: return exc return False class SequenceOf(SequenceOfAndSetOfBase): __doc__ = SequenceOfAndSetOfBase.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) ) #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: object representing ASN.1 type allowed within |ASN.1| type componentType = None #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Disambiguation ASN.1 types identification typeId = SequenceOfAndSetOfBase.getTypeId() class SetOf(SequenceOfAndSetOfBase): __doc__ = SequenceOfAndSetOfBase.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) ) #: Default :py:class:`~pyasn1.type.base.PyAsn1Item` derivative #: object representing ASN.1 type allowed within |ASN.1| type componentType = None #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Disambiguation ASN.1 types identification typeId = SequenceOfAndSetOfBase.getTypeId() class SequenceAndSetBase(base.ConstructedAsn1Type): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, its objects are mutable and duck-type Python :class:`dict` objects. Keyword Args ------------ componentType: :py:class:`~pyasn1.type.namedtype.NamedType` Object holding named ASN.1 types allowed within this collection tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type can only occur on explicit `.isInconsistent` call. Examples -------- .. code-block:: python class Description(Sequence): # Set is similar ''' ASN.1 specification: Description ::= SEQUENCE { surname IA5String, first-name IA5String OPTIONAL, age INTEGER DEFAULT 40 } ''' componentType = NamedTypes( NamedType('surname', IA5String()), OptionalNamedType('first-name', IA5String()), DefaultedNamedType('age', Integer(40)) ) descr = Description() descr['surname'] = 'Smith' descr['first-name'] = 'John' """ #: Default :py:class:`~pyasn1.type.namedtype.NamedTypes` #: object representing named ASN.1 types allowed within |ASN.1| type componentType = namedtype.NamedTypes() class DynamicNames(object): """Fields names/positions mapping for component-less objects""" def __init__(self): self._keyToIdxMap = {} self._idxToKeyMap = {} def __len__(self): return len(self._keyToIdxMap) def __contains__(self, item): return item in self._keyToIdxMap or item in self._idxToKeyMap def __iter__(self): return (self._idxToKeyMap[idx] for idx in range(len(self._idxToKeyMap))) def __getitem__(self, item): try: return self._keyToIdxMap[item] except KeyError: return self._idxToKeyMap[item] def getNameByPosition(self, idx): try: return self._idxToKeyMap[idx] except KeyError: raise error.PyAsn1Error('Type position out of range') def getPositionByName(self, name): try: return self._keyToIdxMap[name] except KeyError: raise error.PyAsn1Error('Name %s not found' % (name,)) def addField(self, idx): self._keyToIdxMap['field-%d' % idx] = idx self._idxToKeyMap[idx] = 'field-%d' % idx def __init__(self, **kwargs): base.ConstructedAsn1Type.__init__(self, **kwargs) self._componentTypeLen = len(self.componentType) if self._componentTypeLen: self._componentValues = [] else: self._componentValues = noValue self._dynamicNames = self._componentTypeLen or self.DynamicNames() def __getitem__(self, idx): if isinstance(idx, str): try: return self.getComponentByName(idx) except error.PyAsn1Error as exc: # duck-typing dict raise KeyError(exc) else: try: return self.getComponentByPosition(idx) except error.PyAsn1Error as exc: # duck-typing list raise IndexError(exc) def __setitem__(self, idx, value): if isinstance(idx, str): try: self.setComponentByName(idx, value) except error.PyAsn1Error as exc: # duck-typing dict raise KeyError(exc) else: try: self.setComponentByPosition(idx, value) except error.PyAsn1Error as exc: # duck-typing list raise IndexError(exc) def __contains__(self, key): if self._componentTypeLen: return key in self.componentType else: return key in self._dynamicNames def __len__(self): return len(self._componentValues) def __iter__(self): return iter(self.componentType or self._dynamicNames) # Python dict protocol def values(self): for idx in range(self._componentTypeLen or len(self._dynamicNames)): yield self[idx] def keys(self): return iter(self) def items(self): for idx in range(self._componentTypeLen or len(self._dynamicNames)): if self._componentTypeLen: yield self.componentType[idx].name, self[idx] else: yield self._dynamicNames[idx], self[idx] def update(self, *iterValue, **mappingValue): for k, v in iterValue: self[k] = v for k in mappingValue: self[k] = mappingValue[k] def clear(self): """Remove all components and become an empty |ASN.1| value object. Has the same effect on |ASN.1| object as it does on :class:`dict` built-in. """ self._componentValues = [] self._dynamicNames = self.DynamicNames() return self def reset(self): """Remove all components and become a |ASN.1| schema object. See :meth:`isValue` property for more information on the distinction between value and schema objects. """ self._componentValues = noValue self._dynamicNames = self.DynamicNames() return self @property def components(self): return self._componentValues def _cloneComponentValues(self, myClone, cloneValueFlag): if self._componentValues is noValue: return for idx, componentValue in enumerate(self._componentValues): if componentValue is not noValue: if isinstance(componentValue, base.ConstructedAsn1Type): myClone.setComponentByPosition( idx, componentValue.clone(cloneValueFlag=cloneValueFlag) ) else: myClone.setComponentByPosition(idx, componentValue.clone()) def getComponentByName(self, name, default=noValue, instantiate=True): """Returns |ASN.1| type component by name. Equivalent to Python :class:`dict` subscription operation (e.g. `[]`). Parameters ---------- name: :class:`str` |ASN.1| type component name Keyword Args ------------ default: :class:`object` If set and requested component is a schema object, return the `default` object instead of the requested component. instantiate: :class:`bool` If :obj:`True` (default), inner component will be automatically instantiated. If :obj:`False` either existing component or the :class:`NoValue` object will be returned. Returns ------- : :py:class:`~pyasn1.type.base.PyAsn1Item` Instantiate |ASN.1| component type or return existing component value """ if self._componentTypeLen: idx = self.componentType.getPositionByName(name) else: try: idx = self._dynamicNames.getPositionByName(name) except KeyError: raise error.PyAsn1Error('Name %s not found' % (name,)) return self.getComponentByPosition(idx, default=default, instantiate=instantiate) def setComponentByName(self, name, value=noValue, verifyConstraints=True, matchTags=True, matchConstraints=True): """Assign |ASN.1| type component by name. Equivalent to Python :class:`dict` item assignment operation (e.g. `[]`). Parameters ---------- name: :class:`str` |ASN.1| type component name Keyword Args ------------ value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A Python value to initialize |ASN.1| component with (if *componentType* is set) or ASN.1 value object to assign to |ASN.1| component. If `value` is not given, schema object will be set as a component. verifyConstraints: :class:`bool` If :obj:`False`, skip constraints validation matchTags: :class:`bool` If :obj:`False`, skip component tags matching matchConstraints: :class:`bool` If :obj:`False`, skip component constraints matching Returns ------- self """ if self._componentTypeLen: idx = self.componentType.getPositionByName(name) else: try: idx = self._dynamicNames.getPositionByName(name) except KeyError: raise error.PyAsn1Error('Name %s not found' % (name,)) return self.setComponentByPosition( idx, value, verifyConstraints, matchTags, matchConstraints ) def getComponentByPosition(self, idx, default=noValue, instantiate=True): """Returns |ASN.1| type component by index. Equivalent to Python sequence subscription operation (e.g. `[]`). Parameters ---------- idx: :class:`int` Component index (zero-based). Must either refer to an existing component or (if *componentType* is set) new ASN.1 schema object gets instantiated. Keyword Args ------------ default: :class:`object` If set and requested component is a schema object, return the `default` object instead of the requested component. instantiate: :class:`bool` If :obj:`True` (default), inner component will be automatically instantiated. If :obj:`False` either existing component or the :class:`NoValue` object will be returned. Returns ------- : :py:class:`~pyasn1.type.base.PyAsn1Item` a PyASN1 object Examples -------- .. code-block:: python # can also be Set class MySequence(Sequence): componentType = NamedTypes( NamedType('id', OctetString()) ) s = MySequence() # returns component #0 with `.isValue` property False s.getComponentByPosition(0) # returns None s.getComponentByPosition(0, default=None) s.clear() # returns noValue s.getComponentByPosition(0, instantiate=False) # sets component #0 to OctetString() ASN.1 schema # object and returns it s.getComponentByPosition(0, instantiate=True) # sets component #0 to ASN.1 value object s.setComponentByPosition(0, 'ABCD') # returns OctetString('ABCD') value object s.getComponentByPosition(0, instantiate=False) s.clear() # returns noValue s.getComponentByPosition(0, instantiate=False) """ try: if self._componentValues is noValue: componentValue = noValue else: componentValue = self._componentValues[idx] except IndexError: componentValue = noValue if not instantiate: if componentValue is noValue or not componentValue.isValue: return default else: return componentValue if componentValue is noValue: self.setComponentByPosition(idx) componentValue = self._componentValues[idx] if default is noValue or componentValue.isValue: return componentValue else: return default def setComponentByPosition(self, idx, value=noValue, verifyConstraints=True, matchTags=True, matchConstraints=True): """Assign |ASN.1| type component by position. Equivalent to Python sequence item assignment operation (e.g. `[]`). Parameters ---------- idx : :class:`int` Component index (zero-based). Must either refer to existing component (if *componentType* is set) or to N+1 component otherwise. In the latter case a new component of given ASN.1 type gets instantiated and appended to |ASN.1| sequence. Keyword Args ------------ value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A Python value to initialize |ASN.1| component with (if *componentType* is set) or ASN.1 value object to assign to |ASN.1| component. If `value` is not given, schema object will be set as a component. verifyConstraints : :class:`bool` If :obj:`False`, skip constraints validation matchTags: :class:`bool` If :obj:`False`, skip component tags matching matchConstraints: :class:`bool` If :obj:`False`, skip component constraints matching Returns ------- self """ componentType = self.componentType componentTypeLen = self._componentTypeLen if self._componentValues is noValue: componentValues = [] else: componentValues = self._componentValues try: currentValue = componentValues[idx] except IndexError: currentValue = noValue if componentTypeLen: if componentTypeLen < idx: raise error.PyAsn1Error('component index out of range') componentValues = [noValue] * componentTypeLen if value is noValue: if componentTypeLen: value = componentType.getTypeByPosition(idx) if isinstance(value, base.ConstructedAsn1Type): value = value.clone(cloneValueFlag=componentType[idx].isDefaulted) elif currentValue is noValue: raise error.PyAsn1Error('Component type not defined') elif not isinstance(value, base.Asn1Item): if componentTypeLen: subComponentType = componentType.getTypeByPosition(idx) if isinstance(subComponentType, base.SimpleAsn1Type): value = subComponentType.clone(value=value) else: raise error.PyAsn1Error('%s can cast only scalar values' % componentType.__class__.__name__) elif currentValue is not noValue and isinstance(currentValue, base.SimpleAsn1Type): value = currentValue.clone(value=value) else: raise error.PyAsn1Error('%s undefined component type' % componentType.__class__.__name__) elif ((verifyConstraints or matchTags or matchConstraints) and componentTypeLen): subComponentType = componentType.getTypeByPosition(idx) if subComponentType is not noValue: subtypeChecker = (self.strictConstraints and subComponentType.isSameTypeWith or subComponentType.isSuperTypeOf) if not subtypeChecker(value, verifyConstraints and matchTags, verifyConstraints and matchConstraints): if not componentType[idx].openType: raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, componentType)) if componentTypeLen or idx in self._dynamicNames: componentValues[idx] = value elif len(componentValues) == idx: componentValues.append(value) self._dynamicNames.addField(idx) else: raise error.PyAsn1Error('Component index out of range') self._componentValues = componentValues return self @property def isValue(self): """Indicate that |ASN.1| object represents ASN.1 value. If *isValue* is :obj:`False` then this object represents just ASN.1 schema. If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, this object can also be used like a Python built-in object (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). Returns ------- : :class:`bool` :obj:`False` if object represents just ASN.1 schema. :obj:`True` if object represents ASN.1 schema and can be used as a normal value. Note ---- There is an important distinction between PyASN1 schema and value objects. The PyASN1 schema objects can only participate in ASN.1 schema-related operations (e.g. defining or testing the structure of the data). Most obvious uses of ASN.1 schema is to guide serialisation codecs whilst encoding/decoding serialised ASN.1 contents. The PyASN1 value objects can **additionally** participate in many operations involving regular Python objects (e.g. arithmetic, comprehension etc). It is sufficient for |ASN.1| objects to have all non-optional and non-defaulted components being value objects to be considered as a value objects as a whole. In other words, even having one or more optional components not turned into value objects, |ASN.1| object is still considered as a value object. Defaulted components are normally value objects by default. """ if self._componentValues is noValue: return False componentType = self.componentType if componentType: for idx, subComponentType in enumerate(componentType.namedTypes): if subComponentType.isDefaulted or subComponentType.isOptional: continue if not self._componentValues: return False componentValue = self._componentValues[idx] if componentValue is noValue or not componentValue.isValue: return False else: for componentValue in self._componentValues: if componentValue is noValue or not componentValue.isValue: return False return True @property def isInconsistent(self): """Run necessary checks to ensure |ASN.1| object consistency. Default action is to verify |ASN.1| object against constraints imposed by `subtypeSpec`. Raises ------ :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found """ if self.componentType is noValue or not self.subtypeSpec: return False if self._componentValues is noValue: return True mapping = {} for idx, value in enumerate(self._componentValues): # Absent fields are not in the mapping if value is noValue: continue name = self.componentType.getNameByPosition(idx) mapping[name] = value try: # Represent Sequence/Set as a bare dict to constraints chain self.subtypeSpec(mapping) except error.PyAsn1Error as exc: return exc return False def prettyPrint(self, scope=0): """Return an object representation string. Returns ------- : :class:`str` Human-friendly object representation. """ scope += 1 representation = self.__class__.__name__ + ':\n' for idx, componentValue in enumerate(self._componentValues): if componentValue is not noValue and componentValue.isValue: representation += ' ' * scope if self.componentType: representation += self.componentType.getNameByPosition(idx) else: representation += self._dynamicNames.getNameByPosition(idx) representation = '%s=%s\n' % ( representation, componentValue.prettyPrint(scope) ) return representation def prettyPrintType(self, scope=0): scope += 1 representation = '%s -> %s {\n' % (self.tagSet, self.__class__.__name__) for idx, componentType in enumerate(self.componentType.values() or self._componentValues): representation += ' ' * scope if self.componentType: representation += '"%s"' % self.componentType.getNameByPosition(idx) else: representation += '"%s"' % self._dynamicNames.getNameByPosition(idx) representation = '%s = %s\n' % ( representation, componentType.prettyPrintType(scope) ) return representation + '\n' + ' ' * (scope - 1) + '}' # backward compatibility def setDefaultComponents(self): return self def getComponentType(self): if self._componentTypeLen: return self.componentType def getNameByPosition(self, idx): if self._componentTypeLen: return self.componentType[idx].name class Sequence(SequenceAndSetBase): __doc__ = SequenceAndSetBase.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) ) #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) #: object imposing size constraint on |ASN.1| objects componentType = namedtype.NamedTypes() # Disambiguation ASN.1 types identification typeId = SequenceAndSetBase.getTypeId() # backward compatibility def getComponentTagMapNearPosition(self, idx): if self.componentType: return self.componentType.getTagMapNearPosition(idx) def getComponentPositionNearType(self, tagSet, idx): if self.componentType: return self.componentType.getPositionNearType(tagSet, idx) else: return idx class Set(SequenceAndSetBase): __doc__ = SequenceAndSetBase.__doc__ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) ) #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) #: object representing ASN.1 type allowed within |ASN.1| type componentType = namedtype.NamedTypes() #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Disambiguation ASN.1 types identification typeId = SequenceAndSetBase.getTypeId() def getComponent(self, innerFlag=False): return self def getComponentByType(self, tagSet, default=noValue, instantiate=True, innerFlag=False): """Returns |ASN.1| type component by ASN.1 tag. Parameters ---------- tagSet : :py:class:`~pyasn1.type.tag.TagSet` Object representing ASN.1 tags to identify one of |ASN.1| object component Keyword Args ------------ default: :class:`object` If set and requested component is a schema object, return the `default` object instead of the requested component. instantiate: :class:`bool` If :obj:`True` (default), inner component will be automatically instantiated. If :obj:`False` either existing component or the :class:`noValue` object will be returned. Returns ------- : :py:class:`~pyasn1.type.base.PyAsn1Item` a pyasn1 object """ componentValue = self.getComponentByPosition( self.componentType.getPositionByType(tagSet), default=default, instantiate=instantiate ) if innerFlag and isinstance(componentValue, Set): # get inner component by inner tagSet return componentValue.getComponent(innerFlag=True) else: # get outer component by inner tagSet return componentValue def setComponentByType(self, tagSet, value=noValue, verifyConstraints=True, matchTags=True, matchConstraints=True, innerFlag=False): """Assign |ASN.1| type component by ASN.1 tag. Parameters ---------- tagSet : :py:class:`~pyasn1.type.tag.TagSet` Object representing ASN.1 tags to identify one of |ASN.1| object component Keyword Args ------------ value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A Python value to initialize |ASN.1| component with (if *componentType* is set) or ASN.1 value object to assign to |ASN.1| component. If `value` is not given, schema object will be set as a component. verifyConstraints : :class:`bool` If :obj:`False`, skip constraints validation matchTags: :class:`bool` If :obj:`False`, skip component tags matching matchConstraints: :class:`bool` If :obj:`False`, skip component constraints matching innerFlag: :class:`bool` If :obj:`True`, search for matching *tagSet* recursively. Returns ------- self """ idx = self.componentType.getPositionByType(tagSet) if innerFlag: # set inner component by inner tagSet componentType = self.componentType.getTypeByPosition(idx) if componentType.tagSet: return self.setComponentByPosition( idx, value, verifyConstraints, matchTags, matchConstraints ) else: componentType = self.getComponentByPosition(idx) return componentType.setComponentByType( tagSet, value, verifyConstraints, matchTags, matchConstraints, innerFlag=innerFlag ) else: # set outer component by inner tagSet return self.setComponentByPosition( idx, value, verifyConstraints, matchTags, matchConstraints ) @property def componentTagMap(self): if self.componentType: return self.componentType.tagMapUnique class Choice(Set): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.ConstructedAsn1Type`, its objects are mutable and duck-type Python :class:`list` objects. Keyword Args ------------ componentType: :py:class:`~pyasn1.type.namedtype.NamedType` Object holding named ASN.1 types allowed within this collection tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type can only occur on explicit `.isInconsistent` call. Examples -------- .. code-block:: python class Afters(Choice): ''' ASN.1 specification: Afters ::= CHOICE { cheese [0] IA5String, dessert [1] IA5String } ''' componentType = NamedTypes( NamedType('cheese', IA5String().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 0) ), NamedType('dessert', IA5String().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 1) ) ) afters = Afters() afters['cheese'] = 'Mascarpone' """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.TagSet() # untagged #: Default collection of ASN.1 types of component (e.g. :py:class:`~pyasn1.type.namedtype.NamedType`) #: object representing ASN.1 type allowed within |ASN.1| type componentType = namedtype.NamedTypes() #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection( constraint.ValueSizeConstraint(1, 1) ) # Disambiguation ASN.1 types identification typeId = Set.getTypeId() _currentIdx = None def __eq__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] == other return NotImplemented def __ne__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] != other return NotImplemented def __lt__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] < other return NotImplemented def __le__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] <= other return NotImplemented def __gt__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] > other return NotImplemented def __ge__(self, other): if self._componentValues: return self._componentValues[self._currentIdx] >= other return NotImplemented def __bool__(self): return bool(self._componentValues) def __len__(self): return self._currentIdx is not None and 1 or 0 def __contains__(self, key): if self._currentIdx is None: return False return key == self.componentType[self._currentIdx].getName() def __iter__(self): if self._currentIdx is None: raise StopIteration yield self.componentType[self._currentIdx].getName() # Python dict protocol def values(self): if self._currentIdx is not None: yield self._componentValues[self._currentIdx] def keys(self): if self._currentIdx is not None: yield self.componentType[self._currentIdx].getName() def items(self): if self._currentIdx is not None: yield self.componentType[self._currentIdx].getName(), self[self._currentIdx] def checkConsistency(self): if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') def _cloneComponentValues(self, myClone, cloneValueFlag): try: component = self.getComponent() except error.PyAsn1Error: pass else: if isinstance(component, Choice): tagSet = component.effectiveTagSet else: tagSet = component.tagSet if isinstance(component, base.ConstructedAsn1Type): myClone.setComponentByType( tagSet, component.clone(cloneValueFlag=cloneValueFlag) ) else: myClone.setComponentByType(tagSet, component.clone()) def getComponentByPosition(self, idx, default=noValue, instantiate=True): __doc__ = Set.__doc__ if self._currentIdx is None or self._currentIdx != idx: return Set.getComponentByPosition(self, idx, default=default, instantiate=instantiate) return self._componentValues[idx] def setComponentByPosition(self, idx, value=noValue, verifyConstraints=True, matchTags=True, matchConstraints=True): """Assign |ASN.1| type component by position. Equivalent to Python sequence item assignment operation (e.g. `[]`). Parameters ---------- idx: :class:`int` Component index (zero-based). Must either refer to existing component or to N+1 component. In the latter case a new component type gets instantiated (if *componentType* is set, or given ASN.1 object is taken otherwise) and appended to the |ASN.1| sequence. Keyword Args ------------ value: :class:`object` or :py:class:`~pyasn1.type.base.PyAsn1Item` derivative A Python value to initialize |ASN.1| component with (if *componentType* is set) or ASN.1 value object to assign to |ASN.1| component. Once a new value is set to *idx* component, previous value is dropped. If `value` is not given, schema object will be set as a component. verifyConstraints : :class:`bool` If :obj:`False`, skip constraints validation matchTags: :class:`bool` If :obj:`False`, skip component tags matching matchConstraints: :class:`bool` If :obj:`False`, skip component constraints matching Returns ------- self """ oldIdx = self._currentIdx Set.setComponentByPosition(self, idx, value, verifyConstraints, matchTags, matchConstraints) self._currentIdx = idx if oldIdx is not None and oldIdx != idx: self._componentValues[oldIdx] = noValue return self @property def effectiveTagSet(self): """Return a :class:`~pyasn1.type.tag.TagSet` object of the currently initialized component or self (if |ASN.1| is tagged).""" if self.tagSet: return self.tagSet else: component = self.getComponent() return component.effectiveTagSet @property def tagMap(self): """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects contained within callee. """ if self.tagSet: return Set.tagMap.fget(self) else: return self.componentType.tagMapUnique def getComponent(self, innerFlag=False): """Return currently assigned component of the |ASN.1| object. Returns ------- : :py:class:`~pyasn1.type.base.PyAsn1Item` a PyASN1 object """ if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') else: c = self._componentValues[self._currentIdx] if innerFlag and isinstance(c, Choice): return c.getComponent(innerFlag) else: return c def getName(self, innerFlag=False): """Return the name of currently assigned component of the |ASN.1| object. Returns ------- : :py:class:`str` |ASN.1| component name """ if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') else: if innerFlag: c = self._componentValues[self._currentIdx] if isinstance(c, Choice): return c.getName(innerFlag) return self.componentType.getNameByPosition(self._currentIdx) @property def isValue(self): """Indicate that |ASN.1| object represents ASN.1 value. If *isValue* is :obj:`False` then this object represents just ASN.1 schema. If *isValue* is :obj:`True` then, in addition to its ASN.1 schema features, this object can also be used like a Python built-in object (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). Returns ------- : :class:`bool` :obj:`False` if object represents just ASN.1 schema. :obj:`True` if object represents ASN.1 schema and can be used as a normal value. Note ---- There is an important distinction between PyASN1 schema and value objects. The PyASN1 schema objects can only participate in ASN.1 schema-related operations (e.g. defining or testing the structure of the data). Most obvious uses of ASN.1 schema is to guide serialisation codecs whilst encoding/decoding serialised ASN.1 contents. The PyASN1 value objects can **additionally** participate in many operations involving regular Python objects (e.g. arithmetic, comprehension etc). """ if self._currentIdx is None: return False componentValue = self._componentValues[self._currentIdx] return componentValue is not noValue and componentValue.isValue def clear(self): self._currentIdx = None return Set.clear(self) # compatibility stubs def getMinTagSet(self): return self.minTagSet class Any(OctetString): """Create |ASN.1| schema or value object. |ASN.1| class is based on :class:`~pyasn1.type.base.SimpleAsn1Type`, its objects are immutable and duck-type :class:`bytes`. When used in Unicode context, |ASN.1| type assumes "|encoding|" serialisation. Keyword Args ------------ value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object :class:`bytes`, alternatively :class:`str` representing character string to be serialised into octets (note `encoding` parameter) or |ASN.1| object. If `value` is not given, schema object will be created. tagSet: :py:class:`~pyasn1.type.tag.TagSet` Object representing non-default ASN.1 tag(s) subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` Object representing non-default ASN.1 subtype constraint(s). Constraints verification for |ASN.1| type occurs automatically on object instantiation. encoding: :py:class:`str` Unicode codec ID to encode/decode :class:`str` the payload when |ASN.1| object is used in text string context. binValue: :py:class:`str` Binary string initializer to use instead of the *value*. Example: '10110011'. hexValue: :py:class:`str` Hexadecimal string initializer to use instead of the *value*. Example: 'DEADBEEF'. Raises ------ ~pyasn1.error.ValueConstraintError, ~pyasn1.error.PyAsn1Error On constraint violation or bad initializer. Examples -------- .. code-block:: python class Error(Sequence): ''' ASN.1 specification: Error ::= SEQUENCE { code INTEGER, parameter ANY DEFINED BY code -- Either INTEGER or REAL } ''' componentType=NamedTypes( NamedType('code', Integer()), NamedType('parameter', Any(), openType=OpenType('code', {1: Integer(), 2: Real()})) ) error = Error() error['code'] = 1 error['parameter'] = Integer(1234) """ #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.tag.TagSet` object representing ASN.1 tag(s) #: associated with |ASN.1| type. tagSet = tag.TagSet() # untagged #: Set (on class, not on instance) or return a #: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection` object #: imposing constraints on |ASN.1| type initialization values. subtypeSpec = constraint.ConstraintsIntersection() # Disambiguation ASN.1 types identification typeId = OctetString.getTypeId() @property def tagMap(self): """"Return a :class:`~pyasn1.type.tagmap.TagMap` object mapping ASN.1 tags to ASN.1 objects contained within callee. """ try: return self._tagMap except AttributeError: self._tagMap = tagmap.TagMap( {self.tagSet: self}, {eoo.endOfOctets.tagSet: eoo.endOfOctets}, self ) return self._tagMap # XXX # coercion rules? ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyasn1/type/useful.py0000644000175000017500000001224414525242621017260 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import datetime from pyasn1 import error from pyasn1.type import char from pyasn1.type import tag from pyasn1.type import univ __all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime'] NoValue = univ.NoValue noValue = univ.noValue class ObjectDescriptor(char.GraphicString): __doc__ = char.GraphicString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.GraphicString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 7) ) # Optimization for faster codec lookup typeId = char.GraphicString.getTypeId() class TimeMixIn(object): _yearsDigits = 4 _hasSubsecond = False _optionalMinutes = False _shortTZ = False class FixedOffset(datetime.tzinfo): """Fixed offset in minutes east from UTC.""" # defaulted arguments required # https: // docs.python.org / 2.3 / lib / datetime - tzinfo.html def __init__(self, offset=0, name='UTC'): self.__offset = datetime.timedelta(minutes=offset) self.__name = name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return datetime.timedelta(0) UTC = FixedOffset() @property def asDateTime(self): """Create :py:class:`datetime.datetime` object from a |ASN.1| object. Returns ------- : new instance of :py:class:`datetime.datetime` object """ text = str(self) if text.endswith('Z'): tzinfo = TimeMixIn.UTC text = text[:-1] elif '-' in text or '+' in text: if '+' in text: text, plusminus, tz = text.partition('+') else: text, plusminus, tz = text.partition('-') if self._shortTZ and len(tz) == 2: tz += '00' if len(tz) != 4: raise error.PyAsn1Error('malformed time zone offset %s' % tz) try: minutes = int(tz[:2]) * 60 + int(tz[2:]) if plusminus == '-': minutes *= -1 except ValueError: raise error.PyAsn1Error('unknown time specification %s' % self) tzinfo = TimeMixIn.FixedOffset(minutes, '?') else: tzinfo = None if '.' in text or ',' in text: if '.' in text: text, _, ms = text.partition('.') else: text, _, ms = text.partition(',') try: ms = int(ms) * 1000 except ValueError: raise error.PyAsn1Error('bad sub-second time specification %s' % self) else: ms = 0 if self._optionalMinutes and len(text) - self._yearsDigits == 6: text += '0000' elif len(text) - self._yearsDigits == 8: text += '00' try: dt = datetime.datetime.strptime(text, self._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') except ValueError: raise error.PyAsn1Error('malformed datetime format %s' % self) return dt.replace(microsecond=ms, tzinfo=tzinfo) @classmethod def fromDateTime(cls, dt): """Create |ASN.1| object from a :py:class:`datetime.datetime` object. Parameters ---------- dt: :py:class:`datetime.datetime` object The `datetime.datetime` object to initialize the |ASN.1| object from Returns ------- : new instance of |ASN.1| value """ text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S') if cls._hasSubsecond: text += '.%d' % (dt.microsecond // 1000) if dt.utcoffset(): seconds = dt.utcoffset().seconds if seconds < 0: text += '-' else: text += '+' text += '%.2d%.2d' % (seconds // 3600, seconds % 3600) else: text += 'Z' return cls(text) class GeneralizedTime(char.VisibleString, TimeMixIn): __doc__ = char.VisibleString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.VisibleString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 24) ) # Optimization for faster codec lookup typeId = char.VideotexString.getTypeId() _yearsDigits = 4 _hasSubsecond = True _optionalMinutes = True _shortTZ = True class UTCTime(char.VisibleString, TimeMixIn): __doc__ = char.VisibleString.__doc__ #: Default :py:class:`~pyasn1.type.tag.TagSet` object for |ASN.1| objects tagSet = char.VisibleString.tagSet.tagImplicitly( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 23) ) # Optimization for faster codec lookup typeId = char.VideotexString.getTypeId() _yearsDigits = 2 _hasSubsecond = False _optionalMinutes = False _shortTZ = False ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2954316 pyasn1-0.6.1/pyasn1.egg-info/0000755000175000017500000000000014670145404016113 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726008068.0 pyasn1-0.6.1/pyasn1.egg-info/PKG-INFO0000644000175000017500000002027714670145404017220 0ustar00spichugispichugiMetadata-Version: 2.1 Name: pyasn1 Version: 0.6.1 Summary: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) Home-page: https://github.com/pyasn1/pyasn1 Author: Ilya Etingof Author-email: etingof@gmail.com Maintainer: pyasn1 maintenance organization Maintainer-email: Christian Heimes License: BSD-2-Clause Project-URL: Documentation, https://pyasn1.readthedocs.io Project-URL: Source, https://github.com/pyasn1/pyasn1 Project-URL: Issues, https://github.com/pyasn1/pyasn1/issues Project-URL: Changelog, https://pyasn1.readthedocs.io/en/latest/changelog.html Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Education Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: Intended Audience :: Telecommunications Industry Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Communications Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.8 Description-Content-Type: text/markdown License-File: LICENSE.rst ASN.1 library for Python ------------------------ [![PyPI](https://img.shields.io/pypi/v/pyasn1.svg?maxAge=2592000)](https://pypi.org/project/pyasn1) [![Python Versions](https://img.shields.io/pypi/pyversions/pyasn1.svg)](https://pypi.org/project/pyasn1/) [![Build status](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml/badge.svg)](https://github.com/pyasn1/pyasn1/actions/workflows/main.yml) [![Coverage Status](https://img.shields.io/codecov/c/github/pyasn1/pyasn1.svg)](https://codecov.io/github/pyasn1/pyasn1) [![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/pyasn1/pyasn1/master/LICENSE.txt) This is a free and open source implementation of ASN.1 types and codecs as a Python package. It has been first written to support particular protocol (SNMP) but then generalized to be suitable for a wide range of protocols based on [ASN.1 specification](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.208-198811-W!!PDF-E&type=items). **NOTE:** The package is now maintained by *Christian Heimes* and *Simon Pichugin* in project https://github.com/pyasn1/pyasn1. Features -------- * Generic implementation of ASN.1 types (X.208) * Standards compliant BER/CER/DER codecs * Can operate on streams of serialized data * Dumps/loads ASN.1 structures from Python types * 100% Python, works with Python 3.8+ * MT-safe * Contributed ASN.1 compiler [Asn1ate](https://github.com/kimgr/asn1ate) Why using pyasn1 ---------------- ASN.1 solves the data serialisation problem. This solution was designed long ago by the wise Ancients. Back then, they did not have the luxury of wasting bits. That is why ASN.1 is designed to serialise data structures of unbounded complexity into something compact and efficient when it comes to processing the data. That probably explains why many network protocols and file formats still rely on the 30+ years old technology. Including a number of high-profile Internet protocols and file formats. Quite a number of books cover the topic of ASN.1. [Communication between heterogeneous systems](http://www.oss.com/asn1/dubuisson.html) by Olivier Dubuisson is one of those high quality books freely available on the Internet. The pyasn1 package is designed to help Python programmers tackling network protocols and file formats at the comfort of their Python prompt. The tool struggles to capture all aspects of a rather complicated ASN.1 system and to represent it on the Python terms. How to use pyasn1 ----------------- With pyasn1 you can build Python objects from ASN.1 data structures. For example, the following ASN.1 data structure: ```bash Record ::= SEQUENCE { id INTEGER, room [0] INTEGER OPTIONAL, house [1] INTEGER DEFAULT 0 } ``` Could be expressed in pyasn1 like this: ```python class Record(Sequence): componentType = NamedTypes( NamedType('id', Integer()), OptionalNamedType( 'room', Integer().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 0) ) ), DefaultedNamedType( 'house', Integer(0).subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 1) ) ) ) ``` It is in the spirit of ASN.1 to take abstract data description and turn it into a programming language specific form. Once you have your ASN.1 data structure expressed in Python, you can use it along the lines of similar Python type (e.g. ASN.1 `SET` is similar to Python `dict`, `SET OF` to `list`): ```python >>> record = Record() >>> record['id'] = 123 >>> record['room'] = 321 >>> str(record) Record: id=123 room=321 >>> ``` Part of the power of ASN.1 comes from its serialisation features. You can serialise your data structure and send it over the network. ```python >>> from pyasn1.codec.der.encoder import encode >>> substrate = encode(record) >>> hexdump(substrate) 00000: 30 07 02 01 7B 80 02 01 41 ``` Conversely, you can turn serialised ASN.1 content, as received from network or read from a file, into a Python object which you can introspect, modify, encode and send back. ```python >>> from pyasn1.codec.der.decoder import decode >>> received_record, rest_of_substrate = decode(substrate, asn1Spec=Record()) >>> >>> for field in received_record: >>> print('{} is {}'.format(field, received_record[field])) id is 123 room is 321 house is 0 >>> >>> record == received_record True >>> received_record.update(room=123) >>> substrate = encode(received_record) >>> hexdump(substrate) 00000: 30 06 02 01 7B 80 01 7B ``` The pyasn1 classes struggle to emulate their Python prototypes (e.g. int, list, dict etc.). But ASN.1 types exhibit more complicated behaviour. To make life easier for a Pythonista, they can turn their pyasn1 classes into Python built-ins: ```python >>> from pyasn1.codec.native.encoder import encode >>> encode(record) {'id': 123, 'room': 321, 'house': 0} ``` Or vice-versa -- you can initialize an ASN.1 structure from a tree of Python objects: ```python >>> from pyasn1.codec.native.decoder import decode >>> record = decode({'id': 123, 'room': 321, 'house': 0}, asn1Spec=Record()) >>> str(record) Record: id=123 room=321 >>> ``` With ASN.1 design, serialisation codecs are decoupled from data objects, so you could turn every single ASN.1 object into many different serialised forms. As of this moment, pyasn1 supports BER, DER, CER and Python built-ins codecs. The extremely compact PER encoding is expected to be introduced in the upcoming pyasn1 release. More information on pyasn1 APIs can be found in the [documentation](https://pyasn1.readthedocs.io/en/latest/pyasn1/contents.html), compiled ASN.1 modules for different protocols and file formats could be found in the pyasn1-modules [repo](https://github.com/pyasn1/pyasn1-modules). How to get pyasn1 ----------------- The pyasn1 package is distributed under terms and conditions of 2-clause BSD [license](https://pyasn1.readthedocs.io/en/latest/license.html). Source code is freely available as a GitHub [repo](https://github.com/pyasn1/pyasn1). You could `pip install pyasn1` or download it from [PyPI](https://pypi.org/project/pyasn1). If something does not work as expected, [open an issue](https://github.com/epyasn1/pyasn1/issues) at GitHub or post your question [on Stack Overflow](https://stackoverflow.com/questions/ask) or try browsing pyasn1 [mailing list archives](https://sourceforge.net/p/pyasn1/mailman/pyasn1-users/). Copyright (c) 2005-2020, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726008068.0 pyasn1-0.6.1/pyasn1.egg-info/SOURCES.txt0000644000175000017500000001220414670145404017776 0ustar00spichugispichugiCHANGES.rst LICENSE.rst MANIFEST.in README.md TODO.rst pyproject.toml setup.cfg setup.py docs/Makefile docs/source/changelog.rst docs/source/conf.py docs/source/contents.rst docs/source/download.rst docs/source/example-use-case.rst docs/source/index.rst docs/source/license.rst docs/source/.static/logo.svg docs/source/pyasn1/contents.rst docs/source/pyasn1/codec/ber/contents.rst docs/source/pyasn1/codec/cer/contents.rst docs/source/pyasn1/codec/der/contents.rst docs/source/pyasn1/codec/native/contents.rst docs/source/pyasn1/error/contents.rst docs/source/pyasn1/type/base/asn1type.rst docs/source/pyasn1/type/base/constructedasn1type.rst docs/source/pyasn1/type/base/contents.rst docs/source/pyasn1/type/base/novalue.rst docs/source/pyasn1/type/base/simpleasn1type.rst docs/source/pyasn1/type/char/bmpstring.rst docs/source/pyasn1/type/char/contents.rst docs/source/pyasn1/type/char/generalstring.rst docs/source/pyasn1/type/char/graphicstring.rst docs/source/pyasn1/type/char/ia5string.rst docs/source/pyasn1/type/char/iso646string.rst docs/source/pyasn1/type/char/numericstring.rst docs/source/pyasn1/type/char/printablestring.rst docs/source/pyasn1/type/char/t61string.rst docs/source/pyasn1/type/char/teletexstring.rst docs/source/pyasn1/type/char/universalstring.rst docs/source/pyasn1/type/char/utf8string.rst docs/source/pyasn1/type/char/videotexstring.rst docs/source/pyasn1/type/char/visiblestring.rst docs/source/pyasn1/type/constraint/constraintsexclusion.rst docs/source/pyasn1/type/constraint/constraintsintersection.rst docs/source/pyasn1/type/constraint/constraintsunion.rst docs/source/pyasn1/type/constraint/containedsubtype.rst docs/source/pyasn1/type/constraint/contents.rst docs/source/pyasn1/type/constraint/permittedalphabet.rst docs/source/pyasn1/type/constraint/singlevalue.rst docs/source/pyasn1/type/constraint/valuerange.rst docs/source/pyasn1/type/constraint/valuesize.rst docs/source/pyasn1/type/constraint/withcomponents.rst docs/source/pyasn1/type/namedtype/contents.rst docs/source/pyasn1/type/namedtype/defaultednamedtype.rst docs/source/pyasn1/type/namedtype/namedtype.rst docs/source/pyasn1/type/namedtype/namedtypes.rst docs/source/pyasn1/type/namedtype/optionalnamedtype.rst docs/source/pyasn1/type/namedval/contents.rst docs/source/pyasn1/type/namedval/namedval.rst docs/source/pyasn1/type/opentype/contents.rst docs/source/pyasn1/type/opentype/opentype.rst docs/source/pyasn1/type/tag/contents.rst docs/source/pyasn1/type/tag/tag.rst docs/source/pyasn1/type/tag/tagmap.rst docs/source/pyasn1/type/tag/tagset.rst docs/source/pyasn1/type/univ/any.rst docs/source/pyasn1/type/univ/bitstring.rst docs/source/pyasn1/type/univ/boolean.rst docs/source/pyasn1/type/univ/choice.rst docs/source/pyasn1/type/univ/contents.rst docs/source/pyasn1/type/univ/enumerated.rst docs/source/pyasn1/type/univ/integer.rst docs/source/pyasn1/type/univ/null.rst docs/source/pyasn1/type/univ/objectidentifier.rst docs/source/pyasn1/type/univ/octetstring.rst docs/source/pyasn1/type/univ/real.rst docs/source/pyasn1/type/univ/sequence.rst docs/source/pyasn1/type/univ/sequenceof.rst docs/source/pyasn1/type/univ/set.rst docs/source/pyasn1/type/univ/setof.rst docs/source/pyasn1/type/useful/contents.rst docs/source/pyasn1/type/useful/generalizedtime.rst docs/source/pyasn1/type/useful/objectdescriptor.rst docs/source/pyasn1/type/useful/utctime.rst pyasn1/__init__.py pyasn1/debug.py pyasn1/error.py pyasn1.egg-info/PKG-INFO pyasn1.egg-info/SOURCES.txt pyasn1.egg-info/dependency_links.txt pyasn1.egg-info/top_level.txt pyasn1.egg-info/zip-safe pyasn1/codec/__init__.py pyasn1/codec/streaming.py pyasn1/codec/ber/__init__.py pyasn1/codec/ber/decoder.py pyasn1/codec/ber/encoder.py pyasn1/codec/ber/eoo.py pyasn1/codec/cer/__init__.py pyasn1/codec/cer/decoder.py pyasn1/codec/cer/encoder.py pyasn1/codec/der/__init__.py pyasn1/codec/der/decoder.py pyasn1/codec/der/encoder.py pyasn1/codec/native/__init__.py pyasn1/codec/native/decoder.py pyasn1/codec/native/encoder.py pyasn1/compat/__init__.py pyasn1/compat/integer.py pyasn1/type/__init__.py pyasn1/type/base.py pyasn1/type/char.py pyasn1/type/constraint.py pyasn1/type/error.py pyasn1/type/namedtype.py pyasn1/type/namedval.py pyasn1/type/opentype.py pyasn1/type/tag.py pyasn1/type/tagmap.py pyasn1/type/univ.py pyasn1/type/useful.py tests/__init__.py tests/__main__.py tests/base.py tests/test_debug.py tests/codec/__init__.py tests/codec/__main__.py tests/codec/test_streaming.py tests/codec/ber/__init__.py tests/codec/ber/__main__.py tests/codec/ber/test_decoder.py tests/codec/ber/test_encoder.py tests/codec/cer/__init__.py tests/codec/cer/__main__.py tests/codec/cer/test_decoder.py tests/codec/cer/test_encoder.py tests/codec/der/__init__.py tests/codec/der/__main__.py tests/codec/der/test_decoder.py tests/codec/der/test_encoder.py tests/codec/native/__init__.py tests/codec/native/__main__.py tests/codec/native/test_decoder.py tests/codec/native/test_encoder.py tests/compat/__init__.py tests/compat/__main__.py tests/type/__init__.py tests/type/__main__.py tests/type/test_char.py tests/type/test_constraint.py tests/type/test_namedtype.py tests/type/test_namedval.py tests/type/test_opentype.py tests/type/test_tag.py tests/type/test_univ.py tests/type/test_useful.py././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726008068.0 pyasn1-0.6.1/pyasn1.egg-info/dependency_links.txt0000644000175000017500000000000114670145404022161 0ustar00spichugispichugi ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726008068.0 pyasn1-0.6.1/pyasn1.egg-info/top_level.txt0000644000175000017500000000000714670145404020642 0ustar00spichugispichugipyasn1 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700088776.0 pyasn1-0.6.1/pyasn1.egg-info/zip-safe0000644000175000017500000000000114525245710017543 0ustar00spichugispichugi ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/pyproject.toml0000644000175000017500000000012714525242621016120 0ustar00spichugispichugi[build-system] requires = [ "setuptools" ] build-backend = "setuptools.build_meta" ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2964318 pyasn1-0.6.1/setup.cfg0000644000175000017500000000345614670145404015037 0ustar00spichugispichugi[metadata] name = pyasn1 version = attr: pyasn1.__version__ description = Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) long_description = file: README.md long_description_content_type = text/markdown license = BSD-2-Clause license_files = LICENSE.rst url = https://github.com/pyasn1/pyasn1 author = Ilya Etingof author_email = etingof@gmail.com maintainer = pyasn1 maintenance organization maintainer_email = Christian Heimes project_urls = Documentation=https://pyasn1.readthedocs.io Source=https://github.com/pyasn1/pyasn1 Issues=https://github.com/pyasn1/pyasn1/issues Changelog=https://pyasn1.readthedocs.io/en/latest/changelog.html platforms = any classifiers = Development Status :: 5 - Production/Stable Environment :: Console Intended Audience :: Developers Intended Audience :: Education Intended Audience :: Information Technology Intended Audience :: System Administrators Intended Audience :: Telecommunications Industry License :: OSI Approved :: BSD License Natural Language :: English Operating System :: OS Independent Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 Programming Language :: Python :: 3.13 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Topic :: Communications Topic :: Software Development :: Libraries :: Python Modules [options] python_requires = >=3.8 zip_safe = True setup_requires = setuptools packages = pyasn1 pyasn1.type pyasn1.compat pyasn1.codec pyasn1.codec.ber pyasn1.codec.cer pyasn1.codec.der pyasn1.codec.native [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/setup.py0000644000175000017500000000034614525242621014721 0ustar00spichugispichugi#!/usr/bin/env python # # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # from setuptools import setup setup() ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2894316 pyasn1-0.6.1/tests/0000755000175000017500000000000014670145404014350 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/__init__.py0000644000175000017500000000007314525242621016457 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/__main__.py0000644000175000017500000000071014525242621016436 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.test_debug.suite', 'tests.type.__main__.suite', 'tests.codec.__main__.suite', 'tests.compat.__main__.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/base.py0000644000175000017500000000061714525242621015636 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest from pyasn1 import debug class BaseTestCase(unittest.TestCase): def setUp(self): debug.setLogger(debug.Debug('all', printer=lambda *x: None)) def tearDown(self): debug.setLogger(None) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2904317 pyasn1-0.6.1/tests/codec/0000755000175000017500000000000014670145404015425 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/__init__.py0000644000175000017500000000007314525242621017534 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/__main__.py0000644000175000017500000000101014525242621017505 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.codec.test_streaming.suite', 'tests.codec.ber.__main__.suite', 'tests.codec.cer.__main__.suite', 'tests.codec.der.__main__.suite', 'tests.codec.native.__main__.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2904317 pyasn1-0.6.1/tests/codec/ber/0000755000175000017500000000000014670145404016175 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/ber/__init__.py0000644000175000017500000000007314525242621020304 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/ber/__main__.py0000644000175000017500000000062614525242621020271 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.codec.ber.test_encoder.suite', 'tests.codec.ber.test_decoder.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/ber/test_decoder.py0000644000175000017500000021761414670137102021222 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import gzip import io import os import sys import tempfile import unittest import zipfile from tests.base import BaseTestCase from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.type import char from pyasn1.codec import streaming from pyasn1.codec.ber import decoder from pyasn1.codec.ber import eoo from pyasn1 import error class LargeTagDecoderTestCase(BaseTestCase): def testLargeTag(self): assert decoder.decode(bytes((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))) == (1, b'') def testLongTag(self): assert decoder.decode(bytes((0x1f, 2, 1, 0)))[0].tagSet == univ.Integer.tagSet def testTagsEquivalence(self): integer = univ.Integer(2).subtype(implicitTag=tag.Tag(tag.tagClassContext, 0, 0)) assert decoder.decode(bytes((0x9f, 0x80, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) == decoder.decode( bytes((0x9f, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) class DecoderCacheTestCase(BaseTestCase): def testCache(self): assert decoder.decode(bytes((0x1f, 2, 1, 0))) == decoder.decode(bytes((0x1f, 2, 1, 0))) class IntegerDecoderTestCase(BaseTestCase): def testPosInt(self): assert decoder.decode(bytes((2, 1, 12))) == (12, b'') def testNegInt(self): assert decoder.decode(bytes((2, 1, 244))) == (-12, b'') def testZero(self): assert decoder.decode(bytes((2, 0))) == (0, b'') def testZeroLong(self): assert decoder.decode(bytes((2, 1, 0))) == (0, b'') def testMinusOne(self): assert decoder.decode(bytes((2, 1, 255))) == (-1, b'') def testPosLong(self): assert decoder.decode( bytes((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) ) == (0xffffffffffffffff, b'') def testNegLong(self): assert decoder.decode( bytes((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) ) == (-0xffffffffffffffff, b'') def testSpec(self): try: decoder.decode( bytes((2, 1, 12)), asn1Spec=univ.Null() ) == (12, b'') except error.PyAsn1Error: pass else: assert 0, 'wrong asn1Spec worked out' assert decoder.decode( bytes((2, 1, 12)), asn1Spec=univ.Integer() ) == (12, b'') def testTagFormat(self): try: decoder.decode(bytes((34, 1, 12))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(bytes((1, 1, 1))) == (1, b'') def testTrueNeg(self): assert decoder.decode(bytes((1, 1, 255))) == (1, b'') def testExtraTrue(self): assert decoder.decode(bytes((1, 1, 1, 0, 120, 50, 50))) == (1, bytes((0, 120, 50, 50))) def testFalse(self): assert decoder.decode(bytes((1, 1, 0))) == (0, b'') def testTagFormat(self): try: decoder.decode(bytes((33, 1, 1))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class BitStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( bytes((3, 3, 1, 169, 138)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), b'') def testIndefMode(self): assert decoder.decode( bytes((3, 3, 1, 169, 138)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), b'') def testDefModeChunked(self): assert decoder.decode( bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), b'') def testIndefModeChunked(self): assert decoder.decode( bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), b'') def testDefModeChunkedSubst(self): assert decoder.decode( bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((3, 2, 0, 169, 3, 2, 1, 138)), b'') def testDefModeChunkedSubstV04(self): assert decoder.decode( bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((3, 2, 0, 169, 3, 2, 1, 138)), b'') def testIndefModeChunkedSubst(self): assert decoder.decode( bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), b'') def testIndefModeChunkedSubstV04(self): assert decoder.decode( bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), b'') def testTypeChecking(self): try: decoder.decode(bytes((35, 4, 2, 2, 42, 42))) except error.PyAsn1Error: pass else: assert 0, 'accepted mis-encoded bit-string constructed out of an integer' class OctetStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) ) == (b'Quick brown fox', b'') def testIndefMode(self): assert decoder.decode( bytes((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) ) == (b'Quick brown fox', b'') def testDefModeChunked(self): assert decoder.decode( bytes( (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) ) == (b'Quick brown fox', b'') def testIndefModeChunked(self): assert decoder.decode( bytes((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)) ) == (b'Quick brown fox', b'') def testDefModeChunkedSubst(self): assert decoder.decode( bytes( (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), b'') def testDefModeChunkedSubstV04(self): assert decoder.decode( bytes( (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), b'') def testIndefModeChunkedSubst(self): assert decoder.decode( bytes((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes( (4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), b'') def testIndefModeChunkedSubstV04(self): assert decoder.decode( bytes((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes( (4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), b'') class ExpTaggedOctetStringDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.o = univ.OctetString( 'Quick brown fox', tagSet=univ.OctetString.tagSet.tagExplicitly( tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5) )) def testDefMode(self): o, r = decoder.decode( bytes((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) ) assert not r assert self.o == o assert self.o.tagSet == o.tagSet assert self.o.isSameTypeWith(o) def testIndefMode(self): o, r = decoder.decode( bytes((101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)) ) assert not r assert self.o == o assert self.o.tagSet == o.tagSet assert self.o.isSameTypeWith(o) def testDefModeChunked(self): o, r = decoder.decode( bytes((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) ) assert not r assert self.o == o assert self.o.tagSet == o.tagSet assert self.o.isSameTypeWith(o) def testIndefModeChunked(self): o, r = decoder.decode( bytes((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) ) assert not r assert self.o == o assert self.o.tagSet == o.tagSet assert self.o.isSameTypeWith(o) def testDefModeSubst(self): assert decoder.decode( bytes((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), b'') def testDefModeSubstV04(self): assert decoder.decode( bytes((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), b'') def testIndefModeSubst(self): assert decoder.decode( bytes(( 101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes( (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), b'') def testIndefModeSubstV04(self): assert decoder.decode( bytes(( 101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes( (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), b'') class NullDecoderTestCase(BaseTestCase): def testNull(self): assert decoder.decode(bytes((5, 0))) == (b'', b'') def testTagFormat(self): try: decoder.decode(bytes((37, 0))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' # Useful analysis of OID encoding issues could be found here: # https://misc.daniel-marschall.de/asn.1/oid_facts.html class ObjectIdentifierDecoderTestCase(BaseTestCase): def testOne(self): assert decoder.decode( bytes((6, 6, 43, 6, 0, 191, 255, 126)) ) == ((1, 3, 6, 0, 0xffffe), b'') def testEdge1(self): assert decoder.decode( bytes((6, 1, 39)) ) == ((0, 39), b'') def testEdge2(self): assert decoder.decode( bytes((6, 1, 79)) ) == ((1, 39), b'') def testEdge3(self): assert decoder.decode( bytes((6, 1, 120)) ) == ((2, 40), b'') def testEdge4(self): assert decoder.decode( bytes((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) ) == ((2, 0xffffffff), b'') def testEdge5(self): assert decoder.decode( bytes((6, 1, 0x7F)) ) == ((2, 47), b'') def testEdge6(self): assert decoder.decode( bytes((6, 2, 0x81, 0x00)) ) == ((2, 48), b'') def testEdge7(self): assert decoder.decode( bytes((6, 3, 0x81, 0x34, 0x03)) ) == ((2, 100, 3), b'') def testEdge8(self): assert decoder.decode( bytes((6, 2, 133, 0)) ) == ((2, 560), b'') def testEdge9(self): assert decoder.decode( bytes((6, 4, 0x88, 0x84, 0x87, 0x02)) ) == ((2, 16843570), b'') def testNonLeading0x80(self): assert decoder.decode( bytes((6, 5, 85, 4, 129, 128, 0)), ) == ((2, 5, 4, 16384), b'') def testLeading0x80Case1(self): try: decoder.decode( bytes((6, 5, 85, 4, 128, 129, 0)) ) except error.PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case2(self): try: decoder.decode( bytes((6, 7, 1, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7F)) ) except error.PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case3(self): try: decoder.decode( bytes((6, 2, 0x80, 1)) ) except error.PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case4(self): try: decoder.decode( bytes((6, 2, 0x80, 0x7F)) ) except error.PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testTagFormat(self): try: decoder.decode(bytes((38, 1, 239))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' def testZeroLength(self): try: decoder.decode(bytes((6, 0, 0))) except error.PyAsn1Error: pass else: assert 0, 'zero length tolerated' def testIndefiniteLength(self): try: decoder.decode(bytes((6, 128, 0))) except error.PyAsn1Error: pass else: assert 0, 'indefinite length tolerated' def testReservedLength(self): try: decoder.decode(bytes((6, 255, 0))) except error.PyAsn1Error: pass else: assert 0, 'reserved length tolerated' def testLarge1(self): assert decoder.decode( bytes((0x06, 0x11, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB7, 0x17)) ) == ((2, 18446744073709551535184467440737095), b'') def testLarge2(self): assert decoder.decode( bytes((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) ) == ((2, 999, 18446744073709551535184467440737095), b'') class RelativeOIDDecoderTestCase(BaseTestCase): def testOne(self): obj, rest = decoder.decode(bytes((13, 1, 39))) assert str(obj) == '39' assert rest == b'' def testTwo(self): assert decoder.decode( bytes((13, 2, 5, 6)) ) == ((5, 6), b'') def testThree(self): assert decoder.decode( bytes((13, 3, 5, 6, 7)) ) == ((5, 6, 7), b'') def testNonLeading0x80(self): assert decoder.decode( bytes((13, 5, 85, 4, 129, 128, 0)), ) == ((85, 4, 16384), b'') def testLeading0x80(self): try: decoder.decode( bytes((13, 5, 85, 4, 128, 129, 0)) ) except error.PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testTagFormat(self): try: decoder.decode(bytes((38, 1, 239))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' def testZeroLength(self): try: decoder.decode(bytes((13, 0, 0))) except error.PyAsn1Error: pass else: assert 0, 'zero length tolerated' def testIndefiniteLength(self): try: decoder.decode(bytes((13, 128, 0))) except error.PyAsn1Error: pass else: assert 0, 'indefinite length tolerated' def testReservedLength(self): try: decoder.decode(bytes((13, 255, 0))) except error.PyAsn1Error: pass else: assert 0, 'reserved length tolerated' def testLarge(self): assert decoder.decode( bytes((0x0D, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) ) == ((1079, 18446744073709551535184467440737095), b'') class RealDecoderTestCase(BaseTestCase): def testChar(self): assert decoder.decode( bytes((9, 7, 3, 49, 50, 51, 69, 49, 49)) ) == (univ.Real((123, 10, 11)), b'') def testBin1(self): # check base = 2 assert decoder.decode( # (0.5, 2, 0) encoded with base = 2 bytes((9, 3, 128, 255, 1)) ) == (univ.Real((1, 2, -1)), b'') def testBin2(self): # check base = 2 and scale factor assert decoder.decode( # (3.25, 2, 0) encoded with base = 8 bytes((9, 3, 148, 255, 13)) ) == (univ.Real((26, 2, -3)), b'') def testBin3(self): # check base = 16 assert decoder.decode( # (0.00390625, 2, 0) encoded with base = 16 bytes((9, 3, 160, 254, 1)) ) == (univ.Real((1, 2, -8)), b'') def testBin4(self): # check exponent = 0 assert decoder.decode( # (1, 2, 0) encoded with base = 2 bytes((9, 3, 128, 0, 1)) ) == (univ.Real((1, 2, 0)), b'') def testBin5(self): # case of 2 octs for exponent and negative exponent assert decoder.decode( # (3, 2, -1020) encoded with base = 16 bytes((9, 4, 161, 255, 1, 3)) ) == (univ.Real((3, 2, -1020)), b'') # TODO: this requires Real type comparison fix # def testBin6(self): # assert decoder.decode( # bytes((9, 5, 162, 0, 255, 255, 1)) # ) == (univ.Real((1, 2, 262140)), b'') # def testBin7(self): # assert decoder.decode( # bytes((9, 7, 227, 4, 1, 35, 69, 103, 1)) # ) == (univ.Real((-1, 2, 76354972)), b'') def testPlusInf(self): assert decoder.decode( bytes((9, 1, 64)) ) == (univ.Real('inf'), b'') def testMinusInf(self): assert decoder.decode( bytes((9, 1, 65)) ) == (univ.Real('-inf'), b'') def testEmpty(self): assert decoder.decode( bytes((9, 0)) ) == (univ.Real(0.0), b'') def testTagFormat(self): try: decoder.decode(bytes((41, 0))) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' def testShortEncoding(self): try: decoder.decode(bytes((9, 1, 131))) except error.PyAsn1Error: pass else: assert 0, 'accepted too-short real' class UniversalStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(bytes((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString('abc'), b'') class BMPStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(bytes((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString('abc'), b'') class UTF8StringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(bytes((12, 3, 97, 98, 99))) == (char.UTF8String('abc'), b'') class SequenceOfDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) def testDefMode(self): assert decoder.decode( bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) == (self.s, b'') def testIndefMode(self): assert decoder.decode( bytes((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) ) == (self.s, b'') def testDefModeChunked(self): assert decoder.decode( bytes((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) ) == (self.s, b'') def testIndefModeChunked(self): assert decoder.decode( bytes((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) ) == (self.s, b'') def testSchemalessDecoder(self): assert decoder.decode( bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SequenceOf() ) == (self.s, b'') class ExpTaggedSequenceOfDecoderTestCase(BaseTestCase): def testWithSchema(self): s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) s2, r = decoder.decode( bytes((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=s ) assert not r assert s2 == [b'quick brown'] assert s.tagSet == s2.tagSet def testWithoutSchema(self): s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) s2, r = decoder.decode( bytes((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) assert not r assert s2 == [b'quick brown'] assert s.tagSet == s2.tagSet class SequenceOfDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) def testDefMode(self): assert decoder.decode( bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testIndefMode(self): assert decoder.decode( bytes((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testDefModeChunked(self): assert decoder.decode( bytes((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testIndefModeChunked(self): assert decoder.decode( bytes((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') class SetOfDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) def testDefMode(self): assert decoder.decode( bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) == (self.s, b'') def testIndefMode(self): assert decoder.decode( bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) ) == (self.s, b'') def testDefModeChunked(self): assert decoder.decode( bytes((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) ) == (self.s, b'') def testIndefModeChunked(self): assert decoder.decode( bytes((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) ) == (self.s, b'') def testSchemalessDecoder(self): assert decoder.decode( bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SetOf() ) == (self.s, b'') class SetOfDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) def testDefMode(self): assert decoder.decode( bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testIndefMode(self): assert decoder.decode( bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testDefModeChunked(self): assert decoder.decode( bytes((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testIndefModeChunked(self): assert decoder.decode( bytes((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') class SequenceDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.NamedType('first-name', univ.OctetString(b'')), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testWithOptionalAndDefaultedDefMode(self): assert decoder.decode( bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) == (self.s, b'') def testWithOptionalAndDefaultedIndefMode(self): assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeChunked(self): assert decoder.decode( bytes( (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) ) == (self.s, b'') def testWithOptionalAndDefaultedIndefModeChunked(self): assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), b'') def testWithOptionalAndDefaultedDefModeSubstV04(self): assert decoder.decode( bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), b'') def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), b'') def testWithOptionalAndDefaultedIndefModeSubstV04(self): assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), b'') def testTagFormat(self): try: decoder.decode( bytes((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class SequenceDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(2, univ.Integer(1)) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert decoder.decode( bytes((48, 2, 5, 0)), asn1Spec=self.s ) == (self.s, b'') def testIndefMode(self): self.__init() assert decoder.decode( bytes((48, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testDefModeChunked(self): self.__init() assert decoder.decode( bytes((48, 2, 5, 0)), asn1Spec=self.s ) == (self.s, b'') def testIndefModeChunked(self): self.__init() assert decoder.decode( bytes((48, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalDefMode(self): self.__initWithOptional() assert decoder.decode( bytes((48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionaIndefMode(self): self.__initWithOptional() assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert decoder.decode( bytes((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert decoder.decode( bytes((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert decoder.decode( bytes((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( bytes((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( bytes((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes( (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) except error.PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 3, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='060127') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1][0] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) except error.PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010c') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1][0] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1][0] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') class SetDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.NamedType('first-name', univ.OctetString(b'')), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testWithOptionalAndDefaultedDefMode(self): assert decoder.decode( bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) == (self.s, b'') def testWithOptionalAndDefaultedIndefMode(self): assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeChunked(self): assert decoder.decode( bytes( (49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) ) == (self.s, b'') def testWithOptionalAndDefaultedIndefModeChunked(self): assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), b'') def testWithOptionalAndDefaultedDefModeSubstV04(self): assert decoder.decode( bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), b'') def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), b'') def testWithOptionalAndDefaultedIndefModeSubstV04(self): assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), b'') def testTagFormat(self): try: decoder.decode( bytes((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) except error.PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class SetDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(2, univ.Integer(1)) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert decoder.decode( bytes((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testIndefMode(self): self.__init() assert decoder.decode( bytes((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testDefModeChunked(self): self.__init() assert decoder.decode( bytes((49, 2, 5, 0)), asn1Spec=self.s ) == (self.s, b'') def testIndefModeChunked(self): self.__init() assert decoder.decode( bytes((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalDefMode(self): self.__initWithOptional() assert decoder.decode( bytes((49, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalIndefMode(self): self.__initWithOptional() assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert decoder.decode( bytes((49, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert decoder.decode( bytes((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert decoder.decode( bytes((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( bytes((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( bytes((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeReordered(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 18, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedIndefModeReordered(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 128, 2, 1, 1, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)), asn1Spec=self.s ) == (self.s, b'') def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, b'') class SequenceOfWithExpTaggedOctetStringDecoder(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf( componentType=univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) ) self.s.setComponentByPosition(0, 'q') self.s2 = univ.SequenceOf() def testDefModeSchema(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeSchema(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testDefModeNoComponent(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s2) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeNoComponent(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s2) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testDefModeSchemaless(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113))) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeSchemaless(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0))) assert not r assert s == self.s assert s.tagSet == self.s.tagSet class SequenceWithExpTaggedOctetStringDecoder(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType( 'x', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) ) ) ) self.s.setComponentByPosition(0, 'q') self.s2 = univ.Sequence() def testDefModeSchema(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeSchema(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testDefModeNoComponent(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113)), asn1Spec=self.s2) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeNoComponent(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0)), asn1Spec=self.s2) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testDefModeSchemaless(self): s, r = decoder.decode(bytes((48, 5, 163, 3, 4, 1, 113))) assert not r assert s == self.s assert s.tagSet == self.s.tagSet def testIndefModeSchemaless(self): s, r = decoder.decode(bytes((48, 128, 163, 128, 4, 1, 113, 0, 0, 0, 0))) assert not r assert s == self.s assert s.tagSet == self.s.tagSet class ChoiceDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.NamedType('number', univ.Integer(0)), namedtype.NamedType('string', univ.OctetString()) ) ) def testBySpec(self): self.s.setComponentByPosition(0, univ.Null(b'')) assert decoder.decode( bytes((5, 0)), asn1Spec=self.s ) == (self.s, b'') def testWithoutSpec(self): self.s.setComponentByPosition(0, univ.Null(b'')) assert decoder.decode(bytes((5, 0))) == (self.s, b'') assert decoder.decode(bytes((5, 0))) == (univ.Null(b''), b'') def testUndefLength(self): self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) assert decoder.decode(bytes((36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)), asn1Spec=self.s) == (self.s, b'') def testExplicitTag(self): s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4)) s.setComponentByPosition(0, univ.Null(b'')) assert decoder.decode(bytes((164, 2, 5, 0)), asn1Spec=s) == (s, b'') def testExplicitTagUndefLength(self): s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4)) s.setComponentByPosition(0, univ.Null(b'')) assert decoder.decode(bytes((164, 128, 5, 0, 0, 0)), asn1Spec=s) == (s, b'') class AnyDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any() def testByUntagged(self): assert decoder.decode( bytes((4, 3, 102, 111, 120)), asn1Spec=self.s ) == (univ.Any('\004\003fox'), b'') def testTaggedEx(self): s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(bytes((164, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, b'') def testTaggedIm(self): s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(bytes((132, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, b'') def testByUntaggedIndefMode(self): assert decoder.decode( bytes((4, 3, 102, 111, 120)), asn1Spec=self.s ) == (univ.Any('\004\003fox'), b'') def testTaggedExIndefMode(self): s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(bytes((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, b'') def testTaggedImIndefMode(self): s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(bytes((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, b'') def testByUntaggedSubst(self): assert decoder.decode( bytes((4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((4, 3, 102, 111, 120)), b'') def testByUntaggedSubstV04(self): assert decoder.decode( bytes((4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((4, 3, 102, 111, 120)), b'') def testTaggedExSubst(self): assert decoder.decode( bytes((164, 5, 4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c, d: streaming.readFromStream(b, c) ) == (bytes((164, 5, 4, 3, 102, 111, 120)), b'') def testTaggedExSubstV04(self): assert decoder.decode( bytes((164, 5, 4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c: (b, b[c:]) ) == (bytes((164, 5, 4, 3, 102, 111, 120)), b'') class EndOfOctetsTestCase(BaseTestCase): def testUnexpectedEoo(self): try: decoder.decode(bytes((0, 0))) except error.PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted at top level' def testExpectedEoo(self): result, remainder = decoder.decode(bytes((0, 0)), allowEoo=True) assert eoo.endOfOctets.isSameTypeWith(result) and result == eoo.endOfOctets and result is eoo.endOfOctets assert remainder == b'' def testDefiniteNoEoo(self): try: decoder.decode(bytes((0x23, 0x02, 0x00, 0x00))) except error.PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted inside definite-length encoding' def testIndefiniteEoo(self): result, remainder = decoder.decode(bytes((0x23, 0x80, 0x00, 0x00))) assert result == () and remainder == b'', 'incorrect decoding of indefinite length end-of-octets' def testNoLongFormEoo(self): try: decoder.decode(bytes((0x23, 0x80, 0x00, 0x81, 0x00))) except error.PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted with invalid long-form length' def testNoConstructedEoo(self): try: decoder.decode(bytes((0x23, 0x80, 0x20, 0x00))) except error.PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted with invalid constructed encoding' def testNoEooData(self): try: decoder.decode(bytes((0x23, 0x80, 0x00, 0x01, 0x00))) except error.PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted with unexpected data' class NonStringDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(b'')), namedtype.NamedType('first-name', univ.OctetString(b'')), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(b'')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) self.substrate = bytes([48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1]) def testOctetString(self): s = list(decoder.StreamingDecoder( univ.OctetString(self.substrate), asn1Spec=self.s)) assert [self.s] == s def testAny(self): s = list(decoder.StreamingDecoder( univ.Any(self.substrate), asn1Spec=self.s)) assert [self.s] == s class ErrorOnDecodingTestCase(BaseTestCase): def testErrorCondition(self): decode = decoder.SingleItemDecoder( tagMap=decoder.TAG_MAP, typeMap=decoder.TYPE_MAP) substrate = bytes((00, 1, 2)) stream = streaming.asSeekableStream(substrate) try: asn1Object = next(decode(stream)) except error.PyAsn1Error: pass else: assert False, 'Unexpected decoder result %r' % (asn1Object,) def testRawDump(self): substrate = bytes((31, 8, 2, 1, 1, 131, 3, 2, 1, 12)) stream = streaming.asSeekableStream(substrate) class SingleItemEncoder(decoder.SingleItemDecoder): defaultErrorState = decoder.stDumpRawValue class StreamingDecoder(decoder.StreamingDecoder): SINGLE_ITEM_DECODER = SingleItemEncoder class OneShotDecoder(decoder.Decoder): STREAMING_DECODER = StreamingDecoder d = OneShotDecoder() asn1Object, rest = d(stream) assert isinstance(asn1Object, univ.Any), ( 'Unexpected raw dump type %r' % (asn1Object,)) assert asn1Object.asNumbers() == (31, 8, 2, 1, 1), ( 'Unexpected raw dump value %r' % (asn1Object,)) assert rest == bytes((131, 3, 2, 1, 12)), ( 'Unexpected rest of substrate after raw dump %r' % rest) class BinaryFileTestCase(BaseTestCase): """Assure that decode works on open binary files.""" def testOneObject(self): _, path = tempfile.mkstemp() try: with open(path, "wb") as out: out.write(bytes((2, 1, 12))) with open(path, "rb") as source: values = list(decoder.StreamingDecoder(source)) assert values == [12] finally: os.remove(path) def testMoreObjects(self): _, path = tempfile.mkstemp() try: with open(path, "wb") as out: out.write(bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0))) with open(path, "rb") as source: values = list(decoder.StreamingDecoder(source)) assert values == [12, (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)] finally: os.remove(path) def testInvalidFileContent(self): _, path = tempfile.mkstemp() try: with open(path, "wb") as out: out.write(bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0, 7))) with open(path, "rb") as source: list(decoder.StreamingDecoder(source)) except error.EndOfStreamError: pass finally: os.remove(path) class BytesIOTestCase(BaseTestCase): def testRead(self): source = bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) stream = io.BytesIO(source) values = list(decoder.StreamingDecoder(stream)) assert values == [12, (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)] class UnicodeTestCase(BaseTestCase): def testFail(self): # This ensures that str objects cannot be parsed. source = bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)).decode("latin-1") try: next(decoder.StreamingDecoder(source)) except error.UnsupportedSubstrateError: pass else: assert False, 'Tolerated parsing broken unicode strings' class RestartableDecoderTestCase(BaseTestCase): class NonBlockingStream(io.BytesIO): block = False def read(self, size=-1): self.block = not self.block if self.block: return # this is what non-blocking streams sometimes do return io.BytesIO.read(self, size) def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) source = bytes( (48, 26, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) self.stream = self.NonBlockingStream(source) def testPartialReadingFromNonBlockingStream(self): iterator = iter(decoder.StreamingDecoder(self.stream, asn1Spec=self.s)) res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' not in res.context res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' not in res.context res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 0 res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 0 res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 0 res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 1 res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 1 res = next(iterator) assert isinstance(res, error.SubstrateUnderrunError) assert 'asn1Object' in res.context assert isinstance(res.context['asn1Object'], univ.SequenceOf) assert res.context['asn1Object'].isValue assert len(res.context['asn1Object']) == 1 res = next(iterator) assert isinstance(res, univ.SequenceOf) assert res.isValue assert len(res) == 2 try: next(iterator) except StopIteration: pass else: assert False, 'End of stream not raised' class CompressedFilesTestCase(BaseTestCase): def testGzip(self): _, path = tempfile.mkstemp(suffix=".gz") try: with gzip.open(path, "wb") as out: out.write(bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0))) with gzip.open(path, "rb") as source: values = list(decoder.StreamingDecoder(source)) assert values == [12, (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)] finally: os.remove(path) def testZipfile(self): # It is a seekable stream. _, path = tempfile.mkstemp(suffix=".zip") try: with zipfile.ZipFile(path, "w") as myzip: myzip.writestr("data", bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0))) with zipfile.ZipFile(path, "r") as myzip: with myzip.open("data", "r") as source: values = list(decoder.StreamingDecoder(source)) assert values == [12, (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)] finally: os.remove(path) def testZipfileMany(self): _, path = tempfile.mkstemp(suffix=".zip") try: with zipfile.ZipFile(path, "w") as myzip: #for i in range(100): myzip.writestr("data", bytes((2, 1, 12, 35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) * 1000) with zipfile.ZipFile(path, "r") as myzip: with myzip.open("data", "r") as source: values = list(decoder.StreamingDecoder(source)) assert values == [12, (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)] * 1000 finally: os.remove(path) class NonStreamingCompatibilityTestCase(BaseTestCase): def setUp(self): from pyasn1 import debug BaseTestCase.setUp(self) debug.setLogger(None) # undo logger setup from BaseTestCase to work around unrelated issue def testPartialDecodeWithCustomSubstrateFun(self): snmp_req_substrate = bytes(( 0x30, 0x22, 0x02, 0x01, 0x01, 0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 0x15, 0x02, 0x04, 0x69, 0x30, 0xdb, 0xeb, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30, 0x07, 0x30, 0x05, 0x06, 0x01, 0x01, 0x05, 0x00)) seq, next_substrate = decoder.decode( snmp_req_substrate, asn1Spec=univ.Sequence(), recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c]) ) assert seq.isSameTypeWith(univ.Sequence) assert next_substrate == snmp_req_substrate[2:] version, next_substrate = decoder.decode( next_substrate, asn1Spec=univ.Integer(), recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c]) ) assert version == 1 def testPartialDecodeWithDefaultSubstrateFun(self): substrate = bytes(( 0x04, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x3c, 0x03, 0x02 )) result, rest = decoder.decode(substrate, recursiveFlag=False) assert result.isSameTypeWith(univ.OctetString) assert rest == substrate[2:] def testPropagateUserException(self): substrate = io.BytesIO(bytes((0x04, 0x00))) def userSubstrateFun(_asn1Object, _substrate, _length, _options): raise TypeError("error inside user function") try: decoder.decode(substrate, asn1Spec=univ.OctetString, substrateFun=userSubstrateFun) except TypeError as exc: assert str(exc) == "error inside user function" else: raise AssertionError("decode() must not hide TypeError from inside user provided callback") suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/ber/test_encoder.py0000644000175000017500000014763514670137102021241 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.type import char from pyasn1.codec.ber import encoder from pyasn1.error import PyAsn1Error class LargeTagEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.o = univ.Integer().subtype( value=1, explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0xdeadbeaf) ) def testEncoder(self): assert encoder.encode(self.o) == bytes((127, 141, 245, 182, 253, 47, 3, 2, 1, 1)) class IntegerEncoderTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(univ.Integer(12)) == bytes((2, 1, 12)) def testNegInt(self): assert encoder.encode(univ.Integer(-12)) == bytes((2, 1, 244)) def testZero(self): assert encoder.encode(univ.Integer(0)) == bytes((2, 1, 0)) def testCompactZero(self): encoder.IntegerEncoder.supportCompactZero = True substrate = encoder.encode(univ.Integer(0)) encoder.IntegerEncoder.supportCompactZero = False assert substrate == bytes((2, 0)) def testMinusOne(self): assert encoder.encode(univ.Integer(-1)) == bytes((2, 1, 255)) def testPosLong(self): assert encoder.encode( univ.Integer(0xffffffffffffffff) ) == bytes((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) def testNegLong(self): assert encoder.encode( univ.Integer(-0xffffffffffffffff) ) == bytes((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) class IntegerEncoderWithSchemaTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(12, asn1Spec=univ.Integer()) == bytes((2, 1, 12)) def testNegInt(self): assert encoder.encode(-12, asn1Spec=univ.Integer()) == bytes((2, 1, 244)) def testZero(self): assert encoder.encode(0, asn1Spec=univ.Integer()) == bytes((2, 1, 0)) def testPosLong(self): assert encoder.encode( 0xffffffffffffffff, asn1Spec=univ.Integer() ) == bytes((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == bytes((1, 1, 1)) def testFalse(self): assert encoder.encode(univ.Boolean(0)) == bytes((1, 1, 0)) class BooleanEncoderWithSchemaTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(True, asn1Spec=univ.Boolean()) == bytes((1, 1, 1)) def testFalse(self): assert encoder.encode(False, asn1Spec=univ.Boolean()) == bytes((1, 1, 0)) class BitStringEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) def testDefMode(self): assert encoder.encode(self.b) == bytes((3, 3, 1, 169, 138)) def testIndefMode(self): assert encoder.encode( self.b, defMode=False ) == bytes((3, 3, 1, 169, 138)) def testDefModeChunked(self): assert encoder.encode( self.b, maxChunkSize=1 ) == bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) def testIndefModeChunked(self): assert encoder.encode( self.b, defMode=False, maxChunkSize=1 ) == bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) def testEmptyValue(self): assert encoder.encode(univ.BitString([])) == bytes((3, 1, 0)) class BitStringEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.b = (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1) self.s = univ.BitString() def testDefMode(self): assert encoder.encode(self.b, asn1Spec=self.s) == bytes((3, 3, 1, 169, 138)) def testIndefMode(self): assert encoder.encode( self.b, asn1Spec=self.s, defMode=False ) == bytes((3, 3, 1, 169, 138)) def testDefModeChunked(self): assert encoder.encode( self.b, asn1Spec=self.s, maxChunkSize=1 ) == bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) def testIndefModeChunked(self): assert encoder.encode( self.b, asn1Spec=self.s, defMode=False, maxChunkSize=1 ) == bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) def testEmptyValue(self): assert encoder.encode([], asn1Spec=self.s) == bytes((3, 1, 0)) class OctetStringEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.o = univ.OctetString('Quick brown fox') def testDefMode(self): assert encoder.encode(self.o) == bytes( (4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testIndefMode(self): assert encoder.encode( self.o, defMode=False ) == bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testDefModeChunked(self): assert encoder.encode( self.o, maxChunkSize=4 ) == bytes((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) def testIndefModeChunked(self): assert encoder.encode( self.o, defMode=False, maxChunkSize=4 ) == bytes((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)) class OctetStringEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.OctetString() self.o = 'Quick brown fox' def testDefMode(self): assert encoder.encode(self.o, asn1Spec=self.s) == bytes( (4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testIndefMode(self): assert encoder.encode( self.o, asn1Spec=self.s, defMode=False ) == bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testDefModeChunked(self): assert encoder.encode( self.o, asn1Spec=self.s, maxChunkSize=4 ) == bytes((36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) def testIndefModeChunked(self): assert encoder.encode( self.o, asn1Spec=self.s, defMode=False, maxChunkSize=4 ) == bytes((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)) class ExpTaggedOctetStringEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.o = univ.OctetString().subtype( value='Quick brown fox', explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5) ) def testDefMode(self): assert encoder.encode(self.o) == bytes( (101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testIndefMode(self): assert encoder.encode( self.o, defMode=False ) == bytes((101, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.o, defMode=True, maxChunkSize=4 ) == bytes((101, 25, 36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)) def testIndefModeChunked(self): assert encoder.encode( self.o, defMode=False, maxChunkSize=4 ) == bytes((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) class NullEncoderTestCase(BaseTestCase): def testNull(self): assert encoder.encode(univ.Null('')) == bytes((5, 0)) class NullEncoderWithSchemaTestCase(BaseTestCase): def testNull(self): assert encoder.encode(None, univ.Null()) == bytes((5, 0)) class ObjectIdentifierEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( univ.ObjectIdentifier((1, 3, 6, 0, 0xffffe)) ) == bytes((6, 6, 43, 6, 0, 191, 255, 126)) def testEdge1(self): assert encoder.encode( univ.ObjectIdentifier((0, 39)) ) == bytes((6, 1, 39)) def testEdge2(self): assert encoder.encode( univ.ObjectIdentifier((1, 39)) ) == bytes((6, 1, 79)) def testEdge3(self): # 01111111 assert encoder.encode( univ.ObjectIdentifier((2, 40)) ) == bytes((6, 1, 120)) def testEdge4(self): # 10010000|10000000|10000000|10000000|01001111 assert encoder.encode( univ.ObjectIdentifier((2, 0xffffffff)) ) == bytes((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) def testEdge5(self): # 01111111 assert encoder.encode( univ.ObjectIdentifier((2, 47)) ) == bytes((6, 1, 0x7F)) def testEdge6(self): # 10000001|00000000 assert encoder.encode( univ.ObjectIdentifier((2, 48)) ) == bytes((6, 2, 0x81, 0x00)) def testEdge7(self): # 10000001|00110100|00000003 assert encoder.encode( univ.ObjectIdentifier((2, 100, 3)) ) == bytes((6, 3, 0x81, 0x34, 0x03)) def testEdge8(self): # 10000101|00000000 assert encoder.encode( univ.ObjectIdentifier((2, 560)) ) == bytes((6, 2, 133, 0)) def testEdge9(self): # 10001000|10000100|10000111|0000010 assert encoder.encode( univ.ObjectIdentifier((2, 16843570)) ) == bytes((6, 4, 0x88, 0x84, 0x87, 0x02)) def testEdgeA(self): assert encoder.encode( univ.ObjectIdentifier((2, 5)) ) == bytes((6, 1, 85)) def testImpossible1(self): try: encoder.encode(univ.ObjectIdentifier((3, 1, 2))) except PyAsn1Error: pass else: assert 0, 'impossible leading arc tolerated' def testImpossible2(self): try: encoder.encode(univ.ObjectIdentifier((0,))) except PyAsn1Error: pass else: assert 0, 'single arc OID tolerated' def testImpossible3(self): try: encoder.encode(univ.ObjectIdentifier((0, 40))) except PyAsn1Error: pass else: assert 0, 'second arc overflow tolerated' def testImpossible4(self): try: encoder.encode(univ.ObjectIdentifier((1, 40))) except PyAsn1Error: pass else: assert 0, 'second arc overflow tolerated' def testLarge1(self): assert encoder.encode( univ.ObjectIdentifier((2, 18446744073709551535184467440737095)) ) == bytes((0x06, 0x11, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB7, 0x17)) def testLarge2(self): assert encoder.encode( univ.ObjectIdentifier((2, 999, 18446744073709551535184467440737095)) ) == bytes((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) class ObjectIdentifierWithSchemaEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( (1, 3, 6, 0, 0xffffe), asn1Spec=univ.ObjectIdentifier() ) == bytes((6, 6, 43, 6, 0, 191, 255, 126)) class RelativeOIDEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( univ.RelativeOID((39,)) ) == bytes((13, 1, 39)) def testTwo(self): assert encoder.encode( univ.RelativeOID((5, 6)) ) == bytes((13, 2, 5, 6)) def testThree(self): assert encoder.encode( univ.RelativeOID((5, 6, 7)) ) == bytes((13, 3, 5, 6, 7)) def testLarge(self): assert encoder.encode( univ.RelativeOID((1079, 18446744073709551535184467440737095)) ) == bytes((0x0D, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) class RelativeOIDWithSchemaEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( (5, 6, 7), asn1Spec=univ.RelativeOID() ) == bytes((13, 3, 5, 6, 7)) class RealEncoderTestCase(BaseTestCase): def testChar(self): assert encoder.encode( univ.Real((123, 10, 11)) ) == bytes((9, 7, 3, 49, 50, 51, 69, 49, 49)) def testBin1(self): assert encoder.encode( # default binEncBase = 2 univ.Real((0.5, 2, 0)) # check encbase = 2 and exponent = -1 ) == bytes((9, 3, 128, 255, 1)) def testBin2(self): r = univ.Real((3.25, 2, 0)) r.binEncBase = 8 # change binEncBase only for this instance of Real assert encoder.encode( r # check encbase = 8 ) == bytes((9, 3, 148, 255, 13)) def testBin3(self): # change binEncBase in the RealEncoder instance => for all further Real binEncBase, encoder.TYPE_MAP[univ.Real.typeId].binEncBase = encoder.TYPE_MAP[univ.Real.typeId].binEncBase, 16 assert encoder.encode( univ.Real((0.00390625, 2, 0)) # check encbase = 16 ) == bytes((9, 3, 160, 254, 1)) encoder.TYPE_MAP[univ.Real.typeId].binEncBase = binEncBase def testBin4(self): # choose binEncBase automatically for all further Real (testBin[4-7]) binEncBase, encoder.TYPE_MAP[univ.Real.typeId].binEncBase = encoder.TYPE_MAP[univ.Real.typeId].binEncBase, None assert encoder.encode( univ.Real((1, 2, 0)) # check exponent = 0 ) == bytes((9, 3, 128, 0, 1)) encoder.TYPE_MAP[univ.Real.typeId].binEncBase = binEncBase def testBin5(self): assert encoder.encode( univ.Real((3, 2, -1020)) # case of 2 octs for exponent and # negative exponent and abs(exponent) is # all 1's and fills the whole octet(s) ) == bytes((9, 4, 129, 252, 4, 3)) def testBin6(self): assert encoder.encode( univ.Real((1, 2, 262140)) # case of 3 octs for exponent and # check that first 9 bits for exponent # are not all 1's ) == bytes((9, 5, 130, 3, 255, 252, 1)) def testBin7(self): assert encoder.encode( univ.Real((-1, 2, 76354972)) # case of >3 octs for exponent and # mantissa < 0 ) == bytes((9, 7, 195, 4, 4, 141, 21, 156, 1)) def testPlusInf(self): assert encoder.encode(univ.Real('inf')) == bytes((9, 1, 64)) def testMinusInf(self): assert encoder.encode(univ.Real('-inf')) == bytes((9, 1, 65)) def testZero(self): assert encoder.encode(univ.Real(0)) == bytes((9, 0)) class RealEncoderWithSchemaTestCase(BaseTestCase): def testChar(self): assert encoder.encode( (123, 10, 11), asn1Spec=univ.Real() ) == bytes((9, 7, 3, 49, 50, 51, 69, 49, 49)) class UniversalStringEncoderTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode(char.UniversalString('abc')) == bytes( (28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' class UniversalStringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( 'abc', asn1Spec=char.UniversalString() ) == bytes((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' class BMPStringEncoderTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode(char.BMPString('abc')) == bytes( (30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class BMPStringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( 'abc', asn1Spec=char.BMPString() ) == bytes((30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class UTF8StringEncoderTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode(char.UTF8String('abc')) == bytes( (12, 3, 97, 98, 99)), 'Incorrect encoding' class UTF8StringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( 'abc', asn1Spec=char.UTF8String() ) == bytes((12, 3, 97, 98, 99)), 'Incorrect encoding' class SequenceOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SequenceOf() s.clear() assert encoder.encode(s) == bytes((48, 0)) def testDefMode(self): s = univ.SequenceOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): s = univ.SequenceOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False ) == bytes((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): s = univ.SequenceOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=True, maxChunkSize=4 ) == bytes((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): s = univ.SequenceOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) self.v = ['quick brown'] def testEmpty(self): assert encoder.encode([], asn1Spec=self.s) == bytes((48, 0)) def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False ) == bytes((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SequenceOfEncoderWithComponentsSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) def __init(self): self.s.clear() self.s.setComponentByPosition(0, 'quick brown') def testDefMode(self): self.__init() assert encoder.encode(self.s) == bytes((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SetOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SetOf() s.clear() assert encoder.encode(s) == bytes((49, 0)) def testDefMode(self): s = univ.SetOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): s = univ.SetOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False ) == bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): s = univ.SetOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=True, maxChunkSize=4 ) == bytes((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): s = univ.SetOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SetOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) self.v = ['quick brown'] def testEmpty(self): s = univ.SetOf() assert encoder.encode([], asn1Spec=self.s) == bytes((49, 0)) def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False ) == bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 ) == bytes( (49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SetOfEncoderWithComponentsSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) def __init(self): self.s.clear() self.s.setComponentByPosition(0, 'quick brown') def testDefMode(self): self.__init() assert encoder.encode(self.s) == bytes((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) class SequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): assert encoder.encode(self.s) == bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testIndefModeChunked(self): assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class SequenceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) self.v = { 'place-holder': None, 'first-name': 'quick brown', 'age': 1 } def testEmpty(self): try: assert encoder.encode({}, asn1Spec=self.s) except PyAsn1Error: pass else: assert False, 'empty bare sequence tolerated' def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == bytes((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testIndefMode(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testIndefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 5, 2, 1, 1, 49, 50) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.OctetString('quick brown') assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50) ) class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50) ) class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any()), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 7, 2, 1, 1, 49, 2, 49, 50) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.OctetString('quick brown')) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50) ) class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50) ) class SequenceEncoderWithComponentsSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, '') def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, '') self.s.setComponentByPosition(1, 'quick brown') def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, '') self.s.setComponentByPosition(2, 1) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert encoder.encode(self.s) == bytes((48, 2, 5, 0)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 5, 0, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 2, 5, 0)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 5, 0, 0, 0)) def testWithOptionalDefMode(self): self.__initWithOptional() assert encoder.encode(self.s) == bytes( (48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes( (48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert encoder.encode(self.s) == bytes((48, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((48, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode(self.s) == bytes( (48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes( (48, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class ExpTaggedSequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('number', univ.Integer()), ) ) s = s.subtype( explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 5) ) s[0] = 12 self.s = s def testDefMode(self): assert encoder.encode(self.s) == bytes((101, 5, 48, 3, 2, 1, 12)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == bytes((101, 128, 48, 128, 2, 1, 12, 0, 0, 0, 0)) class ExpTaggedSequenceComponentEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('number', univ.Boolean().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), ) ) self.s[0] = True def testDefMode(self): assert encoder.encode(self.s) == bytes((48, 5, 160, 3, 1, 1, 1)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == bytes((48, 128, 160, 3, 1, 1, 1, 0, 0, 0, 0)) class SetEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): assert encoder.encode(self.s) == bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testIndefModeChunked(self): assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class SetEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) self.v = { 'place-holder': None, 'first-name': 'quick brown', 'age': 1 } def testEmpty(self): try: assert encoder.encode({}, asn1Spec=self.s) except PyAsn1Error: pass else: assert False, 'empty bare SET tolerated' def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == bytes((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testIndefMode(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False ) == bytes((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testDefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testIndefModeChunked(self): assert encoder.encode( self.v, asn1Spec=self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class SetEncoderWithComponentsSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, '') def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, '') self.s.setComponentByPosition(1, 'quick brown') def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, '') self.s.setComponentByPosition(2, 1) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert encoder.encode(self.s) == bytes((49, 2, 5, 0)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 5, 0, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 2, 5, 0)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 5, 0, 0, 0)) def testWithOptionalDefMode(self): self.__initWithOptional() assert encoder.encode(self.s) == bytes( (49, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 21, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes( (49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert encoder.encode(self.s) == bytes((49, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes((49, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode(self.s) == bytes( (49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=False ) == bytes((49, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == bytes( (49, 24, 5, 0, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 2, 1, 1)) def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == bytes((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) class ChoiceEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.Choice() try: encoder.encode(s) except PyAsn1Error: pass else: assert 0, 'encoded unset choice' def testDefModeOptionOne(self): s = univ.Choice() s.setComponentByPosition(0, univ.Null('')) assert encoder.encode(s) == bytes((5, 0)) def testDefModeOptionTwo(self): s = univ.Choice() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testIndefMode(self): s = univ.Choice() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False ) == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) def testDefModeChunked(self): s = univ.Choice() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=True, maxChunkSize=4 ) == bytes((36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) def testIndefModeChunked(self): s = univ.Choice() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode( s, defMode=False, maxChunkSize=4 ) == bytes((36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0)) class ChoiceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.NamedType('number', univ.Integer(0)), namedtype.NamedType('string', univ.OctetString()) ) ) self.v = { 'place-holder': None } def testFilled(self): assert encoder.encode( self.v, asn1Spec=self.s ) == bytes((5, 0)) class ChoiceEncoderWithComponentsSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.NamedType('number', univ.Integer(0)), namedtype.NamedType('string', univ.OctetString()) ) ) def testEmpty(self): try: encoder.encode(self.s) except PyAsn1Error: pass else: assert 0, 'encoded unset choice' def testFilled(self): self.s.setComponentByPosition(0, univ.Null('')) assert encoder.encode(self.s) == bytes((5, 0)) def testTagged(self): s = self.s.subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4) ) s.setComponentByPosition(0, univ.Null('')) assert encoder.encode(s) == bytes((164, 2, 5, 0)) def testUndefLength(self): self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) assert encoder.encode(self.s, defMode=False, maxChunkSize=3) == bytes( (36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)) def testTaggedUndefLength(self): s = self.s.subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4) ) s.setComponentByPosition(2, univ.OctetString('abcdefgh')) assert encoder.encode(s, defMode=False, maxChunkSize=3) == bytes( (164, 128, 36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0, 0, 0)) class AnyEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) def testUntagged(self): assert encoder.encode(self.s) == bytes((4, 3, 102, 111, 120)) def testTaggedEx(self): s = self.s.subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) ) assert encoder.encode(s) == bytes((164, 5, 4, 3, 102, 111, 120)) def testTaggedIm(self): s = self.s.subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) ) assert encoder.encode(s) == bytes((132, 5, 4, 3, 102, 111, 120)) class AnyEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any() self.v = encoder.encode(univ.OctetString('fox')) def testUntagged(self): assert encoder.encode(self.v, asn1Spec=self.s) == bytes((4, 3, 102, 111, 120)) def testTaggedEx(self): s = self.s.subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) ) assert encoder.encode(self.v, asn1Spec=s) == bytes((164, 5, 4, 3, 102, 111, 120)) def testTaggedIm(self): s = self.s.subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) ) assert encoder.encode(self.v, asn1Spec=s) == bytes((132, 5, 4, 3, 102, 111, 120)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2914317 pyasn1-0.6.1/tests/codec/cer/0000755000175000017500000000000014670145404016176 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/cer/__init__.py0000644000175000017500000000007314525242621020305 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/cer/__main__.py0000644000175000017500000000062614525242621020272 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.codec.cer.test_encoder.suite', 'tests.codec.cer.test_decoder.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/cer/test_decoder.py0000644000175000017500000002704614670137102021221 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.codec.cer import decoder from pyasn1.error import PyAsn1Error class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(bytes((1, 1, 255))) == (1, b'') def testFalse(self): assert decoder.decode(bytes((1, 1, 0))) == (0, b'') def testEmpty(self): try: decoder.decode(bytes((1, 0))) except PyAsn1Error: pass def testOverflow(self): try: decoder.decode(bytes((1, 2, 0, 0))) except PyAsn1Error: pass class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( bytes((3, 3, 6, 170, 128)) ) == (((1, 0) * 5), b'') def testLongMode(self): assert decoder.decode( bytes((3, 127, 6) + (170,) * 125 + (128,)) ) == (((1, 0) * 501), b'') # TODO: test failures on short chunked and long unchunked substrate samples class OctetStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), ) == (b'Quick brown fox', b'') def testLongMode(self): assert decoder.decode( bytes((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) ) == (b'Q' * 1001, b'') # TODO: test failures on short chunked and long unchunked substrate samples class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 128, 6, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) except PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 3, 6, 1, 12, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='06010c') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 163, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 3, 163, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1][0] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 128, 6, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) except PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 3, 49, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010c') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 1, 49, 128, 2, 1, 12, 0, 0, 0, 0)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1][0] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 128, 2, 1, 2, 49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1][0] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/cer/test_encoder.py0000644000175000017500000007414714670137102021237 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.type import useful from pyasn1.codec.cer import encoder from pyasn1.error import PyAsn1Error class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == bytes((1, 1, 255)) def testFalse(self): assert encoder.encode(univ.Boolean(0)) == bytes((1, 1, 0)) class BitStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.BitString((1, 0) * 5) ) == bytes((3, 3, 6, 170, 128)) def testLongMode(self): assert encoder.encode(univ.BitString((1, 0) * 501)) == bytes((3, 127, 6) + (170,) * 125 + (128,)) class OctetStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testLongMode(self): assert encoder.encode( univ.OctetString('Q' * 1001) ) == bytes((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) class GeneralizedTimeEncoderTestCase(BaseTestCase): # def testExtraZeroInSeconds(self): # try: # assert encoder.encode( # useful.GeneralizedTime('20150501120112.10Z') # ) # except PyAsn1Error: # pass # else: # assert 0, 'Meaningless trailing zero in fraction part tolerated' def testLocalTimezone(self): try: assert encoder.encode( useful.GeneralizedTime('20150501120112.1+0200') ) except PyAsn1Error: pass else: assert 0, 'Local timezone tolerated' def testMissingTimezone(self): try: assert encoder.encode( useful.GeneralizedTime('20150501120112.1') ) except PyAsn1Error: pass else: assert 0, 'Missing timezone tolerated' def testDecimalCommaPoint(self): try: assert encoder.encode( useful.GeneralizedTime('20150501120112,1Z') ) except PyAsn1Error: pass else: assert 0, 'Decimal comma tolerated' def testWithSubseconds(self): assert encoder.encode( useful.GeneralizedTime('20170801120112.59Z') ) == bytes((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 53, 57, 90)) def testWithSubsecondsWithZeros(self): assert encoder.encode( useful.GeneralizedTime('20170801120112.099Z') ) == bytes((24, 18, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 90)) def testWithSubsecondsMax(self): assert encoder.encode( useful.GeneralizedTime('20170801120112.999Z') ) == bytes((24, 19, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 46, 57, 57, 57, 90)) def testWithSubsecondsMin(self): assert encoder.encode( useful.GeneralizedTime('20170801120112.000Z') ) == bytes((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) def testWithSubsecondsDanglingDot(self): assert encoder.encode( useful.GeneralizedTime('20170801120112.Z') ) == bytes((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) def testWithSeconds(self): assert encoder.encode( useful.GeneralizedTime('20170801120112Z') ) == bytes((24, 15, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) def testWithMinutes(self): assert encoder.encode( useful.GeneralizedTime('201708011201Z') ) == bytes((24, 13, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 90)) class UTCTimeEncoderTestCase(BaseTestCase): def testFractionOfSecond(self): try: assert encoder.encode( useful.UTCTime('150501120112.10Z') ) except PyAsn1Error: pass else: assert 0, 'Decimal point tolerated' def testMissingTimezone(self): try: assert encoder.encode( useful.UTCTime('150501120112') ) == bytes((23, 13, 49, 53, 48, 53, 48, 49, 49, 50, 48, 49, 49, 50, 90)) except PyAsn1Error: pass else: assert 0, 'Missing timezone tolerated' def testLocalTimezone(self): try: assert encoder.encode( useful.UTCTime('150501120112+0200') ) except PyAsn1Error: pass else: assert 0, 'Local timezone tolerated' def testWithSeconds(self): assert encoder.encode( useful.UTCTime('990801120112Z') ) == bytes((23, 13, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) def testWithMinutes(self): assert encoder.encode( useful.UTCTime('9908011201Z') ) == bytes((23, 11, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 90)) class SequenceOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SequenceOf() s.clear() assert encoder.encode(s) == bytes((48, 128, 0, 0)) def testDefMode1(self): s = univ.SequenceOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('ab')) assert encoder.encode(s) == bytes((48, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testDefMode2(self): s = univ.SequenceOf() s.append(univ.OctetString('ab')) s.append(univ.OctetString('a')) assert encoder.encode(s) == bytes((48, 128, 4, 2, 97, 98, 4, 1, 97, 0, 0)) def testDefMode3(self): s = univ.SequenceOf() s.append(univ.OctetString('b')) s.append(univ.OctetString('a')) assert encoder.encode(s) == bytes((48, 128, 4, 1, 98, 4, 1, 97, 0, 0)) def testDefMode4(self): s = univ.SequenceOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('b')) assert encoder.encode(s) == bytes((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) def testEmpty(self): self.s.clear() assert encoder.encode(self.s) == bytes((48, 128, 0, 0)) def testIndefMode1(self): self.s.clear() self.s.append('a') self.s.append('ab') assert encoder.encode(self.s) == bytes((48, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testIndefMode2(self): self.s.clear() self.s.append('ab') self.s.append('a') assert encoder.encode(self.s) == bytes((48, 128, 4, 2, 97, 98, 4, 1, 97, 0, 0)) def testIndefMode3(self): self.s.clear() self.s.append('b') self.s.append('a') assert encoder.encode(self.s) == bytes((48, 128, 4, 1, 98, 4, 1, 97, 0, 0)) def testIndefMode4(self): self.s.clear() self.s.append('a') self.s.append('b') assert encoder.encode(self.s) == bytes((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) class SetOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SetOf() s.clear() assert encoder.encode(s) == bytes((49, 128, 0, 0)) def testDefMode1(self): s = univ.SetOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('ab')) assert encoder.encode(s) == bytes((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testDefMode2(self): s = univ.SetOf() s.append(univ.OctetString('ab')) s.append(univ.OctetString('a')) assert encoder.encode(s) == bytes((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testDefMode3(self): s = univ.SetOf() s.append(univ.OctetString('b')) s.append(univ.OctetString('a')) assert encoder.encode(s) == bytes((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) def testDefMode4(self): s = univ.SetOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('b')) assert encoder.encode(s) == bytes((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) class SetOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) def testEmpty(self): self.s.clear() assert encoder.encode(self.s) == bytes((49, 128, 0, 0)) def testIndefMode1(self): self.s.clear() self.s.append('a') self.s.append('ab') assert encoder.encode(self.s) == bytes((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testIndefMode2(self): self.s.clear() self.s.append('ab') self.s.append('a') assert encoder.encode(self.s) == bytes((49, 128, 4, 1, 97, 4, 2, 97, 98, 0, 0)) def testIndefMode3(self): self.s.clear() self.s.append('b') self.s.append('a') assert encoder.encode(self.s) == bytes((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) def testIndefMode4(self): self.s.clear() self.s.append('a') self.s.append('b') assert encoder.encode(self.s) == bytes((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) class SetEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testIndefMode(self): assert encoder.encode(self.s) == bytes((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) def testWithOptionalIndefMode(self): assert encoder.encode( self.s ) == bytes((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) def testWithDefaultedIndefMode(self): assert encoder.encode( self.s ) == bytes((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): assert encoder.encode( self.s ) == bytes((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) class SetEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Set(componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)) )) def __init(self): self.s.clear() self.s.setComponentByPosition(0) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0) self.s.setComponentByPosition(1, 'quick brown') def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0) self.s.setComponentByPosition(2, 1) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testIndefMode(self): self.__init() assert encoder.encode(self.s) == bytes((49, 128, 5, 0, 0, 0)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s ) == bytes((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s ) == bytes((49, 128, 2, 1, 1, 5, 0, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s ) == bytes((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) class SetEncoderWithChoiceWithSchemaEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) c = univ.Choice(componentType=namedtype.NamedTypes( namedtype.NamedType('actual', univ.Boolean(0)) )) self.s = univ.Set(componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.NamedType('status', c) )) def testIndefMode(self): self.s.setComponentByPosition(0) self.s.setComponentByName('status') self.s.getComponentByName('status').setComponentByPosition(0, 1) assert encoder.encode(self.s) == bytes((49, 128, 1, 1, 255, 5, 0, 0, 0)) class SetEncoderWithTaggedChoiceEncoderTestCase(BaseTestCase): def testWithUntaggedChoice(self): c = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('premium', univ.Boolean()) ) ) s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('customer', c) ) ) s.setComponentByName('name', 'A') s.getComponentByName('customer').setComponentByName('premium', True) assert encoder.encode(s) == bytes((49, 128, 1, 1, 255, 4, 1, 65, 0, 0)) def testWithTaggedChoice(self): c = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('premium', univ.Boolean()) ) ).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 7)) s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('customer', c) ) ) s.setComponentByName('name', 'A') s.getComponentByName('customer').setComponentByName('premium', True) assert encoder.encode(s) == bytes((49, 128, 4, 1, 65, 167, 128, 1, 1, 255, 0, 0, 0, 0)) class SequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testIndefMode(self): assert encoder.encode(self.s) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testWithOptionalIndefMode(self): assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testWithDefaultedIndefMode(self): assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) class SequenceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)) ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0) self.s.setComponentByPosition(1, 'quick brown') def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0) self.s.setComponentByPosition(2, 1) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testIndefMode(self): self.__init() assert encoder.encode(self.s) == bytes((48, 128, 5, 0, 0, 0)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s ) == bytes((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 49, 50, 0, 0) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.OctetString('quick brown') assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0) ) class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0) ) class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any()), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 49, 128, 49, 50, 0, 0, 0, 0) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.OctetString('quick brown')) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 2, 49, 128, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 0, 0) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0) ) class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 128, 2, 1, 1, 49, 128, 163, 128, 163, 128, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0) ) class NestedOptionalSequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) inner = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) outerWithOptional = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', inner), ) ) outerWithDefault = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.DefaultedNamedType('inner', inner), ) ) self.s1 = outerWithOptional self.s2 = outerWithDefault def __initOptionalWithDefaultAndOptional(self): self.s1.clear() self.s1[0][0] = 'test' self.s1[0][1] = 123 return self.s1 def __initOptionalWithDefault(self): self.s1.clear() self.s1[0][1] = 123 return self.s1 def __initOptionalWithOptional(self): self.s1.clear() self.s1[0][0] = 'test' return self.s1 def __initOptional(self): self.s1.clear() return self.s1 def __initDefaultWithDefaultAndOptional(self): self.s2.clear() self.s2[0][0] = 'test' self.s2[0][1] = 123 return self.s2 def __initDefaultWithDefault(self): self.s2.clear() self.s2[0][0] = 'test' return self.s2 def __initDefaultWithOptional(self): self.s2.clear() self.s2[0][1] = 123 return self.s2 def testOptionalWithDefaultAndOptional(self): s = self.__initOptionalWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == bytes((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 128, 0, 0)) def testDefaultWithDefaultAndOptional(self): s = self.__initDefaultWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) def testDefaultWithDefault(self): s = self.__initDefaultWithDefault() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testDefaultWithOptional(self): s = self.__initDefaultWithOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) class NestedOptionalChoiceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) layer3 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) layer2 = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('inner', layer3), namedtype.NamedType('first-name', univ.OctetString()) ) ) layer1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', layer2), ) ) self.s = layer1 def __initOptionalWithDefaultAndOptional(self): self.s.clear() self.s[0][0][0] = 'test' self.s[0][0][1] = 123 return self.s def __initOptionalWithDefault(self): self.s.clear() self.s[0][0][1] = 123 return self.s def __initOptionalWithOptional(self): self.s.clear() self.s[0][0][0] = 'test' return self.s def __initOptional(self): self.s.clear() return self.s def testOptionalWithDefaultAndOptional(self): s = self.__initOptionalWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == bytes((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 128, 0, 0)) class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) layer2 = univ.SequenceOf( componentType=univ.OctetString() ) layer1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', layer2), ) ) self.s = layer1 def __initOptionalWithValue(self): self.s.clear() self.s[0][0] = 'test' return self.s def __initOptional(self): self.s.clear() return self.s def testOptionalWithValue(self): s = self.__initOptionalWithValue() assert encoder.encode(s) == bytes((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 128, 0, 0)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2924316 pyasn1-0.6.1/tests/codec/der/0000755000175000017500000000000014670145404016177 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/der/__init__.py0000644000175000017500000000007314525242621020306 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/der/__main__.py0000644000175000017500000000062614525242621020273 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.codec.der.test_encoder.suite', 'tests.codec.der.test_decoder.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/der/test_decoder.py0000644000175000017500000002666714670137102021232 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.codec.der import decoder from pyasn1.error import PyAsn1Error class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( bytes((3, 127, 6) + (170,) * 125 + (128,)) ) == (((1, 0) * 501), b'') def testIndefMode(self): try: decoder.decode( bytes((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) ) except PyAsn1Error: pass else: assert 0, 'indefinite length encoding tolerated' def testDefModeChunked(self): try: assert decoder.decode( bytes((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) ) except PyAsn1Error: pass else: assert 0, 'chunked encoding tolerated' class OctetStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( '\004\017Quick brown fox'.encode() ) == ('Quick brown fox'.encode(), ''.encode()) def testIndefMode(self): try: decoder.decode( bytes((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) ) except PyAsn1Error: pass else: assert 0, 'indefinite length encoding tolerated' def testChunkedMode(self): try: decoder.decode( bytes((36, 23, 4, 2, 81, 117, 4, 2, 105, 99, 4, 2, 107, 32, 4, 2, 98, 114, 4, 2, 111, 119, 4, 1, 110)) ) except PyAsn1Error: pass else: assert 0, 'chunked encoding tolerated' class SequenceDecoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) except PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 3, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='060127') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 163, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithUnaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf(componentType=univ.Any()), openType=openType) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 2 assert s[1][0] == univ.OctetString('quick brown') def testDecodeOpenTypesUnknownType(self): try: s, r = decoder.decode( bytes((48, 6, 2, 1, 2, 6, 1, 39)), asn1Spec=self.s, decodeOpenTypes=True ) except PyAsn1Error: pass else: assert False, 'unknown open type tolerated' def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 3, 49, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010c') def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1][0] == bytes((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( bytes((48, 18, 2, 1, 2, 49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) assert not r assert s[0] == 2 assert s[1][0] == bytes((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) class SequenceDecoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') class SequenceDecoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType( 'blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType ) ) ) def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( bytes((48, 10, 2, 1, 1, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1][0] == 12 def testDecodeOpenTypesUnknownId(self): s, r = decoder.decode( bytes( (48, 10, 2, 1, 3, 49, 5, 131, 3, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True ) assert not r assert s[0] == 3 assert s[1][0] == univ.OctetString(hexValue='02010C') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/der/test_encoder.py0000644000175000017500000004670514670137102021237 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.error import PyAsn1Error from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.type import univ from pyasn1.codec.der import encoder class OctetStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == bytes((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) def testDefModeLong(self): assert encoder.encode( univ.OctetString('Q' * 10000) ) == bytes((4, 130, 39, 16) + (81,) * 10000) class BitStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.BitString((1,)) ) == bytes((3, 2, 7, 128)) def testDefModeLong(self): assert encoder.encode( univ.BitString((1,) * 80000) ) == bytes((3, 130, 39, 17, 0) + (255,) * 10000) class SetOfEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) def testDefMode1(self): self.s.clear() self.s.append('a') self.s.append('ab') assert encoder.encode(self.s) == bytes((49, 7, 4, 1, 97, 4, 2, 97, 98)) def testDefMode2(self): self.s.clear() self.s.append('ab') self.s.append('a') assert encoder.encode(self.s) == bytes((49, 7, 4, 1, 97, 4, 2, 97, 98)) def testDefMode3(self): self.s.clear() self.s.append('b') self.s.append('a') assert encoder.encode(self.s) == bytes((49, 6, 4, 1, 97, 4, 1, 98)) def testDefMode4(self): self.s.clear() self.s.append('a') self.s.append('b') assert encoder.encode(self.s) == bytes((49, 6, 4, 1, 97, 4, 1, 98)) class SetWithAlternatingChoiceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) c = univ.Choice(componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('amount', univ.Boolean())) ) self.s = univ.Set(componentType=namedtype.NamedTypes( namedtype.NamedType('value', univ.Integer(5)), namedtype.NamedType('status', c)) ) def testComponentsOrdering1(self): self.s.setComponentByName('status') self.s.getComponentByName('status').setComponentByPosition(0, 'A') assert encoder.encode(self.s) == bytes((49, 6, 2, 1, 5, 4, 1, 65)) def testComponentsOrdering2(self): self.s.setComponentByName('status') self.s.getComponentByName('status').setComponentByPosition(1, True) assert encoder.encode(self.s) == bytes((49, 6, 1, 1, 255, 2, 1, 5)) class SetWithTaggedChoiceEncoderTestCase(BaseTestCase): def testWithUntaggedChoice(self): c = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('premium', univ.Boolean()) ) ) s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('customer', c) ) ) s.setComponentByName('name', 'A') s.getComponentByName('customer').setComponentByName('premium', True) assert encoder.encode(s) == bytes((49, 6, 1, 1, 255, 4, 1, 65)) def testWithTaggedChoice(self): c = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('premium', univ.Boolean()) ) ).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 7)) s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('customer', c) ) ) s.setComponentByName('name', 'A') s.getComponentByName('customer').setComponentByName('premium', True) assert encoder.encode(s) == bytes((49, 8, 4, 1, 65, 167, 3, 1, 1, 255)) class SequenceEncoderWithUntaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 5, 2, 1, 1, 49, 50) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.OctetString('quick brown') assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 14, 2, 1, 2, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1] = univ.ObjectIdentifier('1.3.6') try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 9, 2, 1, 1, 131, 4, 131, 2, 49, 50) ) class SequenceEncoderWithExplicitlyTaggedOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1] = univ.Integer(12) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 9, 2, 1, 1, 163, 4, 163, 2, 49, 50) ) class SequenceEncoderWithUntaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any()), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 7, 2, 1, 1, 49, 2, 49, 50) ) def testEncodeOpenTypeChoiceTwo(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.OctetString('quick brown')) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 16, 2, 1, 2, 49, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110) ) def testEncodeOpenTypeUnknownId(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' def testEncodeOpenTypeIncompatibleType(self): self.s.clear() self.s[0] = 2 self.s[1].append(univ.ObjectIdentifier('1.3.6')) try: encoder.encode(self.s, asn1Spec=self.s) except PyAsn1Error: assert False, 'incompatible open type tolerated' class SequenceEncoderWithImplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 11, 2, 1, 1, 49, 6, 131, 4, 131, 2, 49, 50) ) class SequenceEncoderWithExplicitlyTaggedSetOfOpenTypesTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) openType = opentype.OpenType( 'id', {1: univ.Integer(), 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.SetOf( componentType=univ.Any().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))), openType=openType) ) ) def testEncodeOpenTypeChoiceOne(self): self.s.clear() self.s[0] = 1 self.s[1].append(univ.Integer(12)) assert encoder.encode(self.s, asn1Spec=self.s) == bytes( (48, 11, 2, 1, 1, 49, 6, 163, 4, 163, 2, 49, 50) ) class NestedOptionalSequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) inner = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) outerWithOptional = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', inner), ) ) outerWithDefault = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.DefaultedNamedType('inner', inner), ) ) self.s1 = outerWithOptional self.s2 = outerWithDefault def __initOptionalWithDefaultAndOptional(self): self.s1.clear() self.s1[0][0] = 'test' self.s1[0][1] = 123 return self.s1 def __initOptionalWithDefault(self): self.s1.clear() self.s1[0][1] = 123 return self.s1 def __initOptionalWithOptional(self): self.s1.clear() self.s1[0][0] = 'test' return self.s1 def __initOptional(self): self.s1.clear() return self.s1 def __initDefaultWithDefaultAndOptional(self): self.s2.clear() self.s2[0][0] = 'test' self.s2[0][1] = 123 return self.s2 def __initDefaultWithDefault(self): self.s2.clear() self.s2[0][0] = 'test' return self.s2 def __initDefaultWithOptional(self): self.s2.clear() self.s2[0][1] = 123 return self.s2 def testDefModeOptionalWithDefaultAndOptional(self): s = self.__initOptionalWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == bytes((48, 5, 48, 3, 2, 1, 123)) def testDefModeOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == bytes((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 0)) def testDefModeDefaultWithDefaultAndOptional(self): s = self.__initDefaultWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeDefaultWithDefault(self): s = self.__initDefaultWithDefault() assert encoder.encode(s) == bytes((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeDefaultWithOptional(self): s = self.__initDefaultWithOptional() assert encoder.encode(s) == bytes((48, 5, 48, 3, 2, 1, 123)) class NestedOptionalChoiceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) layer3 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) layer2 = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('inner', layer3), namedtype.NamedType('first-name', univ.OctetString()) ) ) layer1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', layer2), ) ) self.s = layer1 def __initOptionalWithDefaultAndOptional(self): self.s.clear() self.s[0][0][0] = 'test' self.s[0][0][1] = 123 return self.s def __initOptionalWithDefault(self): self.s.clear() self.s[0][0][1] = 123 return self.s def __initOptionalWithOptional(self): self.s.clear() self.s[0][0][0] = 'test' return self.s def __initOptional(self): self.s.clear() return self.s def testDefModeOptionalWithDefaultAndOptional(self): s = self.__initOptionalWithDefaultAndOptional() assert encoder.encode(s) == bytes((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == bytes((48, 5, 48, 3, 2, 1, 123)) def testDefModeOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == bytes((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 0)) class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) layer2 = univ.SequenceOf( componentType=univ.OctetString() ) layer1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('inner', layer2), ) ) self.s = layer1 def __initOptionalWithValue(self): self.s.clear() self.s[0][0] = 'test' return self.s def __initOptional(self): self.s.clear() return self.s def testDefModeOptionalWithValue(self): s = self.__initOptionalWithValue() assert encoder.encode(s) == bytes((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == bytes((48, 0)) class EmptyInnerFieldOfSequenceEncoderTestCase(BaseTestCase): def testInitializedOptionalNullIsEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('null', univ.Null()) ) ) self.s.clear() self.s[0] = '' assert encoder.encode(self.s) == bytes((48, 2, 5, 0)) def testUninitializedOptionalNullIsNotEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('null', univ.Null()) ) ) self.s.clear() assert encoder.encode(self.s) == bytes((48, 0)) def testInitializedDefaultNullIsNotEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.DefaultedNamedType('null', univ.Null('')) ) ) self.s.clear() self.s[0] = '' assert encoder.encode(self.s) == bytes((48, 0)) def testInitializedOptionalOctetStringIsEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('str', univ.OctetString()) ) ) self.s.clear() self.s[0] = '' assert encoder.encode(self.s) == bytes((48, 2, 4, 0)) def testUninitializedOptionalOctetStringIsNotEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('str', univ.OctetString()) ) ) self.s.clear() assert encoder.encode(self.s) == bytes((48, 0)) def testInitializedDefaultOctetStringIsNotEncoded(self): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.DefaultedNamedType('str', univ.OctetString('')) ) ) self.s.clear() self.s[0] = '' assert encoder.encode(self.s) == bytes((48, 0)) class ClassConstructorTestCase(BaseTestCase): def testKeywords(self): tagmap = {"tagmap": True} typemap = {"typemap": True} sie = encoder.Encoder()._singleItemEncoder self.assertIs(sie._tagMap, encoder.TAG_MAP) self.assertIs(sie._typeMap, encoder.TYPE_MAP) sie = encoder.Encoder( tagMap=tagmap, typeMap=typemap )._singleItemEncoder self.assertIs(sie._tagMap, tagmap) self.assertIs(sie._typeMap, typemap) sie = encoder.Encoder(tagmap, typemap)._singleItemEncoder self.assertIs(sie._tagMap, tagmap) self.assertIs(sie._typeMap, typemap) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2924316 pyasn1-0.6.1/tests/codec/native/0000755000175000017500000000000014670145404016713 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/native/__init__.py0000644000175000017500000000007314525242621021022 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/native/__main__.py0000644000175000017500000000063314525242621021005 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.codec.native.test_encoder.suite', 'tests.codec.native.test_decoder.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/codec/native/test_decoder.py0000644000175000017500000000703514525242621021734 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import namedtype from pyasn1.type import univ from pyasn1.codec.native import decoder from pyasn1.error import PyAsn1Error class BadAsn1SpecTestCase(BaseTestCase): def testBadSpec(self): try: decoder.decode('', asn1Spec='not an Asn1Item') except PyAsn1Error: pass else: assert 0, 'Invalid asn1Spec accepted' class IntegerDecoderTestCase(BaseTestCase): def testPosInt(self): assert decoder.decode(12, asn1Spec=univ.Integer()) == univ.Integer(12) def testNegInt(self): assert decoder.decode(-12, asn1Spec=univ.Integer()) == univ.Integer(-12) class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(True, asn1Spec=univ.Boolean()) == univ.Boolean(True) def testTrueNeg(self): assert decoder.decode(False, asn1Spec=univ.Boolean()) == univ.Boolean(False) class BitStringDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode('11111111', asn1Spec=univ.BitString()) == univ.BitString(hexValue='ff') class OctetStringDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode('Quick brown fox', asn1Spec=univ.OctetString()) == univ.OctetString('Quick brown fox') class NullDecoderTestCase(BaseTestCase): def testNull(self): assert decoder.decode(None, asn1Spec=univ.Null()) == univ.Null('') class ObjectIdentifierDecoderTestCase(BaseTestCase): def testOne(self): assert decoder.decode('1.3.6.11', asn1Spec=univ.ObjectIdentifier()) == univ.ObjectIdentifier('1.3.6.11') class RealDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode(1.33, asn1Spec=univ.Real()) == univ.Real(1.33) class SequenceDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.NamedType('first-name', univ.OctetString()), namedtype.NamedType('age', univ.Integer(33)) ) ) def testSimple(self): s = self.s.clone() s[0] = univ.Null('') s[1] = univ.OctetString('xx') s[2] = univ.Integer(33) assert decoder.decode({'place-holder': None, 'first-name': 'xx', 'age': 33}, asn1Spec=self.s) == s class ChoiceDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), namedtype.NamedType('first-name', univ.OctetString()), namedtype.NamedType('age', univ.Integer(33)) ) ) def testSimple(self): s = self.s.clone() s[1] = univ.OctetString('xx') assert decoder.decode({'first-name': 'xx'}, asn1Spec=self.s) == s class AnyDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any() def testSimple(self): assert decoder.decode('fox', asn1Spec=univ.Any()) == univ.Any('fox') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/native/test_encoder.py0000644000175000017500000000745514670137102021752 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import namedtype from pyasn1.type import univ from pyasn1.codec.native import encoder from pyasn1.error import PyAsn1Error class BadAsn1SpecTestCase(BaseTestCase): def testBadValueType(self): try: encoder.encode('not an Asn1Item') except PyAsn1Error: pass else: assert 0, 'Invalid value type accepted' class IntegerEncoderTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(univ.Integer(12)) == 12 def testNegInt(self): assert encoder.encode(univ.Integer(-12)) == -12 class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) is True def testFalse(self): assert encoder.encode(univ.Boolean(0)) is False class BitStringEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) def testValue(self): assert encoder.encode(self.b) == '101010011000101' class OctetStringEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.o = univ.OctetString('Quick brown fox') def testValue(self): assert encoder.encode(self.o) == b'Quick brown fox' class NullEncoderTestCase(BaseTestCase): def testNull(self): assert encoder.encode(univ.Null('')) is None class ObjectIdentifierEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode(univ.ObjectIdentifier((1, 3, 6, 0, 12345))) == '1.3.6.0.12345' class RealEncoderTestCase(BaseTestCase): def testChar(self): assert encoder.encode(univ.Real((123, 10, 11))) == 1.23e+13 def testPlusInf(self): assert encoder.encode(univ.Real('inf')) == float('inf') def testMinusInf(self): assert encoder.encode(univ.Real('-inf')) == float('-inf') class SequenceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence(componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.OptionalNamedType('first-name', univ.OctetString('')), namedtype.DefaultedNamedType('age', univ.Integer(33)), )) def testSimple(self): s = self.s.clone() s[0] = univ.Null('') s[1] = 'abc' s[2] = 123 assert encoder.encode(s) == {'place-holder': None, 'first-name': b'abc', 'age': 123} class ChoiceEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.NamedType('number', univ.Integer(0)), namedtype.NamedType('string', univ.OctetString()) ) ) def testEmpty(self): try: encoder.encode(self.s) except PyAsn1Error: pass else: assert False, 'encoded unset choice' def testFilled(self): self.s.setComponentByPosition(0, univ.Null('')) assert encoder.encode(self.s) == {'place-holder': None} class AnyEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) def testSimple(self): assert encoder.encode(self.s) == b'fox' suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/codec/test_streaming.py0000644000175000017500000000441614670137102021030 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import io import sys import unittest from tests.base import BaseTestCase from pyasn1.codec import streaming class CachingStreamWrapperTestCase(BaseTestCase): def setUp(self): self.shortText = b"abcdefghij" self.longText = self.shortText * (io.DEFAULT_BUFFER_SIZE * 5) self.shortStream = io.BytesIO(self.shortText) self.longStream = io.BytesIO(self.longText) def testReadJustFromCache(self): wrapper = streaming.CachingStreamWrapper(self.shortStream) wrapper.read(6) wrapper.seek(3) assert wrapper.read(1) == b"d" assert wrapper.read(1) == b"e" assert wrapper.tell() == 5 def testReadFromCacheAndStream(self): wrapper = streaming.CachingStreamWrapper(self.shortStream) wrapper.read(6) wrapper.seek(3) assert wrapper.read(4) == b"defg" assert wrapper.tell() == 7 def testReadJustFromStream(self): wrapper = streaming.CachingStreamWrapper(self.shortStream) assert wrapper.read(6) == b"abcdef" assert wrapper.tell() == 6 def testPeek(self): wrapper = streaming.CachingStreamWrapper(self.longStream) read_bytes = wrapper.peek(io.DEFAULT_BUFFER_SIZE + 73) assert len(read_bytes) == io.DEFAULT_BUFFER_SIZE + 73 assert read_bytes.startswith(b"abcdefg") assert wrapper.tell() == 0 assert wrapper.read(4) == b"abcd" def testMarkedPositionResets(self): wrapper = streaming.CachingStreamWrapper(self.longStream) wrapper.read(10) wrapper.markedPosition = wrapper.tell() assert wrapper.markedPosition == 10 # Reach the maximum capacity of cache wrapper.read(io.DEFAULT_BUFFER_SIZE) assert wrapper.tell() == 10 + io.DEFAULT_BUFFER_SIZE # The following should clear the cache wrapper.markedPosition = wrapper.tell() assert wrapper.markedPosition == 0 assert len(wrapper._cache.getvalue()) == 0 suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2934318 pyasn1-0.6.1/tests/compat/0000755000175000017500000000000014670145404015633 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/compat/__init__.py0000644000175000017500000000007314525242621017742 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/compat/__main__.py0000644000175000017500000000061714525242621017727 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.compat.test_integer.suite', 'tests.compat.test_octets.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/test_debug.py0000644000175000017500000000164514525242621017053 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1 import debug from pyasn1 import error class DebugCaseBase(BaseTestCase): def testKnownFlags(self): debug.setLogger(0) debug.setLogger(debug.Debug('all', 'encoder', 'decoder')) debug.setLogger(0) def testUnknownFlags(self): try: debug.setLogger(debug.Debug('all', 'unknown', loggerName='xxx')) except error.PyAsn1Error: debug.setLogger(0) return else: debug.setLogger(0) assert 0, 'unknown debug flag tolerated' suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1726008068.2944317 pyasn1-0.6.1/tests/type/0000755000175000017500000000000014670145404015331 5ustar00spichugispichugi././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/__init__.py0000644000175000017500000000007314525242621017440 0ustar00spichugispichugi# This file is necessary to make this directory a package. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/__main__.py0000644000175000017500000000115414525242621017422 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.type.test_constraint.suite', 'tests.type.test_opentype.suite', 'tests.type.test_namedtype.suite', 'tests.type.test_namedval.suite', 'tests.type.test_tag.suite', 'tests.type.test_univ.suite', 'tests.type.test_char.suite', 'tests.type.test_useful.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/type/test_char.py0000644000175000017500000001201514670137102017652 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import pickle import sys import unittest from tests.base import BaseTestCase from pyasn1.type import char from pyasn1.type import univ from pyasn1.type import constraint from pyasn1.error import PyAsn1Error class AbstractStringTestCase(object): initializer = () encoding = 'us-ascii' asn1Type = None def setUp(self): BaseTestCase.setUp(self) self.asn1String = self.asn1Type(bytes(self.initializer), encoding=self.encoding) self.pythonString = bytes(self.initializer).decode(self.encoding) def testUnicode(self): assert self.asn1String == self.pythonString, 'unicode init fails' def testLength(self): assert len(self.asn1String) == len(self.pythonString), 'unicode len() fails' def testSizeConstraint(self): asn1Spec = self.asn1Type(subtypeSpec=constraint.ValueSizeConstraint(1, 1)) try: asn1Spec.clone(self.pythonString) except PyAsn1Error: pass else: assert False, 'Size constraint tolerated' try: asn1Spec.clone(self.pythonString[0]) except PyAsn1Error: assert False, 'Size constraint failed' def testSerialised(self): assert bytes(self.asn1String) == self.pythonString.encode(self.encoding), '__str__() fails' def testPrintable(self): assert str(self.asn1String) == self.pythonString, '__str__() fails' def testInit(self): assert self.asn1Type(self.pythonString) == self.pythonString assert self.asn1Type(self.pythonString.encode(self.encoding)) == self.pythonString assert self.asn1Type(univ.OctetString(self.pythonString.encode(self.encoding))) == self.pythonString assert self.asn1Type(self.asn1Type(self.pythonString)) == self.pythonString assert self.asn1Type(self.initializer, encoding=self.encoding) == self.pythonString def testInitFromAsn1(self): assert self.asn1Type(self.asn1Type(self.pythonString)) == self.pythonString assert self.asn1Type(univ.OctetString(self.pythonString.encode(self.encoding), encoding=self.encoding)) == self.pythonString def testAsOctets(self): assert self.asn1String.asOctets() == self.pythonString.encode(self.encoding), 'testAsOctets() fails' def testAsNumbers(self): assert self.asn1String.asNumbers() == self.initializer, 'testAsNumbers() fails' def testSeq(self): assert self.asn1String[0] == self.pythonString[0], '__getitem__() fails' def testEmpty(self): try: str(self.asn1Type()) except PyAsn1Error: pass else: assert 0, 'Value operation on ASN1 type tolerated' def testAdd(self): assert self.asn1String + self.pythonString.encode(self.encoding) == self.pythonString + self.pythonString, '__add__() fails' def testRadd(self): assert self.pythonString.encode(self.encoding) + self.asn1String == self.pythonString + self.pythonString, '__radd__() fails' def testMul(self): assert self.asn1String * 2 == self.pythonString * 2, '__mul__() fails' def testRmul(self): assert 2 * self.asn1String == 2 * self.pythonString, '__rmul__() fails' def testContains(self): assert self.pythonString in self.asn1String assert self.pythonString + self.pythonString not in self.asn1String def testReverse(self): assert list(reversed(self.asn1String)) == list(reversed(self.pythonString)) def testSchemaPickling(self): old_asn1 = self.asn1Type() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == self.asn1Type assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = self.asn1String serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == self.asn1String class VisibleStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (97, 102) encoding = 'us-ascii' asn1Type = char.VisibleString class GeneralStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (169, 174) encoding = 'iso-8859-1' asn1Type = char.GeneralString class UTF8StringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (209, 132, 208, 176) encoding = 'utf-8' asn1Type = char.UTF8String class BMPStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (4, 48, 4, 68) encoding = 'utf-16-be' asn1Type = char.BMPString class UniversalStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (0, 0, 4, 48, 0, 0, 4, 68) encoding = 'utf-32-be' asn1Type = char.UniversalString suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/test_constraint.py0000644000175000017500000002613014525242621021126 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import constraint from pyasn1.type import error class SingleValueConstraintTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.v1 = 1, 2 self.v2 = 3, 4 self.c1 = constraint.SingleValueConstraint(*self.v1) self.c2 = constraint.SingleValueConstraint(*self.v2) def testCmp(self): assert self.c1 == self.c1, 'comparison fails' def testHash(self): assert hash(self.c1) != hash(self.c2), 'hash() fails' def testGoodVal(self): try: self.c1(1) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(4) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' def testContains(self): for v in self.v1: assert v in self.c1 assert v not in self.c2 for v in self.v2: assert v in self.c2 assert v not in self.c1 def testIter(self): assert set(self.v1) == set(self.c1) assert set(self.v2) == set(self.c2) def testSub(self): subconst = self.c1 - constraint.SingleValueConstraint(self.v1[0]) assert list(subconst) == [self.v1[1]] def testAdd(self): superconst = self.c1 + self.c2 assert set(superconst) == set(self.v1 + self.v2) class ContainedSubtypeConstraintTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ContainedSubtypeConstraint( constraint.SingleValueConstraint(12) ) def testGoodVal(self): try: self.c1(12) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(4) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class ValueRangeConstraintTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ValueRangeConstraint(1, 4) def testGoodVal(self): try: self.c1(1) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(-5) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class ValueSizeConstraintTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ValueSizeConstraint(1, 2) def testGoodVal(self): try: self.c1('a') except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1('abc') except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class PermittedAlphabetConstraintTestCase(SingleValueConstraintTestCase): def setUp(self): self.v1 = 'A', 'B' self.v2 = 'C', 'D' self.c1 = constraint.PermittedAlphabetConstraint(*self.v1) self.c2 = constraint.PermittedAlphabetConstraint(*self.v2) def testGoodVal(self): try: self.c1('A') except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1('E') except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class WithComponentsConstraintTestCase(BaseTestCase): def testGoodVal(self): c = constraint.WithComponentsConstraint( ('A', constraint.ComponentPresentConstraint()), ('B', constraint.ComponentAbsentConstraint())) try: c({'A': 1}) except error.ValueConstraintError: assert 0, 'constraint check fails' def testGoodValWithExtraFields(self): c = constraint.WithComponentsConstraint( ('A', constraint.ComponentPresentConstraint()), ('B', constraint.ComponentAbsentConstraint()) ) try: c({'A': 1, 'C': 2}) except error.ValueConstraintError: assert 0, 'constraint check fails' def testEmptyConstraint(self): c = constraint.WithComponentsConstraint() try: c({'A': 1}) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): c = constraint.WithComponentsConstraint( ('A', constraint.ComponentPresentConstraint()) ) try: c({'B': 2}) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' def testBadValExtraFields(self): c = constraint.WithComponentsConstraint( ('A', constraint.ComponentPresentConstraint()) ) try: c({'B': 2, 'C': 3}) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class ConstraintsIntersectionTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsIntersection( constraint.SingleValueConstraint(4), constraint.ValueRangeConstraint(2, 4) ) def testCmp1(self): assert constraint.SingleValueConstraint(4) in self.c1, '__cmp__() fails' def testCmp2(self): assert constraint.SingleValueConstraint(5) not in self.c1, \ '__cmp__() fails' def testCmp3(self): c = constraint.ConstraintsUnion(constraint.ConstraintsIntersection( constraint.SingleValueConstraint(4), constraint.ValueRangeConstraint(2, 4)) ) assert self.c1 in c, '__cmp__() fails' def testCmp4(self): c = constraint.ConstraintsUnion( constraint.ConstraintsIntersection(constraint.SingleValueConstraint(5)) ) assert self.c1 not in c, '__cmp__() fails' def testGoodVal(self): try: self.c1(4) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(-5) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class InnerTypeConstraintTestCase(BaseTestCase): def testConst1(self): c = constraint.InnerTypeConstraint( constraint.SingleValueConstraint(4) ) try: c(4, 32) except error.ValueConstraintError: assert 0, 'constraint check fails' try: c(5, 32) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' def testConst2(self): c = constraint.InnerTypeConstraint( (0, constraint.SingleValueConstraint(4), 'PRESENT'), (1, constraint.SingleValueConstraint(4), 'ABSENT') ) try: c(4, 0) except error.ValueConstraintError: assert 0, 'constraint check fails' try: c(4, 1) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' try: c(3, 0) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' # Constraints compositions class ConstraintsIntersectionRangeTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsIntersection( constraint.ValueRangeConstraint(1, 9), constraint.ValueRangeConstraint(2, 5) ) def testGoodVal(self): try: self.c1(3) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(0) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class ConstraintsUnionTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsUnion( constraint.SingleValueConstraint(5), constraint.ValueRangeConstraint(1, 3) ) def testGoodVal(self): try: self.c1(2) self.c1(5) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(-5) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' class ConstraintsExclusionTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsExclusion( constraint.ValueRangeConstraint(2, 4) ) def testGoodVal(self): try: self.c1(6) except error.ValueConstraintError: assert 0, 'constraint check fails' def testBadVal(self): try: self.c1(2) except error.ValueConstraintError: pass else: assert 0, 'constraint check fails' # Constraints derivations class DirectDerivationTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.SingleValueConstraint(5) self.c2 = constraint.ConstraintsUnion( self.c1, constraint.ValueRangeConstraint(1, 3) ) def testGoodVal(self): assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed' assert not self.c1.isSubTypeOf(self.c2), 'isSubTypeOf failed' def testBadVal(self): assert not self.c2.isSuperTypeOf(self.c1), 'isSuperTypeOf failed' assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' class IndirectDerivationTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsIntersection( constraint.ValueRangeConstraint(1, 30) ) self.c2 = constraint.ConstraintsIntersection( self.c1, constraint.ValueRangeConstraint(1, 20) ) self.c2 = constraint.ConstraintsIntersection( self.c2, constraint.ValueRangeConstraint(1, 10) ) def testGoodVal(self): assert self.c1.isSuperTypeOf(self.c2), 'isSuperTypeOf failed' assert not self.c1.isSubTypeOf(self.c2), 'isSubTypeOf failed' def testBadVal(self): assert not self.c2.isSuperTypeOf(self.c1), 'isSuperTypeOf failed' assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' # TODO: how to apply size constraints to constructed types? suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/test_namedtype.py0000644000175000017500000001023214525242621020724 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import namedtype from pyasn1.type import univ from pyasn1.error import PyAsn1Error class NamedTypeCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.e = namedtype.NamedType('age', univ.Integer(0)) def testIter(self): n, t = self.e assert n == 'age' or t == univ.Integer(), 'unpack fails' def testRepr(self): assert 'age' in repr(self.e) class NamedTypesCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.e = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.OctetString('')), namedtype.OptionalNamedType('age', univ.Integer(0)), namedtype.NamedType('family-name', univ.OctetString('')) ) def testRepr(self): assert 'first-name' in repr(self.e) def testContains(self): assert 'first-name' in self.e assert '' not in self.e # noinspection PyUnusedLocal def testGetItem(self): assert self.e[0] == namedtype.NamedType('first-name', univ.OctetString('')) def testIter(self): assert list(self.e) == ['first-name', 'age', 'family-name'] def testGetTypeByPosition(self): assert self.e.getTypeByPosition(0) == univ.OctetString(''), \ 'getTypeByPosition() fails' def testGetNameByPosition(self): assert self.e.getNameByPosition(0) == 'first-name', \ 'getNameByPosition() fails' def testGetPositionByName(self): assert self.e.getPositionByName('first-name') == 0, \ 'getPositionByName() fails' def testGetTypesNearPosition(self): assert self.e.getTagMapNearPosition(0).presentTypes == { univ.OctetString.tagSet: univ.OctetString('') } assert self.e.getTagMapNearPosition(1).presentTypes == { univ.Integer.tagSet: univ.Integer(0), univ.OctetString.tagSet: univ.OctetString('') } assert self.e.getTagMapNearPosition(2).presentTypes == { univ.OctetString.tagSet: univ.OctetString('') } def testGetTagMap(self): assert self.e.tagMap.presentTypes == { univ.OctetString.tagSet: univ.OctetString(''), univ.Integer.tagSet: univ.Integer(0) } def testStrTagMap(self): assert 'TagMap' in str(self.e.tagMap) assert 'OctetString' in str(self.e.tagMap) assert 'Integer' in str(self.e.tagMap) def testReprTagMap(self): assert 'TagMap' in repr(self.e.tagMap) assert 'OctetString' in repr(self.e.tagMap) assert 'Integer' in repr(self.e.tagMap) def testGetTagMapWithDups(self): try: self.e.tagMapUnique[0] except PyAsn1Error: pass else: assert 0, 'Duped types not noticed' def testGetPositionNearType(self): assert self.e.getPositionNearType(univ.OctetString.tagSet, 0) == 0 assert self.e.getPositionNearType(univ.Integer.tagSet, 1) == 1 assert self.e.getPositionNearType(univ.OctetString.tagSet, 2) == 2 class OrderedNamedTypesCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.e = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.OctetString('')), namedtype.NamedType('age', univ.Integer(0)) ) def testGetTypeByPosition(self): assert self.e.getTypeByPosition(0) == univ.OctetString(''), \ 'getTypeByPosition() fails' class DuplicateNamedTypesCaseBase(BaseTestCase): def testDuplicateDefaultTags(self): nt = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.Any()), namedtype.NamedType('age', univ.Any()) ) assert isinstance(nt.tagMap, namedtype.NamedTypes.PostponedError) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/test_namedval.py0000644000175000017500000000334314525242621020532 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import namedval class NamedValuesCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.e = namedval.NamedValues(('off', 0), ('on', 1)) def testDict(self): assert set(self.e.items()) == {('off', 0), ('on', 1)} assert set(self.e.keys()) == {'off', 'on'} assert set(self.e) == {'off', 'on'} assert set(self.e.values()) == {0, 1} assert 'on' in self.e and 'off' in self.e and 'xxx' not in self.e assert 0 in self.e and 1 in self.e and 2 not in self.e def testInit(self): assert namedval.NamedValues(off=0, on=1) == {'off': 0, 'on': 1} assert namedval.NamedValues('off', 'on') == {'off': 0, 'on': 1} assert namedval.NamedValues(('c', 0)) == {'c': 0} assert namedval.NamedValues('a', 'b', ('c', 0), d=1) == {'c': 0, 'd': 1, 'a': 2, 'b': 3} def testLen(self): assert len(self.e) == 2 assert len(namedval.NamedValues()) == 0 def testAdd(self): assert namedval.NamedValues(off=0) + namedval.NamedValues(on=1) == {'off': 0, 'on': 1} def testClone(self): assert namedval.NamedValues(off=0).clone(('on', 1)) == {'off': 0, 'on': 1} assert namedval.NamedValues(off=0).clone(on=1) == {'off': 0, 'on': 1} def testStrRepr(self): assert str(self.e) assert repr(self.e) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/type/test_opentype.py0000644000175000017500000000500514670137102020601 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import univ from pyasn1.type import tag from pyasn1.type import namedtype from pyasn1.type import opentype from pyasn1.error import PyAsn1Error class UntaggedAnyTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', univ.Any()) ) self.s = Sequence() def testTypeCheckOnAssignment(self): self.s.clear() self.s['blob'] = univ.Any(b'xxx') # this should succeed because Any is untagged and unconstrained self.s['blob'] = univ.Integer(123) class TaggedAnyTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.taggedAny = univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 20)) class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', self.taggedAny) ) self.s = Sequence() def testTypeCheckOnAssignment(self): self.s.clear() self.s['blob'] = self.taggedAny.clone('xxx') try: self.s.setComponentByName('blob', univ.Integer(123)) except PyAsn1Error: pass else: assert False, 'non-open type assignment tolerated' class TaggedAnyOpenTypeTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.taggedAny = univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 20)) class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), namedtype.NamedType('blob', self.taggedAny, openType=opentype.OpenType(name='id')) ) self.s = Sequence() def testTypeCheckOnAssignment(self): self.s.clear() self.s['blob'] = univ.Any(b'xxx') self.s['blob'] = univ.Integer(123) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/test_tag.py0000644000175000017500000001053714525242621017521 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import sys import unittest from tests.base import BaseTestCase from pyasn1.type import tag class TagTestCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.t1 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) self.t2 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) class TagReprTestCase(TagTestCaseBase): def testRepr(self): assert 'Tag' in repr(self.t1) class TagCmpTestCase(TagTestCaseBase): def testCmp(self): assert self.t1 == self.t2, 'tag comparison fails' def testHash(self): assert hash(self.t1) == hash(self.t2), 'tag hash comparison fails' def testSequence(self): assert self.t1[0] == self.t2[0] and \ self.t1[1] == self.t2[1] and \ self.t1[2] == self.t2[2], 'tag sequence protocol fails' class TagSetTestCaseBase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.ts1 = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ) self.ts2 = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ) class TagSetReprTestCase(TagSetTestCaseBase): def testRepr(self): assert 'TagSet' in repr(self.ts1) class TagSetCmpTestCase(TagSetTestCaseBase): def testCmp(self): assert self.ts1 == self.ts2, 'tag set comparison fails' def testHash(self): assert hash(self.ts1) == hash(self.ts2), 'tag set hash comp. fails' def testLen(self): assert len(self.ts1) == len(self.ts2), 'tag length comparison fails' class TaggingTestSuite(TagSetTestCaseBase): def testImplicitTag(self): t = self.ts1.tagImplicitly( tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14) ) assert t == tag.TagSet( tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 14) ), 'implicit tagging went wrong' def testExplicitTag(self): t = self.ts1.tagExplicitly( tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 32) ) assert t == tag.TagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassPrivate, tag.tagFormatConstructed, 32) ), 'explicit tagging went wrong' class TagSetAddTestSuite(TagSetTestCaseBase): def testAdd(self): t = self.ts1 + tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) assert t == tag.TagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) ), 'TagSet.__add__() fails' def testRadd(self): t = tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2) + self.ts1 assert t == tag.TagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 2), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ), 'TagSet.__radd__() fails' class SuperTagSetTestCase(TagSetTestCaseBase): def testSuperTagCheck1(self): assert self.ts1.isSuperTagSetOf( tag.TagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) )), 'isSuperTagSetOf() fails' def testSuperTagCheck2(self): assert not self.ts1.isSuperTagSetOf( tag.TagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 13) )), 'isSuperTagSetOf() fails' def testSuperTagCheck3(self): assert self.ts1.isSuperTagSetOf( tag.TagSet((), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12)) ), 'isSuperTagSetOf() fails' suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1726004802.0 pyasn1-0.6.1/tests/type/test_univ.py0000644000175000017500000020524514670137102017727 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import math import pickle import platform import sys import unittest from tests.base import BaseTestCase from pyasn1.type import univ from pyasn1.type import tag from pyasn1.type import constraint from pyasn1.type import namedtype from pyasn1.type import namedval from pyasn1.type import error from pyasn1.error import PyAsn1Error from pyasn1.error import PyAsn1UnicodeEncodeError, PyAsn1UnicodeDecodeError class NoValueTestCase(BaseTestCase): def testSingleton(self): assert univ.NoValue() is univ.NoValue(), 'NoValue is not a singleton' def testRepr(self): try: repr(univ.noValue) except PyAsn1Error: assert False, 'repr() on NoValue object fails' def testIsInstance(self): try: assert isinstance(univ.noValue, univ.NoValue), 'isinstance() on NoValue() object fails' except PyAsn1Error: assert False, 'isinstance() on NoValue object fails' def testStr(self): try: str(univ.noValue) except PyAsn1Error: pass else: assert False, 'str() works for NoValue object' def testLen(self): try: len(univ.noValue) except PyAsn1Error: pass else: assert False, 'len() works for NoValue object' def testCmp(self): try: univ.noValue == 1 except PyAsn1Error: pass else: assert False, 'comparison works for NoValue object' def testSubs(self): try: univ.noValue[0] except PyAsn1Error: pass else: assert False, '__getitem__() works for NoValue object' def testKey(self): try: univ.noValue['key'] except PyAsn1Error: pass else: assert False, '__getitem__() works for NoValue object' def testKeyAssignment(self): try: univ.noValue['key'] = 123 except PyAsn1Error: pass else: assert False, '__setitem__() works for NoValue object' def testInt(self): try: int(univ.noValue) except PyAsn1Error: pass else: assert False, 'integer conversion works for NoValue object' def testAdd(self): try: univ.noValue + univ.noValue except PyAsn1Error: pass else: assert False, 'addition works for NoValue object' def testBitShift(self): try: univ.noValue << 1 except PyAsn1Error: pass else: assert False, 'bitshift works for NoValue object' def testBooleanEvaluation(self): try: if univ.noValue: pass except PyAsn1Error: pass else: assert False, 'boolean evaluation works for NoValue object' @unittest.skipIf( platform.python_implementation() == "PyPy", "getsizeof() raises TypeError on PyPy" ) def testSizeOf(self): try: sys.getsizeof(univ.noValue) except PyAsn1Error: assert False, 'sizeof failed for NoValue object' class IntegerTestCase(BaseTestCase): def testStr(self): assert str(univ.Integer(1)) in ('1', '1L'), 'str() fails' def testRepr(self): assert '123' in repr(univ.Integer(123)) def testAnd(self): assert univ.Integer(1) & 0 == 0, '__and__() fails' def testOr(self): assert univ.Integer(1) | 0 == 1, '__or__() fails' def testXor(self): assert univ.Integer(1) ^ 0 == 1, '__xor__() fails' def testRand(self): assert 0 & univ.Integer(1) == 0, '__rand__() fails' def testRor(self): assert 0 | univ.Integer(1) == 1, '__ror__() fails' def testRxor(self): assert 0 ^ univ.Integer(1) == 1, '__rxor__() fails' def testAdd(self): assert univ.Integer(-4) + 6 == 2, '__add__() fails' def testRadd(self): assert 4 + univ.Integer(5) == 9, '__radd__() fails' def testSub(self): assert univ.Integer(3) - 6 == -3, '__sub__() fails' def testRsub(self): assert 6 - univ.Integer(3) == 3, '__rsub__() fails' def testMul(self): assert univ.Integer(3) * -3 == -9, '__mul__() fails' def testRmul(self): assert 2 * univ.Integer(3) == 6, '__rmul__() fails' def testDivInt(self): assert univ.Integer(4) / 2 == 2, '__div__() fails' def testDivFloat(self): assert univ.Integer(3) / 2 == 1.5, '__div__() fails' def testRdivFloat(self): assert 3 / univ.Integer(2) == 1.5, '__rdiv__() fails' def testRdivInt(self): assert 6 / univ.Integer(3) == 2, '__rdiv__() fails' def testTrueDiv(self): assert univ.Integer(3) / univ.Integer(2) == 1.5, '__truediv__() fails' def testFloorDiv(self): assert univ.Integer(3) // univ.Integer(2) == 1, '__floordiv__() fails' def testMod(self): assert univ.Integer(3) % 2 == 1, '__mod__() fails' def testRmod(self): assert 4 % univ.Integer(3) == 1, '__rmod__() fails' def testPow(self): assert univ.Integer(3) ** 2 == 9, '__pow__() fails' def testRpow(self): assert 2 ** univ.Integer(2) == 4, '__rpow__() fails' def testLshift(self): assert univ.Integer(1) << 1 == 2, '<< fails' def testRshift(self): assert univ.Integer(2) >> 1 == 1, '>> fails' def testInt(self): assert int(univ.Integer(3)) == 3, '__int__() fails' def testLong(self): assert int(univ.Integer(8)) == 8, '__long__() fails' def testFloat(self): assert float(univ.Integer(4)) == 4.0, '__float__() fails' def testPos(self): assert +univ.Integer(1) == 1, '__pos__() fails' def testNeg(self): assert -univ.Integer(1) == -1, '__neg__() fails' def testInvert(self): assert ~univ.Integer(1) == -2, '__invert__() fails' def testRound(self): assert round(univ.Integer(1), 3) == 1.0, '__round__() fails' def testFloor(self): assert math.floor(univ.Integer(1)) == 1, '__floor__() fails' def testCeil(self): assert math.ceil(univ.Integer(1)) == 1, '__ceil__() fails' def testTrunc(self): assert math.trunc(univ.Integer(1)) == 1, '__trunc__() fails' def testPrettyIn(self): assert univ.Integer('3') == 3, 'prettyIn() fails' def testTag(self): assert univ.Integer().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x02) ) def testNamedVals(self): class Integer(univ.Integer): namedValues = univ.Integer.namedValues.clone(('asn1', 1)) assert Integer('asn1') == 1, 'named val fails' assert int(Integer('asn1')) == 1, 'named val fails' assert str(Integer('asn1')) == 'asn1', 'named val __str__() fails' def testSubtype(self): assert univ.Integer().subtype( value=1, implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2), subtypeSpec=constraint.SingleValueConstraint(1, 3) ) == univ.Integer( value=1, tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2)), subtypeSpec=constraint.ConstraintsIntersection(constraint.SingleValueConstraint(1, 3)) ) class IntegerPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Integer() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Integer assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Integer(-123) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == -123 class BooleanTestCase(BaseTestCase): def testTruth(self): assert univ.Boolean(True) and univ.Boolean(1), 'Truth initializer fails' def testFalse(self): assert not univ.Boolean(False) and not univ.Boolean(0), 'False initializer fails' def testStr(self): assert str(univ.Boolean(1)) == 'True', 'str() fails' def testInt(self): assert int(univ.Boolean(1)) == 1, 'int() fails' def testRepr(self): assert 'Boolean' in repr(univ.Boolean(1)) def testTag(self): assert univ.Boolean().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x01) ) def testConstraints(self): class Boolean(univ.Boolean): pass try: Boolean(2) except error.ValueConstraintError: pass else: assert 0, 'constraint fail' class BooleanPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Boolean() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Boolean assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Boolean(True) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == True class BitStringTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.b = univ.BitString( namedValues=namedval.NamedValues(('Active', 0), ('Urgent', 1)) ) def testBinDefault(self): class BinDefault(univ.BitString): defaultBinValue = '1010100110001010' assert BinDefault() == univ.BitString(binValue='1010100110001010') def testHexDefault(self): class HexDefault(univ.BitString): defaultHexValue = 'A98A' assert HexDefault() == univ.BitString(hexValue='A98A') def testSet(self): assert self.b.clone('Active') == (1,) assert self.b.clone('Urgent') == (0, 1) assert self.b.clone('Urgent, Active') == (1, 1) assert self.b.clone("'1010100110001010'B") == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) assert self.b.clone("'A98A'H") == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) assert self.b.clone(binValue='1010100110001010') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) assert self.b.clone(hexValue='A98A') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) assert self.b.clone('1010100110001010') == (1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0) assert self.b.clone((1, 0, 1)) == (1, 0, 1) def testStr(self): assert str(self.b.clone('Urgent')) == '01' def testRepr(self): assert 'BitString' in repr(self.b.clone('Urgent,Active')) def testTag(self): assert univ.BitString().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x03) ) def testLen(self): assert len(self.b.clone("'A98A'H")) == 16 def testGetItem(self): assert self.b.clone("'A98A'H")[0] == 1 assert self.b.clone("'A98A'H")[1] == 0 assert self.b.clone("'A98A'H")[2] == 1 def testReverse(self): assert list(reversed(univ.BitString([0, 0, 1]))) == list(univ.BitString([1, 0, 0])) def testAsOctets(self): assert self.b.clone(hexValue='A98A').asOctets() == bytes((0xa9, 0x8a)), 'testAsOctets() fails' def testAsInts(self): assert self.b.clone(hexValue='A98A').asNumbers() == (0xa9, 0x8a), 'testAsNumbers() fails' def testMultipleOfEightPadding(self): assert self.b.clone((1, 0, 1)).asNumbers() == (5,) def testAsInteger(self): assert self.b.clone('11000000011001').asInteger() == 12313 assert self.b.clone('1100110011011111').asInteger() == 52447 def testStaticDef(self): class BitString(univ.BitString): pass assert BitString('11000000011001').asInteger() == 12313 class BitStringPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.BitString() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.BitString assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.BitString((1, 0, 1, 0)) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == (1, 0, 1, 0) class OctetStringWithUnicodeMixIn(object): initializer = () encoding = 'us-ascii' def setUp(self): self.pythonString = bytes(self.initializer).decode(self.encoding) self.encodedPythonString = self.pythonString.encode(self.encoding) self.numbersString = tuple(self.encodedPythonString) def testInit(self): assert univ.OctetString(self.encodedPythonString) == self.encodedPythonString, '__init__() fails' def testInitFromAsn1(self): assert univ.OctetString(univ.OctetString(self.encodedPythonString)) == self.encodedPythonString assert univ.OctetString(univ.Integer(123)) == univ.OctetString('123') def testSerialised(self): assert bytes(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' def testPrintable(self): assert str(univ.OctetString(self.pythonString, encoding=self.encoding)) == self.pythonString, 'unicode init fails' def testSeq(self): assert univ.OctetString(self.encodedPythonString)[0] == self.encodedPythonString[0], '__getitem__() fails' def testRepr(self): assert 'abc' in repr(univ.OctetString('abc')) def testAsOctets(self): assert univ.OctetString(self.encodedPythonString).asOctets() == self.encodedPythonString, 'testAsOctets() fails' def testAsInts(self): assert univ.OctetString(self.encodedPythonString).asNumbers() == self.numbersString, 'testAsNumbers() fails' def testAdd(self): assert univ.OctetString(self.encodedPythonString) + self.encodedPythonString == self.encodedPythonString + self.encodedPythonString, '__add__() fails' def testRadd(self): assert self.encodedPythonString + univ.OctetString(self.encodedPythonString) == self.encodedPythonString + self.encodedPythonString, '__radd__() fails' def testMul(self): assert univ.OctetString(self.encodedPythonString) * 2 == self.encodedPythonString * 2, '__mul__() fails' def testRmul(self): assert 2 * univ.OctetString(self.encodedPythonString) == 2 * self.encodedPythonString, '__rmul__() fails' def testContains(self): s = univ.OctetString(self.encodedPythonString) assert self.encodedPythonString in s assert self.encodedPythonString * 2 not in s def testReverse(self): assert list(reversed(univ.OctetString(self.encodedPythonString))) == list(reversed(self.encodedPythonString)) class OctetStringWithAsciiTestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (97, 102) encoding = 'us-ascii' class OctetStringUnicodeErrorTestCase(BaseTestCase): def testEncodeError(self): serialized = bytes((0xff, 0xfe)) text = serialized.decode('iso-8859-1') try: univ.OctetString(text, encoding='us-ascii') except PyAsn1UnicodeEncodeError: pass def testDecodeError(self): serialized = bytes((0xff, 0xfe)) octetString = univ.OctetString(serialized, encoding='us-ascii') try: str(octetString) except PyAsn1UnicodeDecodeError: pass class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (208, 176, 208, 177, 208, 178) encoding = 'utf-8' class OctetStringWithUtf16TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (4, 48, 4, 49, 4, 50) encoding = 'utf-16-be' class OctetStringWithUtf32TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (0, 0, 4, 48, 0, 0, 4, 49, 0, 0, 4, 50) encoding = 'utf-32-be' class OctetStringTestCase(BaseTestCase): def testBinDefault(self): class BinDefault(univ.OctetString): defaultBinValue = '1000010111101110101111000000111011' assert BinDefault() == univ.OctetString(binValue='1000010111101110101111000000111011') def testHexDefault(self): class HexDefault(univ.OctetString): defaultHexValue = 'FA9823C43E43510DE3422' assert HexDefault() == univ.OctetString(hexValue='FA9823C43E43510DE3422') def testBinStr(self): assert univ.OctetString(binValue="1000010111101110101111000000111011") == bytes((133, 238, 188, 14, 192)), 'bin init fails' def testHexStr(self): assert univ.OctetString(hexValue="FA9823C43E43510DE3422") == bytes((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)), 'hex init fails' def testTuple(self): assert univ.OctetString((1, 2, 3, 4, 5)) == bytes((1, 2, 3, 4, 5)), 'tuple init failed' def testRepr(self): assert 'abc' in repr(univ.OctetString('abc')) def testEmpty(self): try: str(univ.OctetString()) except PyAsn1Error: pass else: assert 0, 'empty OctetString() not reported' def testTag(self): assert univ.OctetString().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x04) ) def testStaticDef(self): class OctetString(univ.OctetString): pass assert OctetString(hexValue="FA9823C43E43510DE3422") == bytes((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)) class OctetStringPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.BitString() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.BitString assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.BitString((1, 0, 1, 0)) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == (1, 0, 1, 0) class Null(BaseTestCase): def testInit(self): assert not univ.Null().isValue assert univ.Null(0) == b'' assert univ.Null(False) == b'' assert univ.Null('') == b'' assert univ.Null(None) == b'' try: assert univ.Null(True) except PyAsn1Error: pass try: assert univ.Null('xxx') except PyAsn1Error: pass def testStr(self): assert str(univ.Null('')) == '', 'str() fails' def testRepr(self): assert 'Null' in repr(univ.Null('')) def testTag(self): assert univ.Null().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x05) ) def testConstraints(self): try: univ.Null(2) except error.ValueConstraintError: pass else: assert 0, 'constraint fail' def testStaticDef(self): class Null(univ.Null): pass assert not Null('') class NullPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Null() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Null assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Null('') serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert not new_asn1 class RealTestCase(BaseTestCase): def testFloat4BinEnc(self): assert univ.Real((0.25, 2, 3)) == 2.0, 'float initializer for binary encoding fails' def testStr(self): assert str(univ.Real(1.0)) == '1.0', 'str() fails' def testRepr(self): assert 'Real' in repr(univ.Real(-4.1)) assert 'Real' in repr(univ.Real(-4.1)) assert 'inf' in repr(univ.Real('inf')) assert '-inf' in repr(univ.Real('-inf')) def testAdd(self): assert univ.Real(-4.1) + 1.4 == -2.7, '__add__() fails' def testRadd(self): assert 4 + univ.Real(0.5) == 4.5, '__radd__() fails' def testSub(self): assert univ.Real(3.9) - 1.7 == 2.2, '__sub__() fails' def testRsub(self): assert 6.1 - univ.Real(0.1) == 6, '__rsub__() fails' def testMul(self): assert univ.Real(3.0) * -3 == -9, '__mul__() fails' def testRmul(self): assert 2 * univ.Real(3.0) == 6, '__rmul__() fails' def testDiv(self): assert univ.Real(3.0) / 2 == 1.5, '__div__() fails' def testRdiv(self): assert 6 / univ.Real(3.0) == 2, '__rdiv__() fails' def testMod(self): assert univ.Real(3.0) % 2 == 1, '__mod__() fails' def testRmod(self): assert 4 % univ.Real(3.0) == 1, '__rmod__() fails' def testPow(self): assert univ.Real(3.0) ** 2 == 9, '__pow__() fails' def testRpow(self): assert 2 ** univ.Real(2.0) == 4, '__rpow__() fails' def testInt(self): assert int(univ.Real(3.0)) == 3, '__int__() fails' def testLong(self): assert int(univ.Real(8.0)) == 8, '__long__() fails' def testFloat(self): assert float(univ.Real(4.0)) == 4.0, '__float__() fails' def testPrettyIn(self): assert univ.Real((3, 10, 0)) == 3, 'prettyIn() fails' # infinite float values def testStrInf(self): assert str(univ.Real('inf')) == 'inf', 'str() fails' def testAddInf(self): assert univ.Real('inf') + 1 == float('inf'), '__add__() fails' def testRaddInf(self): assert 1 + univ.Real('inf') == float('inf'), '__radd__() fails' def testIntInf(self): try: assert int(univ.Real('inf')) except OverflowError: pass else: assert 0, '__int__() fails' def testLongInf(self): try: assert int(univ.Real('inf')) except OverflowError: pass else: assert 0, '__long__() fails' assert int(univ.Real(8.0)) == 8, '__long__() fails' def testFloatInf(self): assert float(univ.Real('-inf')) == float('-inf'), '__float__() fails' def testPrettyInInf(self): assert univ.Real(float('inf')) == float('inf'), 'prettyIn() fails' def testPlusInf(self): assert univ.Real('inf').isPlusInf, 'isPlusInfinity failed' def testMinusInf(self): assert univ.Real('-inf').isMinusInf, 'isMinusInfinity failed' def testPos(self): assert +univ.Real(1.0) == 1.0, '__pos__() fails' def testNeg(self): assert -univ.Real(1.0) == -1.0, '__neg__() fails' def testRound(self): assert round(univ.Real(1.123), 2) == 1.12, '__round__() fails' def testFloor(self): assert math.floor(univ.Real(1.6)) == 1.0, '__floor__() fails' def testCeil(self): assert math.ceil(univ.Real(1.2)) == 2.0, '__ceil__() fails' def testTrunc(self): assert math.trunc(univ.Real(1.1)) == 1.0, '__trunc__() fails' def testTag(self): assert univ.Real().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x09) ) def testStaticDef(self): class Real(univ.Real): pass assert Real(1.0) == 1.0 class RealPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Real() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Real assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Real((1, 10, 3)) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == 1000 class ObjectIdentifier(BaseTestCase): def testStr(self): assert str(univ.ObjectIdentifier((1, 3, 6))) == '1.3.6', 'str() fails' def testRepr(self): assert '1.3.6' in repr(univ.ObjectIdentifier('1.3.6')) def testEq(self): assert univ.ObjectIdentifier((1, 3, 6)) == (1, 3, 6), '__cmp__() fails' def testAdd(self): assert univ.ObjectIdentifier((1, 3)) + (6,) == (1, 3, 6), '__add__() fails' def testRadd(self): assert (1,) + univ.ObjectIdentifier((3, 6)) == (1, 3, 6), '__radd__() fails' def testLen(self): assert len(univ.ObjectIdentifier((1, 3))) == 2, '__len__() fails' def testPrefix(self): o = univ.ObjectIdentifier('1.3.6') assert o.isPrefixOf((1, 3, 6)), 'isPrefixOf() fails' assert o.isPrefixOf((1, 3, 6, 1)), 'isPrefixOf() fails' assert not o.isPrefixOf((1, 3)), 'isPrefixOf() fails' def testInput1(self): assert univ.ObjectIdentifier('1.3.6') == (1, 3, 6), 'prettyIn() fails' def testInput2(self): assert univ.ObjectIdentifier((1, 3, 6)) == (1, 3, 6), 'prettyIn() fails' def testInput3(self): assert univ.ObjectIdentifier(univ.ObjectIdentifier('1.3') + (6,)) == (1, 3, 6), 'prettyIn() fails' def testUnicode(self): s = '1.3.6' assert univ.ObjectIdentifier(s) == (1, 3, 6), 'unicode init fails' def testTag(self): assert univ.ObjectIdentifier().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x06) ) def testContains(self): s = univ.ObjectIdentifier('1.3.6.1234.99999') assert 1234 in s assert 4321 not in s def testStaticDef(self): class ObjectIdentifier(univ.ObjectIdentifier): pass assert str(ObjectIdentifier((1, 3, 6))) == '1.3.6' class ObjectIdentifierPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.ObjectIdentifier() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.ObjectIdentifier assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.ObjectIdentifier('2.3.1.1.2') serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == (2, 3, 1, 1, 2) class RelativeOID(BaseTestCase): def testStr(self): assert str(univ.RelativeOID((1, 3, 6))) == '1.3.6', 'str() fails' def testRepr(self): assert '1.3.6' in repr(univ.RelativeOID('1.3.6')) def testEq(self): assert univ.RelativeOID((1, 3, 6)) == (1, 3, 6), '__cmp__() fails' def testAdd(self): assert univ.RelativeOID((1, 3)) + (6,) == (1, 3, 6), '__add__() fails' def testRadd(self): assert (1,) + univ.RelativeOID((3, 6)) == (1, 3, 6), '__radd__() fails' def testLen(self): assert len(univ.RelativeOID((1, 3))) == 2, '__len__() fails' def testPrefix(self): o = univ.RelativeOID('1.3.6') assert o.isPrefixOf((1, 3, 6)), 'isPrefixOf() fails' assert o.isPrefixOf((1, 3, 6, 1)), 'isPrefixOf() fails' assert not o.isPrefixOf((1, 3)), 'isPrefixOf() fails' def testInput1(self): assert univ.RelativeOID('1.3.6') == (1, 3, 6), 'prettyIn() fails' def testInput2(self): assert univ.RelativeOID((1, 3, 6)) == (1, 3, 6), 'prettyIn() fails' def testInput3(self): assert univ.RelativeOID(univ.RelativeOID('1.3') + (6,)) == (1, 3, 6), 'prettyIn() fails' def testUnicode(self): s = '1.3.6' assert univ.RelativeOID(s) == (1, 3, 6), 'unicode init fails' def testTag(self): assert univ.RelativeOID().tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 0x0d) ) def testContains(self): s = univ.RelativeOID('1.3.6.1234.99999') assert 1234 in s assert 4321 not in s def testStaticDef(self): class RelOID(univ.ObjectIdentifier): pass assert str(RelOID((1, 3, 6))) == '1.3.6' class RelativeOIDPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.RelativeOID() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.RelativeOID assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.RelativeOID('2.3.1.1.2') serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == (2, 3, 1, 1, 2) class SequenceOf(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s1 = univ.SequenceOf( componentType=univ.OctetString('') ) self.s2 = self.s1.clone() def testRepr(self): assert 'a' in repr(self.s1.clone().setComponents('a', 'b')) def testTag(self): assert self.s1.tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) ), 'wrong tagSet' def testSeq(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) assert self.s1[0] == b'abc', 'set by idx fails' self.s1[0] = 'cba' assert self.s1[0] == b'cba', 'set by idx fails' def testCmp(self): self.s1.clear() self.s1.setComponentByPosition(0, 'abc') self.s2.clear() self.s2.setComponentByPosition(0, univ.OctetString('abc')) assert self.s1 == self.s2, '__cmp__() fails' def testSubtypeSpec(self): s = self.s1.clone( componentType=univ.OctetString().subtype( subtypeSpec=constraint.SingleValueConstraint(b'abc'))) try: s.setComponentByPosition( 0, univ.OctetString().subtype( 'abc', subtypeSpec=constraint.SingleValueConstraint(b'abc'))) except PyAsn1Error: assert 0, 'constraint fails' try: s.setComponentByPosition(1, univ.OctetString('Abc')) except PyAsn1Error: try: s.setComponentByPosition(1, univ.OctetString('Abc'), verifyConstraints=False) except PyAsn1Error: assert 0, 'constraint fails with verifyConstraints=False' else: assert 0, 'constraint fails' def testComponentTagsMatching(self): s = self.s1.clone() s.strictConstraints = True # This requires types equality o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12)) try: s.setComponentByPosition(0, o) except PyAsn1Error: pass else: assert 0, 'inner supertype tag allowed' def testComponentConstraintsMatching(self): s = self.s1.clone() o = univ.OctetString().subtype( subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(b'cba'))) s.strictConstraints = True # This requires types equality try: s.setComponentByPosition(0, o.clone('cba')) except PyAsn1Error: pass else: assert 0, 'inner supertype constraint allowed' s.strictConstraints = False # This requires subtype relationships try: s.setComponentByPosition(0, o.clone('cba')) except PyAsn1Error: assert 0, 'inner supertype constraint disallowed' else: pass def testConsistency(self): s = self.s1.clone(subtypeSpec=constraint.ConstraintsUnion( constraint.ValueSizeConstraint(1, 1) )) s.setComponentByPosition(0, univ.OctetString('abc')) assert not s.isInconsistent, 'size spec fails' s.setComponentByPosition(1, univ.OctetString('abc')) assert s.isInconsistent, 'size spec fails' def testGetComponentTagMap(self): assert self.s1.componentType.tagMap.presentTypes == { univ.OctetString.tagSet: univ.OctetString('') } def testSubtype(self): subtype = self.s1.subtype( implicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2), subtypeSpec=constraint.ValueSizeConstraint(0, 1) ) subtype.clear() clone = self.s1.clone( tagSet=tag.TagSet(tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 2)), subtypeSpec=constraint.ValueSizeConstraint(0, 1) ) clone.clear() assert clone == subtype def testClone(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) s = self.s1.clone() s.clear() assert len(s) == 0 s = self.s1.clone(cloneValueFlag=1) assert len(s) == 1 assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) def testSetComponents(self): assert self.s1.clone().setComponents('abc', 'def') == \ self.s1.setComponentByPosition(0, 'abc').setComponentByPosition(1, 'def') def testGetItem(self): s = self.s1.clone() s.append('xxx') assert s[0] # this is a deviation from standard sequence protocol assert not s[2] def testGetItemSlice(self): s = self.s1.clone() s.extend(['xxx', 'yyy', 'zzz']) assert s[:1] == [b'xxx'] assert s[-2:] == [b'yyy', b'zzz'] assert s[1:2] == [b'yyy'] def testSetItem(self): s = self.s1.clone() s.append('xxx') s[2] = 'yyy' assert len(s) == 3 assert s[1] == b'' def testSetItemSlice(self): s = self.s1.clone() s[:1] = ['xxx'] assert s == [b'xxx'] s[-2:] = ['yyy', 'zzz'] assert s == [b'yyy', b'zzz'] s[1:2] = ['yyy'] assert s == [b'yyy', b'yyy'] assert len(s) == 2 def testAppend(self): self.s1.clear() self.s1.setComponentByPosition(0, univ.OctetString('abc')) assert len(self.s1) == 1 self.s1.append('def') assert len(self.s1) == 2 assert list(self.s1) == [b'abc', b'def'] def testExtend(self): self.s1.clear() self.s1.setComponentByPosition(0, univ.OctetString('abc')) assert len(self.s1) == 1 self.s1.extend(['def', 'ghi']) assert len(self.s1) == 3 assert list(self.s1) == [b'abc', b'def', b'ghi'] def testCount(self): self.s1.clear() for x in ['abc', 'def', 'abc']: self.s1.append(x) assert self.s1.count(b'abc') == 2 assert self.s1.count(b'def') == 1 assert self.s1.count(b'ghi') == 0 def testIndex(self): self.s1.clear() for x in ['abc', 'def', 'abc']: self.s1.append(x) assert self.s1.index(b'abc') == 0 assert self.s1.index(b'def') == 1 assert self.s1.index(b'abc', 1) == 2 def testSort(self): self.s1.clear() self.s1[0] = 'b' self.s1[1] = 'a' assert list(self.s1) == [b'b', b'a'] self.s1.sort() assert list(self.s1) == [b'a', b'b'] def testStaticDef(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString('') s = SequenceOf() s[0] = 'abc' assert len(s) == 1 assert s == [b'abc'] def testUntyped(self): n = univ.SequenceOf() assert not n.isValue n[0] = univ.OctetString('fox') assert n.isValue def testLegacyInitializer(self): n = univ.SequenceOf( componentType=univ.OctetString() ) o = univ.SequenceOf( univ.OctetString() # this is the old way ) assert n.isSameTypeWith(o) and o.isSameTypeWith(n) n[0] = 'fox' o[0] = 'fox' assert n == o def testGetComponentWithDefault(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString() s = SequenceOf() assert s.getComponentByPosition(0, default=None, instantiate=False) is None assert s.getComponentByPosition(0, default=None) is None s[0] = 'test' assert s.getComponentByPosition(0, default=None) is not None assert s.getComponentByPosition(0, default=None) == b'test' s.clear() assert s.getComponentByPosition(0, default=None) is None def testGetComponentNoInstantiation(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString() s = SequenceOf() assert s.getComponentByPosition(0, instantiate=False) is univ.noValue s[0] = 'test' assert s.getComponentByPosition(0, instantiate=False) is not univ.noValue assert s.getComponentByPosition(0, instantiate=False) == b'test' s.clear() assert s.getComponentByPosition(0, instantiate=False) is univ.noValue def testClear(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString() s = SequenceOf() s.setComponentByPosition(0, 'test') assert s.getComponentByPosition(0) == b'test' assert len(s) == 1 assert s.isValue s.clear() assert len(s) == 0 assert s == [] assert s.isValue def testReset(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString() s = SequenceOf() s.setComponentByPosition(0, 'test') assert s.getComponentByPosition(0) == b'test' assert s.isValue s.reset() assert not s.isValue def testIsInconsistentSizeConstraint(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString() subtypeSpec = constraint.ValueSizeConstraint(0, 1) s = SequenceOf() assert s.isInconsistent s[0] = 'test' assert not s.isInconsistent s[0] = 'test' s[1] = 'test' assert s.isInconsistent s.clear() assert not s.isInconsistent s.reset() assert s.isInconsistent s[1] = 'test' assert not s.isInconsistent class SequenceOfPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.SequenceOf(componentType=univ.OctetString()) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.SequenceOf assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.SequenceOf(componentType=univ.OctetString()) old_asn1[0] = 'test' serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 assert new_asn1 == [b'test'] class Sequence(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('nick', univ.OctetString('')), namedtype.DefaultedNamedType('age', univ.Integer(34)) ) ) def testRepr(self): assert 'name' in repr(self.s1.clone().setComponents('a', 'b')) def testTag(self): assert self.s1.tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x10) ), 'wrong tagSet' def testById(self): self.s1.setComponentByName('name', univ.OctetString('abc')) assert self.s1.getComponentByName('name') == b'abc', 'set by name fails' def testByKey(self): self.s1['name'] = 'abc' assert self.s1['name'] == b'abc', 'set by key fails' def testContains(self): assert 'name' in self.s1 assert '' not in self.s1 def testGetNearPosition(self): assert self.s1.componentType.getTagMapNearPosition(1).presentTypes == { univ.OctetString.tagSet: univ.OctetString(''), univ.Integer.tagSet: univ.Integer(34) } assert self.s1.componentType.getPositionNearType( univ.OctetString.tagSet, 1 ) == 1 def testSetDefaultComponents(self): self.s1.clear() self.s1.setComponentByPosition(0, univ.OctetString('Ping')) self.s1.setComponentByPosition(1, univ.OctetString('Pong')) assert self.s1.getComponentByPosition(2) == 34 def testClone(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) self.s1.setComponentByPosition(1, univ.OctetString('def')) self.s1.setComponentByPosition(2, univ.Integer(123)) s = self.s1.clone() assert s.getComponentByPosition(0) != self.s1.getComponentByPosition(0) assert s.getComponentByPosition(1) != self.s1.getComponentByPosition(1) assert s.getComponentByPosition(2) != self.s1.getComponentByPosition(2) s = self.s1.clone(cloneValueFlag=1) assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) assert s.getComponentByPosition(1) == self.s1.getComponentByPosition(1) assert s.getComponentByPosition(2) == self.s1.getComponentByPosition(2) def testComponentTagsMatching(self): s = self.s1.clone() s.strictConstraints = True # This requires types equality o = univ.OctetString('abc').subtype(explicitTag=tag.Tag(tag.tagClassPrivate, tag.tagFormatSimple, 12)) try: s.setComponentByName('name', o) except PyAsn1Error: pass else: assert 0, 'inner supertype tag allowed' def testComponentConstraintsMatching(self): s = self.s1.clone() o = univ.OctetString().subtype( subtypeSpec=constraint.ConstraintsUnion(constraint.SingleValueConstraint(b'cba'))) s.strictConstraints = True # This requires types equality try: s.setComponentByName('name', o.clone('cba')) except PyAsn1Error: pass else: assert 0, 'inner supertype constraint allowed' s.strictConstraints = False # This requires subtype relationships try: s.setComponentByName('name', o.clone('cba')) except PyAsn1Error: assert 0, 'inner supertype constraint disallowed' else: pass def testSetComponents(self): assert self.s1.clone().setComponents(name='a', nick='b', age=1) == \ self.s1.setComponentByPosition(0, 'a').setComponentByPosition(1, 'b').setComponentByPosition(2, 1) def testSetToDefault(self): s = self.s1.clone() s.setComponentByPosition(0, univ.noValue) s[2] = univ.noValue assert s[0] == univ.OctetString('') assert s[2] == univ.Integer(34) def testGetItem(self): s = self.s1.clone() s['name'] = 'xxx' assert s['name'] assert s[0] try: s['xxx'] except KeyError: pass else: assert False, 'KeyError not raised' try: s[100] except IndexError: pass else: assert False, 'IndexError not raised' def testSetItem(self): s = self.s1.clone() s['name'] = 'xxx' try: s['xxx'] = 'xxx' except KeyError: pass else: assert False, 'KeyError not raised' try: s[100] = 'xxx' except IndexError: pass else: assert False, 'IndexError not raised' def testIter(self): assert list(self.s1) == ['name', 'nick', 'age'] def testKeys(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) self.s1.setComponentByPosition(1, univ.OctetString('def')) self.s1.setComponentByPosition(2, univ.Integer(123)) assert list(self.s1.keys()) == ['name', 'nick', 'age'] def testValues(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) self.s1.setComponentByPosition(1, univ.OctetString('def')) self.s1.setComponentByPosition(2, univ.Integer(123)) assert list(self.s1.values()) == [b'abc', b'def', 123] def testItems(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) self.s1.setComponentByPosition(1, univ.OctetString('def')) self.s1.setComponentByPosition(2, univ.Integer(123)) assert list(self.s1.items()) == [('name', b'abc'), ('nick', b'def'), ('age', 123)] def testUpdate(self): self.s1.clear() assert list(self.s1.values()) == [b'', b'', 34] self.s1.update(**{'name': 'abc', 'nick': 'def', 'age': 123}) assert list(self.s1.items()) == [('name', b'abc'), ('nick', b'def'), ('age', 123)] self.s1.update(('name', 'ABC')) assert list(self.s1.items()) == [('name', b'ABC'), ('nick', b'def'), ('age', 123)] self.s1.update(name='CBA') assert list(self.s1.items()) == [('name', b'CBA'), ('nick', b'def'), ('age', 123)] def testStaticDef(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('nick', univ.OctetString('')), namedtype.DefaultedNamedType('age', univ.Integer(34)) ) s = Sequence() s['name'] = 'abc' assert s['name'] == b'abc' def testGetComponentWithDefault(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('nick', univ.OctetString()), ) s = Sequence() assert s[0] == b'' assert s.getComponentByPosition(1, default=None, instantiate=False) is None assert s.getComponentByName('nick', default=None) is None s[1] = 'test' assert s.getComponentByPosition(1, default=None) is not None assert s.getComponentByPosition(1, default=None) == b'test' s.clear() assert s.getComponentByPosition(1, default=None) is None def testGetComponentWithConstructedDefault(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.DefaultedNamedType('nick', univ.SequenceOf( componentType=univ.Integer() ).setComponentByPosition(0, 1)), ) s = Sequence() assert s.getComponentByPosition(1, default=None, instantiate=False) is None assert s.getComponentByPosition(1, instantiate=False) is univ.noValue assert s.getComponentByPosition(1) == [1] def testGetComponentNoInstantiation(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('nick', univ.OctetString()), ) s = Sequence() assert s[0] == b'' assert s.getComponentByPosition(1, instantiate=False) is univ.noValue assert s.getComponentByName('nick', instantiate=False) is univ.noValue s[1] = 'test' assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue assert s.getComponentByPosition(1, instantiate=False) == b'test' s.clear() assert s.getComponentByPosition(1, instantiate=False) is univ.noValue def testSchemaWithComponents(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()) ) s = Sequence() assert not s.isValue s[0] = 'test' assert s.isValue s.clear() assert not s.isValue s.reset() assert not s.isValue def testSchemaWithOptionalComponents(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.DefaultedNamedType('name', univ.OctetString('')) ) s = Sequence() assert s.isValue s[0] = 'test' assert s.isValue s.clear() assert s.isValue s.reset() assert not s.isValue def testIsInconsistentWithComponentsConstraint(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.OptionalNamedType('name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(65)) ) subtypeSpec = constraint.WithComponentsConstraint( ('name', constraint.ComponentPresentConstraint()), ('age', constraint.ComponentAbsentConstraint()) ) s = Sequence() assert s.isInconsistent s[0] = 'test' assert not s.isInconsistent s[0] = 'test' s[1] = 23 assert s.isInconsistent s.clear() assert s.isInconsistent s.reset() assert s.isInconsistent s[1] = 23 assert s.isInconsistent def testIsInconsistentSizeConstraint(self): class Sequence(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.OptionalNamedType('name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(65)) ) subtypeSpec = constraint.ValueSizeConstraint(0, 1) s = Sequence() assert not s.isInconsistent s[0] = 'test' assert not s.isInconsistent s[0] = 'test' s[1] = 23 assert s.isInconsistent s.clear() assert not s.isInconsistent s.reset() assert s.isInconsistent s[1] = 23 assert not s.isInconsistent class SequenceWithoutSchema(BaseTestCase): def testGetItem(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s[0] = 'abc' assert s['field-0'] assert s[0] try: s['field-1'] except KeyError: pass else: assert False, 'KeyError not raised' def testSetItem(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s['field-0'] = 'xxx' try: s['field-1'] = 'xxx' except KeyError: pass else: assert False, 'KeyError not raised' def testIter(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s.setComponentByPosition(1, univ.Integer(123)) assert list(s) == ['field-0', 'field-1'] def testKeys(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s.setComponentByPosition(1, univ.Integer(123)) assert list(s.keys()) == ['field-0', 'field-1'] def testValues(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s.setComponentByPosition(1, univ.Integer(123)) assert list(s.values()) == [b'abc', 123] def testItems(self): s = univ.Sequence() s.setComponentByPosition(0, univ.OctetString('abc')) s.setComponentByPosition(1, univ.Integer(123)) assert list(s.items()) == [('field-0', b'abc'), ('field-1', 123)] def testUpdate(self): s = univ.Sequence().clear() assert not s s.setComponentByPosition(0, univ.OctetString('abc')) s.setComponentByPosition(1, univ.Integer(123)) assert s assert list(s.keys()) == ['field-0', 'field-1'] assert list(s.values()) == [b'abc', 123] assert list(s.items()) == [('field-0', b'abc'), ('field-1', 123)] s['field-0'] = univ.OctetString('def') assert list(s.values()) == [b'def', 123] s['field-1'] = univ.OctetString('ghi') assert list(s.values()) == [b'def', b'ghi'] try: s['field-2'] = univ.OctetString('xxx') except KeyError: pass else: assert False, 'unknown field at schema-less object tolerated' assert 'field-0' in s s.clear() assert 'field-0' not in s def testSchema(self): class Sequence(univ.Sequence): pass s = Sequence() assert not s.isValue s[0] = univ.OctetString('test') assert s.isValue s.clear() assert s.isValue s.reset() assert not s.isValue class SequencePicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()) ) ) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Sequence assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()) ) ) old_asn1['name'] = 'test' serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 assert new_asn1['name'] == b'test' class SetOf(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s1 = univ.SetOf(componentType=univ.OctetString('')) def testTag(self): assert self.s1.tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) ), 'wrong tagSet' def testSeq(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) assert self.s1[0] == b'abc', 'set by idx fails' self.s1.setComponentByPosition(0, self.s1[0].clone('cba')) assert self.s1[0] == b'cba', 'set by idx fails' def testStaticDef(self): class SetOf(univ.SequenceOf): componentType = univ.OctetString('') s = SetOf() s[0] = 'abc' assert len(s) == 1 assert s == [b'abc'] class SetOfPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.SetOf(componentType=univ.OctetString()) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.SetOf assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.SetOf(componentType=univ.OctetString()) old_asn1[0] = 'test' serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 assert new_asn1 == [b'test'] class Set(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s1 = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('null', univ.Null('')), namedtype.DefaultedNamedType('age', univ.Integer(34)) ) ) self.s2 = self.s1.clone() def testTag(self): assert self.s1.tagSet == tag.TagSet( (), tag.Tag(tag.tagClassUniversal, tag.tagFormatConstructed, 0x11) ), 'wrong tagSet' def testByTypeWithPythonValue(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert self.s1.getComponentByType( univ.OctetString.tagSet ) == b'abc', 'set by name fails' def testByTypeWithInstance(self): self.s1.setComponentByType(univ.OctetString.tagSet, univ.OctetString('abc')) assert self.s1.getComponentByType( univ.OctetString.tagSet ) == b'abc', 'set by name fails' def testGetTagMap(self): assert self.s1.tagMap.presentTypes == { univ.Set.tagSet: univ.Set().clear() } def testGetComponentTagMap(self): assert self.s1.componentType.tagMapUnique.presentTypes == { univ.OctetString.tagSet: univ.OctetString(''), univ.Null.tagSet: univ.Null(''), univ.Integer.tagSet: univ.Integer(34) } def testGetPositionByType(self): assert self.s1.componentType.getPositionByType(univ.Null().tagSet) == 1 def testSetToDefault(self): self.s1.setComponentByName('name', univ.noValue) assert self.s1['name'] == univ.OctetString('') def testIter(self): assert list(self.s1) == ['name', 'null', 'age'] def testStaticDef(self): class Set(univ.Set): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString('')), namedtype.OptionalNamedType('nick', univ.OctetString('')), namedtype.DefaultedNamedType('age', univ.Integer(34)) ) s = Set() s['name'] = 'abc' assert s['name'] == b'abc' def testGetComponentWithDefault(self): class Set(univ.Set): componentType = namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer(123)), namedtype.OptionalNamedType('nick', univ.OctetString()), ) s = Set() assert s[0] == 123 assert s.getComponentByPosition(1, default=None, instantiate=False) is None assert s.getComponentByName('nick', default=None) is None s[1] = 'test' assert s.getComponentByPosition(1, default=None) is not None assert s.getComponentByPosition(1, default=None) == b'test' s.clear() assert s.getComponentByPosition(1, default=None) is None def testGetComponentNoInstantiation(self): class Set(univ.Set): componentType = namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer(123)), namedtype.OptionalNamedType('nick', univ.OctetString()), ) s = Set() assert s[0] == 123 assert s.getComponentByPosition(1, instantiate=False) is univ.noValue assert s.getComponentByName('nick', instantiate=False) is univ.noValue assert s.getComponentByType(univ.OctetString.tagSet, instantiate=False) is univ.noValue s[1] = 'test' assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue assert s.getComponentByPosition(1, instantiate=False) == b'test' s.clear() assert s.getComponentByPosition(1, instantiate=False) is univ.noValue class SetPicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()) ) ) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Set assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()) ) ) old_asn1['name'] = 'test' serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 assert new_asn1['name'] == b'test' class Choice(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) innerComp = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('count', univ.Integer()), namedtype.NamedType('flag', univ.Boolean()) ) ) self.s1 = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('sex', innerComp) ) ) def testTag(self): assert self.s1.tagSet == tag.TagSet(), 'wrong tagSet' def testRepr(self): assert 'Choice' in repr(self.s1.clone().setComponents('a')) s = self.s1.clone().setComponents( sex=self.s1.setComponentByPosition(1).getComponentByPosition(1).clone().setComponents(count=univ.Integer(123)) ) assert 'Choice' in repr(s) def testContains(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert 'name' in self.s1 assert 'sex' not in self.s1 self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) assert 'name' not in self.s1 assert 'sex' in self.s1 def testIter(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert list(self.s1) == ['name'] self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) assert list(self.s1) == ['sex'] def testOuterByTypeWithPythonValue(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert self.s1.getComponentByType( univ.OctetString.tagSet ) == b'abc' def testOuterByTypeWithInstanceValue(self): self.s1.setComponentByType( univ.OctetString.tagSet, univ.OctetString('abc') ) assert self.s1.getComponentByType( univ.OctetString.tagSet ) == b'abc' def testInnerByTypeWithPythonValue(self): self.s1.setComponentByType(univ.Integer.tagSet, 123, innerFlag=True) assert self.s1.getComponentByType( univ.Integer.tagSet, 1 ) == 123 def testInnerByTypeWithInstanceValue(self): self.s1.setComponentByType( univ.Integer.tagSet, univ.Integer(123), innerFlag=True ) assert self.s1.getComponentByType( univ.Integer.tagSet, 1 ) == 123 def testCmp(self): self.s1.setComponentByName('name', univ.OctetString('abc')) assert self.s1 == b'abc', '__cmp__() fails' def testGetComponent(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert self.s1.getComponent() == b'abc', 'getComponent() fails' def testGetName(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert self.s1.getName() == 'name', 'getName() fails' def testSetComponentByPosition(self): self.s1.setComponentByPosition(0, univ.OctetString('Jim')) assert self.s1 == b'Jim' def testClone(self): self.s1.setComponentByPosition(0, univ.OctetString('abc')) s = self.s1.clone() assert len(s) == 0 s = self.s1.clone(cloneValueFlag=1) assert len(s) == 1 assert s.getComponentByPosition(0) == self.s1.getComponentByPosition(0) def testSetToDefault(self): s = self.s1.clone() s.setComponentByName('sex', univ.noValue) assert s['sex'] is not univ.noValue def testStaticDef(self): class InnerChoice(univ.Choice): componentType = namedtype.NamedTypes( namedtype.NamedType('count', univ.Integer()), namedtype.NamedType('flag', univ.Boolean()) ) class OuterChoice(univ.Choice): componentType = namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('sex', InnerChoice()) ) c = OuterChoice() c.setComponentByType(univ.OctetString.tagSet, 'abc') assert c.getName() == 'name' def testGetComponentWithDefault(self): s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('id', univ.Integer()) ) ) assert s.getComponentByPosition(0, default=None, instantiate=False) is None assert s.getComponentByPosition(1, default=None, instantiate=False) is None assert s.getComponentByName('name', default=None, instantiate=False) is None assert s.getComponentByName('id', default=None, instantiate=False) is None assert s.getComponentByType(univ.OctetString.tagSet, default=None) is None assert s.getComponentByType(univ.Integer.tagSet, default=None) is None s[1] = 123 assert s.getComponentByPosition(1, default=None) is not None assert s.getComponentByPosition(1, univ.noValue) == 123 s.clear() assert s.getComponentByPosition(1, default=None, instantiate=False) is None def testGetComponentNoInstantiation(self): s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('id', univ.Integer()) ) ) assert s.getComponentByPosition(0, instantiate=False) is univ.noValue assert s.getComponentByPosition(1, instantiate=False) is univ.noValue assert s.getComponentByName('name', instantiate=False) is univ.noValue assert s.getComponentByName('id', instantiate=False) is univ.noValue assert s.getComponentByType(univ.OctetString.tagSet, instantiate=False) is univ.noValue assert s.getComponentByType(univ.Integer.tagSet, instantiate=False) is univ.noValue s[1] = 123 assert s.getComponentByPosition(1, instantiate=False) is not univ.noValue assert s.getComponentByPosition(1, instantiate=False) == 123 s.clear() assert s.getComponentByPosition(1, instantiate=False) is univ.noValue class ChoicePicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('id', univ.Integer()) ) ) serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == univ.Choice assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('id', univ.Integer()) ) ) old_asn1['name'] = 'test' serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 assert new_asn1['name'] == b'test' suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1700087185.0 pyasn1-0.6.1/tests/type/test_useful.py0000644000175000017500000001117314525242621020246 0ustar00spichugispichugi# # This file is part of pyasn1 software. # # Copyright (c) 2005-2020, Ilya Etingof # License: https://pyasn1.readthedocs.io/en/latest/license.html # import datetime import pickle import sys from copy import deepcopy import unittest from tests.base import BaseTestCase from pyasn1.type import useful class FixedOffset(datetime.tzinfo): def __init__(self, offset, name): self.__offset = datetime.timedelta(minutes=offset) self.__name = name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return datetime.timedelta(0) UTC = FixedOffset(0, 'UTC') UTC2 = FixedOffset(120, 'UTC') class ObjectDescriptorTestCase(BaseTestCase): pass class GeneralizedTimeTestCase(BaseTestCase): def testFromDateTime(self): assert useful.GeneralizedTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC)) == '20170711000102.3Z' def testToDateTime0(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2) == useful.GeneralizedTime('20170711000102').asDateTime def testToDateTime1(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.GeneralizedTime('20170711000102Z').asDateTime def testToDateTime2(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102.3Z').asDateTime def testToDateTime3(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102,3Z').asDateTime def testToDateTime4(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC) == useful.GeneralizedTime('20170711000102.3+0000').asDateTime def testToDateTime5(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC2) == useful.GeneralizedTime('20170711000102.3+0200').asDateTime def testToDateTime6(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, 3000, tzinfo=UTC2) == useful.GeneralizedTime('20170711000102.3+02').asDateTime def testToDateTime7(self): assert datetime.datetime(2017, 7, 11, 0, 1) == useful.GeneralizedTime('201707110001').asDateTime def testToDateTime8(self): assert datetime.datetime(2017, 7, 11, 0) == useful.GeneralizedTime('2017071100').asDateTime def testCopy(self): dt = useful.GeneralizedTime("20170916234254+0130").asDateTime assert dt == deepcopy(dt) class GeneralizedTimePicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = useful.GeneralizedTime() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == useful.GeneralizedTime assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = useful.GeneralizedTime("20170916234254+0130") serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == old_asn1 class UTCTimeTestCase(BaseTestCase): def testFromDateTime(self): assert useful.UTCTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC)) == '170711000102Z' def testToDateTime0(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2) == useful.UTCTime('170711000102').asDateTime def testToDateTime1(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.UTCTime('170711000102Z').asDateTime def testToDateTime2(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC) == useful.UTCTime('170711000102+0000').asDateTime def testToDateTime3(self): assert datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC2) == useful.UTCTime('170711000102+0200').asDateTime def testToDateTime4(self): assert datetime.datetime(2017, 7, 11, 0, 1) == useful.UTCTime('1707110001').asDateTime class UTCTimePicklingTestCase(unittest.TestCase): def testSchemaPickling(self): old_asn1 = useful.UTCTime() serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert type(new_asn1) == useful.UTCTime assert old_asn1.isSameTypeWith(new_asn1) def testValuePickling(self): old_asn1 = useful.UTCTime("170711000102") serialised = pickle.dumps(old_asn1) assert serialised new_asn1 = pickle.loads(serialised) assert new_asn1 == old_asn1 suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite)