pyasn1-0.4.8/0000775006321400632140000000000013564027341014405 5ustar ietingofietingof00000000000000pyasn1-0.4.8/CHANGES.rst0000664006321400632140000010024513564027254016214 0ustar ietingofietingof00000000000000 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 pyasn1-0.4.8/LICENSE.rst0000644006321400632140000000246613551772544016237 0ustar ietingofietingof00000000000000Copyright (c) 2005-2019, 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. pyasn1-0.4.8/MANIFEST.in0000644006321400632140000000022213551772543016144 0ustar ietingofietingof00000000000000include *.rst *.md recursive-include tests *.py recursive-include docs Makefile *.rst *.svg conf.py prune docs/build prune docs/source/.templates pyasn1-0.4.8/PKG-INFO0000664006321400632140000000277313564027341015513 0ustar ietingofietingof00000000000000Metadata-Version: 1.2 Name: pyasn1 Version: 0.4.8 Summary: ASN.1 types and codecs Home-page: https://github.com/etingof/pyasn1 Author: Ilya Etingof Author-email: etingof@gmail.com Maintainer: Ilya Etingof License: BSD Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) 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 :: 2 Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Communications Classifier: Topic :: Software Development :: Libraries :: Python Modules pyasn1-0.4.8/README.md0000644006321400632140000001432313551772544015675 0ustar ietingofietingof00000000000000 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://travis-ci.org/etingof/pyasn1.svg?branch=master)](https://secure.travis-ci.org/etingof/pyasn1) [![Coverage Status](https://img.shields.io/codecov/c/github/etingof/pyasn1.svg)](https://codecov.io/github/etingof/pyasn1) [![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/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). Features -------- * Generic implementation of ASN.1 types (X.208) * Standards compliant BER/CER/DER codecs * Dumps/loads ASN.1 structures from Python types * 100% Python, works with Python 2.4 up to Python 3.7 * 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](http://snmplabs.com/pyasn1/), compiled ASN.1 modules for different protocols and file formats could be found in the pyasn1-modules [repo](https://github.com/etingof/pyasn1-modules). How to get pyasn1 ----------------- The pyasn1 package is distributed under terms and conditions of 2-clause BSD [license](http://snmplabs.com/pyasn1/license.html). Source code is freely available as a GitHub [repo](https://github.com/etingof/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/etingof/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-2019, [Ilya Etingof](mailto:etingof@gmail.com). All rights reserved. pyasn1-0.4.8/TODO.rst0000644006321400632140000000365713551772543015724 0ustar ietingofietingof00000000000000 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 pyasn1-0.4.8/docs/0000775006321400632140000000000013564027341015335 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/Makefile0000644006321400632140000001637213551772543017013 0ustar ietingofietingof00000000000000# 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." pyasn1-0.4.8/docs/source/0000775006321400632140000000000013564027341016635 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/.static/0000775006321400632140000000000013564027341020202 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/.static/logo.svg0000644006321400632140000003276313551772543021703 0ustar ietingofietingof00000000000000 pyasn1-0.4.8/docs/source/changelog.rst0000644006321400632140000000006613551772543021325 0ustar ietingofietingof00000000000000 Changelog ========= .. include:: ../../CHANGES.rst pyasn1-0.4.8/docs/source/conf.py0000644006321400632140000002454213551772543020150 0ustar ietingofietingof00000000000000# -*- 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('.')) # -- 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-2019, 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 = '0.4' # The full version, including alpha/beta/rc tags. release = '0.4' # 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 = None # 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.4/', 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 pyasn1-0.4.8/docs/source/contents.rst0000644006321400632140000001231513551772543021233 0ustar ietingofietingof00000000000000 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. pyasn1-0.4.8/docs/source/download.rst0000644006321400632140000000132213551772543021201 0ustar ietingofietingof00000000000000 Download & Install ================== The *pyasn1* library is a pure-Python package with no external dependencies. Considering how much industrial or finance software can be stuck with an old platform (think RHEL 5), we struggle to maintain its compatibility back to the very pre-historic Python (which is 2.4!). 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 `_. pyasn1-0.4.8/docs/source/example-use-case.rst0000644006321400632140000001437613551772543022545 0ustar ietingofietingof00000000000000 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) pyasn1-0.4.8/docs/source/license.rst0000644006321400632140000000007613551772543021021 0ustar ietingofietingof00000000000000.. _license: License ======= .. include:: ../../LICENSE.rst pyasn1-0.4.8/docs/source/pyasn1/0000775006321400632140000000000013564027341020050 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/0000775006321400632140000000000013564027341021125 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/ber/0000775006321400632140000000000013564027341021675 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/ber/contents.rst0000644006321400632140000000033713551772543024274 0ustar ietingofietingof00000000000000 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) pyasn1-0.4.8/docs/source/pyasn1/codec/cer/0000775006321400632140000000000013564027341021676 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/cer/contents.rst0000644006321400632140000000031113551772543024265 0ustar ietingofietingof00000000000000 Canonical Encoding Rules ------------------------ .. autofunction:: pyasn1.codec.cer.encoder.encode(value, asn1Spec=None) .. autofunction:: pyasn1.codec.cer.decoder.decode(substrate, asn1Spec=None) pyasn1-0.4.8/docs/source/pyasn1/codec/der/0000775006321400632140000000000013564027341021677 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/der/contents.rst0000644006321400632140000000032113551772543024267 0ustar ietingofietingof00000000000000 Distinguished Encoding Rules ---------------------------- .. autofunction:: pyasn1.codec.der.encoder.encode(value, asn1Spec=None) .. autofunction:: pyasn1.codec.der.decoder.decode(substrate, asn1Spec=None) pyasn1-0.4.8/docs/source/pyasn1/codec/native/0000775006321400632140000000000013564027341022413 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/codec/native/contents.rst0000644006321400632140000000026413551772543025011 0ustar ietingofietingof00000000000000 Native Python types ------------------- .. autofunction:: pyasn1.codec.native.encoder.encode(asn1Value) .. autofunction:: pyasn1.codec.native.decoder.decode(pyObject, asn1Spec) pyasn1-0.4.8/docs/source/pyasn1/contents.rst0000644006321400632140000001506013551772543022446 0ustar ietingofietingof00000000000000 .. _pyasn1: 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 2.4 through 3.7. 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 pyasn1-0.4.8/docs/source/pyasn1/error/0000775006321400632140000000000013564027341021201 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/error/contents.rst0000644006321400632140000000226013551772543023575 0ustar ietingofietingof00000000000000 .. _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: pyasn1-0.4.8/docs/source/pyasn1/type/0000775006321400632140000000000013564027341021031 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/base/0000775006321400632140000000000013564027341021743 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/base/asn1type.rst0000644006321400632140000000041113551772543024242 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/base/constructedasn1type.rst0000644006321400632140000000047613551772543026533 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/base/contents.rst0000644006321400632140000000104313551772543024335 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/base/novalue.rst0000644006321400632140000000014513551772543024153 0ustar ietingofietingof00000000000000.. _type.base.NoValue: NoValue sentinel ---------------- .. autoclass:: pyasn1.type.base.NoValue() pyasn1-0.4.8/docs/source/pyasn1/type/base/simpleasn1type.rst0000644006321400632140000000046513551772543025465 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/char/0000775006321400632140000000000013564027341021746 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/char/bmpstring.rst0000644006321400632140000000142713551772543024516 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/contents.rst0000644006321400632140000000153513551772543024346 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/char/generalstring.rst0000644006321400632140000000147513551772543025360 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/graphicstring.rst0000644006321400632140000000151113551772543025347 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/ia5string.rst0000644006321400632140000000143513551772543024415 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/iso646string.rst0000644006321400632140000000137213551772543024771 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/numericstring.rst0000644006321400632140000000140713551772543025400 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/printablestring.rst0000644006321400632140000000152113551772543025713 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/t61string.rst0000644006321400632140000000134313551772543024347 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/teletexstring.rst0000644006321400632140000000167213551772543025414 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/universalstring.rst0000644006321400632140000000145613551772543025752 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/utf8string.rst0000644006321400632140000000141413551772543024622 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/videotexstring.rst0000644006321400632140000000156213551772543025567 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/char/visiblestring.rst0000644006321400632140000000151613551772543025374 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/constraint/0000775006321400632140000000000013564027341023215 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/constraint/constraintsexclusion.rst0000644006321400632140000000032713551772543030257 0ustar ietingofietingof00000000000000 .. _constrain.ConstraintsExclusion: .. |Constraint| replace:: ConstraintsExclusion Constraints exclusion --------------------- .. autoclass:: pyasn1.type.constraint.ConstraintsExclusion(constraint) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/constraintsintersection.rst0000644006321400632140000000035013551772543030750 0ustar ietingofietingof00000000000000 .. _constrain.ConstraintsIntersection: .. |Constraint| replace:: ConstraintsIntersection Constraints intersection ------------------------ .. autoclass:: pyasn1.type.constraint.ConstraintsIntersection(*constraints) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/constraintsunion.rst0000644006321400632140000000030513551772543027372 0ustar ietingofietingof00000000000000 .. _constrain.ConstraintsUnion: .. |Constraint| replace:: ConstraintsUnion Constraints union ----------------- .. autoclass:: pyasn1.type.constraint.ConstraintsUnion(*constraints) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/containedsubtype.rst0000644006321400632140000000035313551772543027335 0ustar ietingofietingof00000000000000 .. _constrain.ContainedSubtypeConstraint: .. |Constraint| replace:: ContainedSubtypeConstraint Contained subtype constraint ---------------------------- .. autoclass:: pyasn1.type.constraint.ContainedSubtypeConstraint :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/contents.rst0000644006321400632140000000357213551772543025620 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/constraint/permittedalphabet.rst0000644006321400632140000000037313551772543027455 0ustar ietingofietingof00000000000000 .. _constrain.PermittedAlphabetConstraint: .. |Constraint| replace:: PermittedAlphabetConstraint Permitted alphabet constraint ----------------------------- .. autoclass:: pyasn1.type.constraint.PermittedAlphabetConstraint(*alphabet) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/singlevalue.rst0000644006321400632140000000032213551772543026267 0ustar ietingofietingof00000000000000 .. _constrain.SingleValueConstraint: .. |Constraint| replace:: SingleValueConstraint Single value constraint ----------------------- .. autoclass:: pyasn1.type.constraint.SingleValueConstraint :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/valuerange.rst0000644006321400632140000000033113551772543026102 0ustar ietingofietingof00000000000000 .. _constrain.ValueRangeConstraint: .. |Constraint| replace:: ValueRangeConstraint Value range constraint ---------------------- .. autoclass:: pyasn1.type.constraint.ValueRangeConstraint(start, end) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/valuesize.rst0000644006321400632140000000033313551772543025762 0ustar ietingofietingof00000000000000 .. _constrain.ValueSizeConstraint: .. |Constraint| replace:: ValueSizeConstraint Value size constraint ---------------------- .. autoclass:: pyasn1.type.constraint.ValueSizeConstraint(minimum, maximum) :members: pyasn1-0.4.8/docs/source/pyasn1/type/constraint/withcomponents.rst0000644006321400632140000000061313551772543027035 0ustar ietingofietingof00000000000000 .. _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: pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/0000775006321400632140000000000013564027341023017 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/contents.rst0000644006321400632140000000205513551772543025415 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/defaultednamedtype.rst0000644006321400632140000000102013551772543027413 0ustar ietingofietingof00000000000000 .. _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. pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/namedtype.rst0000644006321400632140000000070113551772543025542 0ustar ietingofietingof00000000000000 .. _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. pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/namedtypes.rst0000644006321400632140000000056613551772543025736 0ustar ietingofietingof00000000000000 .. _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. pyasn1-0.4.8/docs/source/pyasn1/type/namedtype/optionalnamedtype.rst0000644006321400632140000000076513551772543027322 0ustar ietingofietingof00000000000000 .. _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. pyasn1-0.4.8/docs/source/pyasn1/type/namedval/0000775006321400632140000000000013564027341022620 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/namedval/contents.rst0000644006321400632140000000164613551772543025223 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/namedval/namedval.rst0000644006321400632140000000036413551772543025151 0ustar ietingofietingof00000000000000 .. _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: pyasn1-0.4.8/docs/source/pyasn1/type/opentype/0000775006321400632140000000000013564027341022674 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/opentype/contents.rst0000644006321400632140000000703313551772543025273 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/opentype/opentype.rst0000644006321400632140000000033113551772543025273 0ustar ietingofietingof00000000000000 .. _opentype.OpenType: .. |OpenType| replace:: OpenType |OpenType| ----------- .. autoclass:: pyasn1.type.opentype.OpenType :members: More information on open type use can be found :ref:`here `.pyasn1-0.4.8/docs/source/pyasn1/type/tag/0000775006321400632140000000000013564027341021604 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/tag/contents.rst0000644006321400632140000000255013551772543024202 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/tag/tag.rst0000644006321400632140000000063513551772543023122 0ustar ietingofietingof00000000000000 .. _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. pyasn1-0.4.8/docs/source/pyasn1/type/tag/tagmap.rst0000644006321400632140000000044013551772543023612 0ustar ietingofietingof00000000000000 .. _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 `. pyasn1-0.4.8/docs/source/pyasn1/type/tag/tagset.rst0000644006321400632140000000044413551772543023634 0ustar ietingofietingof00000000000000 .. _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 `). pyasn1-0.4.8/docs/source/pyasn1/type/univ/0000775006321400632140000000000013564027341022012 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/univ/any.rst0000644006321400632140000000171313551772543023342 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/univ/bitstring.rst0000644006321400632140000000165113551772543024561 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/boolean.rst0000644006321400632140000000121013551772543024162 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/choice.rst0000644006321400632140000000162213551772543024004 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/contents.rst0000644006321400632140000000164513551772543024414 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/univ/enumerated.rst0000644006321400632140000000145713551772543024711 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/integer.rst0000644006321400632140000000147313551772543024213 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/null.rst0000644006321400632140000000074413551772543023530 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/objectidentifier.rst0000644006321400632140000000132013551772543026056 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/octetstring.rst0000644006321400632140000000155613551772543025125 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/univ/real.rst0000644006321400632140000000122513551772543023474 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/sequence.rst0000644006321400632140000000165213551772543024365 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/sequenceof.rst0000644006321400632140000000155713551772543024716 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/set.rst0000644006321400632140000000167513551772543023355 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/univ/setof.rst0000644006321400632140000000152513551772543023674 0ustar ietingofietingof00000000000000 .. _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()) pyasn1-0.4.8/docs/source/pyasn1/type/useful/0000775006321400632140000000000013564027341022334 5ustar ietingofietingof00000000000000pyasn1-0.4.8/docs/source/pyasn1/type/useful/contents.rst0000644006321400632140000000042713551772543024733 0ustar ietingofietingof00000000000000 .. _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 pyasn1-0.4.8/docs/source/pyasn1/type/useful/generalizedtime.rst0000644006321400632140000000274213551772543026250 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/useful/objectdescriptor.rst0000644006321400632140000000155213551772543026443 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/source/pyasn1/type/useful/utctime.rst0000644006321400632140000000246013551772543024547 0ustar ietingofietingof00000000000000 .. _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') pyasn1-0.4.8/docs/tutorial.rst0000644006321400632140000016226513551772543017753 0ustar ietingofietingof00000000000000 Documentation ============= .. toctree:: :maxdepth: 2 Data model for ASN.1 types -------------------------- All ASN.1 types could be categorized into two groups: scalar (also called simple or primitive) and constructed. The first group is populated by well-known types like Integer or String. Members of constructed group hold other types (simple or constructed) as their inner components, thus they are semantically close to a programming language records or lists. In pyasn1, all ASN.1 types and values are implemented as Python objects. The same pyasn1 object can represent either ASN.1 type and/or value depending of the presence of value initializer on object instantiation. We will further refer to these as *pyasn1 type object* versus *pyasn1 value object*. Primitive ASN.1 types are implemented as immutable scalar objects. There values could be used just like corresponding native Python values (integers, strings/bytes etc) and freely mixed with them in expressions. .. code-block:: pycon >>> from pyasn1.type import univ >>> asn1IntegerValue = univ.Integer(12) >>> asn1IntegerValue - 2 10 >>> univ.OctetString('abc') == 'abc' True # Python 2 >>> univ.OctetString(b'abc') == b'abc' True # Python 3 It would be an error to perform an operation on a pyasn1 type object as it holds no value to deal with: .. code-block:: pycon >>> from pyasn1.type import univ >>> asn1IntegerType = univ.Integer() >>> asn1IntegerType - 2 ... pyasn1.error.PyAsn1Error: No value for __coerce__() Scalar types ------------ In the sub-sections that follow we will explain pyasn1 mapping to those primitive ASN.1 types. Both, ASN.1 notation and corresponding pyasn1 syntax will be given in each case. Boolean type ++++++++++++ *BOOLEAN* is the simplest type those values could be either True or False. .. code-block:: bash ;; type specification FunFactorPresent ::= BOOLEAN ;; values declaration and assignment pythonFunFactor FunFactorPresent ::= TRUE cobolFunFactor FunFactorPresent :: FALSE And here's pyasn1 version of :py:class:`~pyasn1.type.univ.Boolean`: .. code-block:: pycon >>> from pyasn1.type import univ >>> class FunFactorPresent(univ.Boolean): pass ... >>> pythonFunFactor = FunFactorPresent(True) >>> cobolFunFactor = FunFactorPresent(False) >>> pythonFunFactor FunFactorPresent('True(1)') >>> cobolFunFactor FunFactorPresent('False(0)') >>> pythonFunFactor == cobolFunFactor False >>> Null type +++++++++ The *NULL* type is sometimes used to express the absence of information. .. code-block:: bash ;; type specification Vote ::= CHOICE { agreed BOOLEAN, skip NULL } ;; value declaration and assignment myVote Vote ::= skip:NULL We will explain the CHOICE type later on, meanwhile the :py:class:`~pyasn1.type.univ.Null` type: .. code-block:: pycon >>> from pyasn1.type import univ >>> skip = univ.Null() >>> skip Null('') >>> Integer type ++++++++++++ ASN.1 defines the values of *INTEGER* type as negative or positive of whatever length. This definition plays nicely with Python as the latter places no limit on Integers. However, some ASN.1 implementations may impose certain limits of integer value ranges. Keep that in mind when designing new data structures. .. code-block:: bash ;; values specification age-of-universe INTEGER ::= 13750000000 mean-martian-surface-temperature INTEGER ::= -63 A rather straightforward mapping into pyasn1 - :py:class:`~pyasn1.type.univ.Integer`: .. code-block:: pycon >>> from pyasn1.type import univ >>> ageOfUniverse = univ.Integer(13750000000) >>> ageOfUniverse Integer(13750000000) >>> >>> meanMartianSurfaceTemperature = univ.Integer(-63) >>> meanMartianSurfaceTemperature Integer(-63) >>> ASN.1 allows to assign human-friendly names to particular values of an INTEGER type. .. code-block:: bash Temperature ::= INTEGER { freezing(0), boiling(100) } The Temperature type expressed in pyasn1: .. code-block:: pycon >>> from pyasn1.type import univ, namedval >>> class Temperature(univ.Integer): ... namedValues = namedval.NamedValues(('freezing', 0), ('boiling', 100)) ... >>> t = Temperature(0) >>> t Temperature('freezing(0)') >>> t + 1 Temperature(1) >>> t + 100 Temperature('boiling(100)') >>> t = Temperature('boiling') >>> t Temperature('boiling(100)') >>> Temperature('boiling') / 2 Temperature(50) >>> -1 < Temperature('freezing') True >>> 47 > Temperature('boiling') False These values labels have no effect on Integer type operations, any value still could be assigned to a type (information on value constraints will follow further in the documentation). Enumerated type +++++++++++++++ ASN.1 *ENUMERATED* type differs from an Integer type in a number of ways. Most important is that its instance can only hold a value that belongs to a set of values specified on type declaration. .. code-block:: bash error-status ::= ENUMERATED { no-error(0), authentication-error(10), authorization-error(20), general-failure(51) } When constructing :py:class:`~pyasn1.type.univ.Enumerated` type we will use two pyasn1 features: values labels (as mentioned above) and value constraint (will be described in more details later on). .. code-block:: pycon >>> from pyasn1.type import univ, namedval, constraint >>> class ErrorStatus(univ.Enumerated): ... namedValues = namedval.NamedValues( ... ('no-error', 0), ... ('authentication-error', 10), ... ('authorization-error', 20), ... ('general-failure', 51) ... ) ... subtypeSpec = univ.Enumerated.subtypeSpec + \ ... constraint.SingleValueConstraint(0, 10, 20, 51) ... >>> errorStatus = univ.ErrorStatus('no-error') >>> errorStatus ErrorStatus('no-error(0)') >>> errorStatus == univ.ErrorStatus('general-failure') False >>> univ.ErrorStatus('non-existing-state') Traceback (most recent call last): ... pyasn1.error.PyAsn1Error: Can't coerce non-existing-state into integer >>> Particular integer values associated with Enumerated value states have no meaning. They should not be used as such or in any kind of math operation. Those integer values are only used by codecs to transfer state from one entity to another. Real type +++++++++ Values of the *REAL* type are a three-component tuple of mantissa, base and exponent. All three are integers. .. code-block:: bash pi ::= REAL { mantissa 314159, base 10, exponent -5 } Corresponding pyasn1 :py:class:`~pyasn1.type.univ.Real` objects can be initialized with either a three-component tuple or a Python float. Infinite values could be expressed in a way, compatible with Python float type. .. code-block:: pycon >>> from pyasn1.type import univ >>> pi = univ.Real((314159, 10, -5)) >>> pi Real((314159, 10,-5)) >>> float(pi) 3.14159 >>> pi == univ.Real(3.14159) True >>> univ.Real('inf') Real('inf') >>> univ.Real('-inf') == float('-inf') True >>> If a Real object is initialized from a Python float or yielded by a math operation, the base is set to decimal 10 (what affects encoding). Bit string type +++++++++++++++ ASN.1 *BIT STRING* type holds opaque binary data of an arbitrarily length. A BIT STRING value could be initialized by either a binary (base 2) or hex (base 16) value. .. code-block:: bash public-key BIT STRING ::= '1010111011110001010110101101101 1011000101010000010110101100010 0110101010000111101010111111110'B signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H The pyasn1 :py:class:`~pyasn1.type.univ.BitString` objects can initialize from native ASN.1 notation (base 2 or base 16 strings) or from a Python tuple of binary components. .. code-block:: pycon >>> from pyasn1.type import univ >>> publicKey = univ.BitString( ... binValue='1010111011110001010110101101101' ... '1011000101010000010110101100010' ... '0110101010000111101010111111110' ) >>> publicKey BitString(binValue='101011101111000101011010110110110110001010100000101101011000100110101010000111101010111111110') >>> signature = univ.BitString( ... hexValue='AF01330CD932093392100B39FF00DE0' ... ) >>> signature BitString(binValue='1010111100000001001100110000110011011001001100100000100100110011100100100001000000001011001110011111111100000000110111100000') >>> fingerprint = univ.BitString( ... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1) ... ) >>> fingerprint BitString(binValue='101101110101') >>> Another BIT STRING initialization method supported by ASN.1 notation is to specify only 1-th bits along with their human-friendly label and bit offset relative to the beginning of the bit string. With this method, all not explicitly mentioned bits are doomed to be zeros. .. code-block:: bash bit-mask BIT STRING ::= { read-flag(0), write-flag(2), run-flag(4) } To express this in pyasn1, we will employ the named values feature (as with Enumeration type). .. code-block:: pycon >>> from pyasn1.type import univ, namedval >>> class BitMask(univ.BitString): ... namedValues = namedval.NamedValues( ... ('read-flag', 0), ... ('write-flag', 2), ... ('run-flag', 4) ... ) >>> bitMask = BitMask('read-flag,run-flag') >>> bitMask BitMask(binValue='10001') >>> tuple(bitMask) (1, 0, 0, 0, 1) >>> bitMask[4] 1 >>> The BitString objects mimic the properties of Python tuple type in part of immutable sequence object protocol support. OctetString type ++++++++++++++++ The *OCTET STRING* type is a confusing subject. According to ASN.1 specification, this type is similar to BIT STRING, the major difference is that the former operates in 8-bit chunks of data. What is important to note, is that OCTET STRING was NOT designed to handle text strings - the standard provides many other types specialized for text content. For that reason, ASN.1 forbids to initialize OCTET STRING values with "quoted text strings", only binary or hex initializers, similar to BIT STRING ones, are allowed. .. code-block:: bash thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H However, ASN.1 users (e.g. protocols designers) seem to ignore the original purpose of the OCTET STRING type - they used it for handling all kinds of data, including text strings. .. code-block:: bash welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!" In pyasn1, we have taken a liberal approach and allowed both BIT STRING style and quoted text initializers for the :py:class:`~pyasn1.type.univ.OctetString` objects. To avoid possible collisions, quoted text is the default initialization syntax. .. code-block:: pycon >>> from pyasn1.type import univ >>> thumbnail = univ.OctetString( ... binValue='1000010111101110101111000000111011' ... ) >>> thumbnail OctetString(hexValue='85eebcec0') >>> thumbnail = univ.OctetString( ... hexValue='FA9823C43E43510DE3422' ... ) >>> thumbnail OctetString(hexValue='fa9823c43e4351de34220') >>> Most frequent usage of the OctetString class is to instantiate it with a text string. .. code-block:: pycon >>> from pyasn1.type import univ >>> welcomeMessage = univ.OctetString('Welcome to ASN.1 wilderness!') >>> welcomeMessage OctetString(b'Welcome to ASN.1 wilderness!') >>> print('%s' % welcomeMessage) Welcome to ASN.1 wilderness! >>> welcomeMessage[11:16] OctetString(b'ASN.1') >>> OctetString objects support the immutable sequence object protocol. In other words, they behave like Python 3 bytes (or Python 2 strings). When running pyasn1 on Python 3, it's better to use the bytes objects for OctetString instantiation, as it's more reliable and efficient. Additionally, OctetString's can also be instantiated with a sequence of 8-bit integers (ASCII codes). .. code-block:: pycon >>> univ.OctetString((77, 101, 101, 103, 111)) OctetString(b'Meego') It is sometimes convenient to express OctetString instances as 8-bit characters (Python 3 bytes or Python 2 strings) or 8-bit integers. .. code-block:: pycon >>> octetString = univ.OctetString('ABCDEF') >>> octetString.asNumbers() (65, 66, 67, 68, 69, 70) >>> octetString.asOctets() b'ABCDEF' ObjectIdentifier type +++++++++++++++++++++ Values of the *OBJECT IDENTIFIER* type are sequences of integers that could be used to identify virtually anything in the world. Various ASN.1-based protocols employ OBJECT IDENTIFIERs for their own identification needs. .. code-block:: bash internet-id OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) internet(1) } One of the natural ways to map OBJECT IDENTIFIER type into a Python one is to use Python tuples of integers. So this approach is taken by pyasn1's :py:class:`~pyasn1.type.univ.ObjectIdentifier` class. .. code-block:: pycon >>> from pyasn1.type import univ >>> internetId = univ.ObjectIdentifier((1, 3, 6, 1)) >>> internetId ObjectIdentifier('1.3.6.1') >>> internetId[2] 6 >>> internetId[1:3] ObjectIdentifier('3.6') A more human-friendly "dotted" notation is also supported. .. code-block:: pycon >>> from pyasn1.type import univ >>> univ.ObjectIdentifier('1.3.6.1') ObjectIdentifier('1.3.6.1') Symbolic names of the arcs of object identifier, sometimes present in ASN.1 specifications, are not preserved and used in pyasn1 objects. The ObjectIdentifier objects mimic the properties of Python tuple type in part of immutable sequence object protocol support. Any type ++++++++ The ASN.1 ANY type is a kind of wildcard or placeholder that matches any other type without knowing it in advance. ANY has no base tag. .. code-block:: bash Error ::= SEQUENCE { code INTEGER, parameter ANY DEFINED BY code } The ANY type is frequently used in specifications, where exact type is not yet agreed upon between communicating parties or the number of possible alternatives of a type is infinite. Sometimes an auxiliary selector is kept around to help parties indicate the kind of ANY payload in effect ("code" in the example above). Values of the ANY type contain serialized ASN.1 value(s) in form of an octet string. Therefore pyasn1 :py:class:`~pyasn1.type.univ.Any` value object share the properties of pyasn1 OctetString object. .. code-block:: pycon >>> from pyasn1.type import univ >>> someValue = univ.Any(b'\x02\x01\x01') >>> someValue Any(b'\x02\x01\x01') >>> str(someValue) '\x02\x01\x01' >>> bytes(someValue) b'\x02\x01\x01' >>> Receiving application is supposed to explicitly deserialize the content of Any value object, possibly using auxiliary selector for figuring out its ASN.1 type to pick appropriate decoder. There will be some more talk and code snippets covering Any type in the codecs chapters that follow. Character string types ++++++++++++++++++++++ ASN.1 standard introduces a diverse set of text-specific types. All of them were designed to handle various types of characters. Some of these types seem be obsolete now days, as their target technologies are gone. Another issue to be aware of is that raw OCTET STRING type is sometimes used in practice by ASN.1 users instead of specialized character string types, despite explicit prohibition imposed by ASN.1 specification. The two types are specific to ASN.1 are NumericString and PrintableString. .. code-block:: bash welcome-message ::= PrintableString { "Welcome to ASN.1 text types" } dial-pad-numbers ::= NumericString { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" } Their pyasn1 implementations are :py:class:`~pyasn1.type.char.PrintableString` and :py:class:`~pyasn1.type.char.NumericString`: .. code-block:: pycon >>> from pyasn1.type import char >>> '%s' % char.PrintableString("Welcome to ASN.1 text types") 'Welcome to ASN.1 text types' >>> dialPadNumbers = char.NumericString( "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ) >>> dialPadNumbers NumericString(b'0123456789') >>> The :py:class:`~pyasn1.type.char.VisibleString`, :py:class:`~pyasn1.type.char.IA5String`, :py:class:`~pyasn1.type.char.TeletexString`, :py:class:`~pyasn1.type.char.VideotexString`, :py:class:`~pyasn1.type.char.GraphicString` and :py:class:`~pyasn1.type.char.GeneralString` types came to ASN.1 from ISO standards on character sets. .. code-block:: pycon >>> from pyasn1.type import char >>> char.VisibleString("abc") VisibleString(b'abc') >>> char.IA5String('abc') IA5String(b'abc') >>> char.TeletexString('abc') TeletexString(b'abc') >>> char.VideotexString('abc') VideotexString(b'abc') >>> char.GraphicString('abc') GraphicString(b'abc') >>> char.GeneralString('abc') GeneralString(b'abc') >>> The last three types are relatively recent addition to the family of character string types: :py:class:`~pyasn1.type.char.UniversalString`, :py:class:`~pyasn1.type.char.BMPString` and :py:class:`~pyasn1.type.char.UTF8String`. .. code-block:: pycon >>> from pyasn1.type import char >>> char.UniversalString("abc") UniversalString(b'abc') >>> char.BMPString('abc') BMPString(b'abc') >>> char.UTF8String('abc') UTF8String(b'abc') >>> utf8String = char.UTF8String('У попа была собака') >>> utf8String UTF8String(b'\xd0\xa3 \xd0\xbf\xd0\xbe\xd0\xbf\xd0\xb0 \xd0\xb1\xd1\x8b\xd0\xbb\xd0\xb0\xd1\x81\xd0\xbe\xd0\xb1\xd0\xb0\xd0\xba\xd0\xb0') >>> print(utf8String) У попа была собака >>> In pyasn1, all character type objects behave like Python strings. None of them is currently constrained in terms of valid alphabet so it's up to the data source to keep an eye on data validation for these types. Useful types ++++++++++++ There are three so-called useful types defined in the standard: :py:class:`~pyasn1.type.useful.ObjectDescriptor`, :py:class:`~pyasn1.type.useful.GeneralizedTime` and :py:class:`~pyasn1.type.useful.UTCTime`. They all are subtypes of GraphicString or VisibleString types therefore useful types are character string types. It's advised by the ASN.1 standard to have an instance of ObjectDescriptor type holding a human-readable description of corresponding instance of OBJECT IDENTIFIER type. There are no formal linkage between these instances and provision for ObjectDescriptor uniqueness in the standard. .. code-block:: pycon >>> from pyasn1.type import useful >>> descrBER = useful.ObjectDescriptor( "Basic encoding of a single ASN.1 type" ) >>> GeneralizedTime and UTCTime types are designed to hold a human-readable timestamp in a universal and unambiguous form. The former provides more flexibility in notation while the latter is more strict but has Y2K issues. .. code-block:: bash ;; Mar 8 2010 12:00:00 MSK moscow-time GeneralizedTime ::= "20110308120000.0" ;; Mar 8 2010 12:00:00 UTC utc-time GeneralizedTime ::= "201103081200Z" ;; Mar 8 1999 12:00:00 UTC utc-time UTCTime ::= "9803081200Z" In pyasn1 parlance: .. code-block:: pycon >>> from pyasn1.type import useful >>> moscowTime = useful.GeneralizedTime("20110308120000.0") >>> utcTime = useful.UTCTime("9803081200Z") >>> Despite their intended use, these types possess no special, time-related, handling in pyasn1. They are just printable strings. Tagging ------- In order to proceed to the Constructed ASN.1 types, we will first have to introduce the concept of tagging (and its pyasn1 implementation), as some of the Constructed types rely upon the tagging feature. When a value is coming into an ASN.1-based system (received from a network or read from some storage), the receiving entity has to determine the type of the value to interpret and verify it accordingly. Historically, the first data serialization protocol introduced in ASN.1 was BER (Basic Encoding Rules). According to BER, any serialized value is packed into a triplet of (Type, Length, Value) where Type is a code that identifies the value (which is called *tag* in ASN.1), length is the number of bytes occupied by the value in its serialized form and value is ASN.1 value in a form suitable for serial transmission or storage. For that reason almost every ASN.1 type has a tag (which is actually a BER type) associated with it by default. An ASN.1 tag could be viewed as a tuple of three numbers: (Class, Format, Number). While Number identifies a tag, Class component is used to create scopes for Numbers. Four scopes are currently defined: UNIVERSAL, context-specific, APPLICATION and PRIVATE. The Format component is actually a one-bit flag - zero for tags associated with scalar types, and one for constructed types (will be discussed later on). .. code-block:: bash MyIntegerType ::= [12] INTEGER MyOctetString ::= [APPLICATION 0] OCTET STRING In pyasn1, tags are implemented as immutable, tuple-like objects: .. code-block:: pycon >>> from pyasn1.type import tag >>> myTag = tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) >>> myTag Tag(tagClass=128, tagFormat=0, tagId=10) >>> tuple(myTag) (128, 0, 10) >>> myTag[2] 10 >>> myTag == tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 10) False >>> Default tag, associated with any ASN.1 type, could be extended or replaced to make new type distinguishable from its ancestor. The standard provides two modes of tag mangling - IMPLICIT and EXPLICIT. EXPLICIT mode works by appending new tag to the existing ones thus creating an ordered set of tags. This set will be considered as a whole for type identification and encoding purposes. Important property of EXPLICIT tagging mode is that it preserves base type information in encoding what makes it possible to completely recover type information from encoding. When tagging in IMPLICIT mode, the outermost existing tag is dropped and replaced with a new one. .. code-block:: bash MyIntegerType ::= [12] IMPLICIT INTEGER MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING To model both modes of tagging, a specialized container TagSet object (holding zero, one or more Tag objects) is used in pyasn1. .. code-block:: pycon >>> from pyasn1.type import tag >>> tagSet = tag.TagSet( ... # base tag (OBSOLETE AND NOT USED ANYMORE) ... (), ... # effective tag ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) ... ) >>> tagSet TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10)) >>> tagSet.getBaseTag() Tag(tagClass=128, tagFormat=0, tagId=10) >>> tagSet = tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)) >>> tagSet TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), Tag(tagClass=128, tagFormat=32, tagId=20)) >>> tagSet = tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 30)) >>> tagSet TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), Tag(tagClass=128, tagFormat=32, tagId=20), Tag(tagClass=128, tagFormat=32, tagId=30)) >>> tagSet = tagSet.tagImplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40)) >>> tagSet TagSet((), Tag(tagClass=128, tagFormat=0, tagId=10), Tag(tagClass=128, tagFormat=32, tagId=20), Tag(tagClass=128, tagFormat=32, tagId=40)) >>> As a side note: the "base tag" concept is now obsolete and not used. The "effective tag" is the one that always appears in encoding and is used on tagSets comparison. Any two TagSet objects could be compared to see if one is a derivative of the other. Figuring this out is also useful in cases when a type-specific data processing algorithms are to be chosen. .. code-block:: pycon >>> from pyasn1.type import tag >>> tagSet1 = tag.TagSet( ... # base tag (OBSOLETE AND NOT USED ANYMORE) ... (), ... # effective tag ... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) ... ) >>> tagSet2 = tagSet1.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20)) >>> tagSet1.isSuperTagSetOf(tagSet2) True >>> tagSet2.isSuperTagSetOf(tagSet1) False >>> We will complete this discussion on tagging with a real-world example. The following ASN.1 tagged type: .. code-block:: bash MyIntegerType ::= [12] EXPLICIT INTEGER could be expressed in pyasn1 like this: .. code-block:: pycon >>> from pyasn1.type import univ, tag >>> class MyIntegerType(univ.Integer): ... tagSet = univ.Integer.tagSet.tagExplicitly(tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 12)) >>> myInteger = MyIntegerType(12345) >>> myInteger.tagSet TagSet((), Tag(tagClass=0, tagFormat=0, tagId=2), Tag(tagClass=128, tagFormat=32, tagId=12)) >>> Referring to the above code, the tagSet class attribute is a property of any pyasn1 type object that assigns default tagSet to a pyasn1 value object. This default tagSet specification can be ignored and effectively replaced by some other tagSet value passed on object instantiation. It's important to understand that the tag set property of pyasn1 type/value object can never be modified in place. In other words, a pyasn1 type/value object can never change its tags. The only way is to create a new pyasn1 type/value object and associate different tag set with it. Constructed types ----------------- Besides scalar types, ASN.1 specifies so-called constructed ones - these are capable of holding one or more values of other types, both scalar and constructed. In pyasn1 implementation, constructed ASN.1 types behave like Python sequences, and also support additional component addressing methods, specific to particular constructed type. Sequence and Set types ++++++++++++++++++++++ The *SEQUENCE* and *SET* types have many similar properties: * Both can hold any number of inner components of different types. * Every component has a human-friendly identifier. * Any component can have a default value. * Some components can be absent. However, :py:class:`~pyasn1.type.univ.Sequence` type guarantees the ordering of Sequence value components to match their declaration order. By contrast, components of the :py:class:`~pyasn1.type.univ.Set` type can be ordered to best suite application's needs. .. code-block:: bash Record ::= SEQUENCE { id INTEGER, room [0] INTEGER OPTIONAL, house [1] INTEGER DEFAULT 0 } Up to this moment, the only method we used for creating new pyasn1 types is Python sub-classing. With this method, a new, named Python class is created what mimics type derivation in ASN.1 grammar. However, ASN.1 also allows for defining anonymous subtypes (room and house components in the example above). To support anonymous subtyping in pyasn1, a cloning operation on an existing pyasn1 type object can be invoked what creates a new instance of original object with possibly modified properties. .. code-block:: pycon >>> from pyasn1.type import univ, namedtype, tag >>> class Record(univ.Sequence): ... componentType = namedtype.NamedTypes( ... namedtype.NamedType('id', univ.Integer()), ... namedtype.OptionalNamedType( ... 'room', ... univ.Integer().subtype( ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0) ... ) ... ), ... namedtype.DefaultedNamedType( ... 'house', ... univ.Integer(0).subtype( ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1) ... ) ... ) ... ) >>> All pyasn1 constructed type classes have a class attribute **componentType** that represent default type specification. Its value is a NamedTypes object. The NamedTypes class instance holds a sequence of NameType, OptionalNamedType or DefaultedNamedType objects which, in turn, refer to pyasn1 type objects that represent inner SEQUENCE components specification. Finally, invocation of a subtype() method of pyasn1 type objects in the code above returns an implicitly tagged copy of original object. Once a SEQUENCE or SET type is declared with pyasn1, it can be instantiated and initialized (continuing the above code): .. code-block:: pycon >>> record = Record() >>> record['id'] = 123 >>> print(record.prettyPrint()) Record: id=123 >>> >>> record[1] = 321 >>> print(record.prettyPrint()) Record: id=123 room=321 >>> >>> record.setDefaultComponents() >>> print(record.prettyPrint()) Record: id=123 room=321 house=0 Inner components of pyasn1 Sequence/Set objects could be accessed using the following methods: .. code-block:: pycon >>> record['id'] Integer(123) >>> record[1] Integer(321) >>> record[2] Integer(0) >>> for idx, field in enumerate(record): ... print(record.componentType[idx].name, field) id 123 room 321 house 0 >>> The Set type share all the properties of Sequence type, and additionally support by-tag component addressing (as all Set components have distinct types). .. code-block:: pycon >>> from pyasn1.type import univ, namedtype, tag >>> class Gamer(univ.Set): ... componentType = namedtype.NamedTypes( ... namedtype.NamedType('score', univ.Integer()), ... namedtype.NamedType('player', univ.OctetString()), ... namedtype.NamedType('id', univ.ObjectIdentifier()) ... ) >>> gamer = Gamer() >>> gamer.setComponentByType(univ.Integer().tagSet, 121343) >>> gamer.setComponentByType(univ.OctetString().tagSet, 'Pascal') >>> gamer.setComponentByType(univ.ObjectIdentifier().tagSet, (1,3,7,2)) >>> print(gamer.prettyPrint()) Gamer: score=121343 player=b'Pascal' id=1.3.7.2 SequenceOf and SetOf types ++++++++++++++++++++++++++ Both, *SEQUENCE OF* and *SET OF* types resemble an unlimited size list of components. All the components must be of the same type. .. code-block:: bash Progression ::= SEQUENCE OF INTEGER arithmeticProgression Progression ::= { 1, 3, 5, 7 } :py:class:`~pyasn1.type.univ.SequenceOf` and :py:class:`~pyasn1.type.univ.SetOf` types are expressed by the very similar pyasn1 `list` type objects. Their components can only be addressed by position and they both have a property of automatic resize. To specify inner component type, the **componentType** class attribute should refer to another pyasn1 type object. .. code-block:: pycon >>> from pyasn1.type import univ >>> class Progression(univ.SequenceOf): ... componentType = univ.Integer() >>> arithmeticProgression = Progression() >>> arithmeticProgression[1] = 111 >>> print(arithmeticProgression.prettyPrint()) Progression: -empty- 111 >>> arithmeticProgression[0] = 100 >>> print(arithmeticProgression.prettyPrint()) Progression: 100 111 >>> >>> for element in arithmeticProgression: ... element Integer(100) Integer(111) >>> Any scalar or constructed pyasn1 type object can serve as an inner component. Missing components are prohibited in SequenceOf/SetOf value objects. Choice type +++++++++++ Values of ASN.1 *CHOICE* type can contain only a single value of a type from a list of possible alternatives. Alternatives must be ASN.1 types with distinct tags for the whole structure to remain unambiguous. Unlike most other types, CHOICE is an untagged one, e.g. it has no base tag of its own. .. code-block:: bash CodeOrMessage ::= CHOICE { code INTEGER, message OCTET STRING } In pyasn1 implementation, :py:class:`~pyasn1.type.univ.Choice` object behaves like Set but accepts only a single inner component at a time. It also offers a few additional methods specific to its behaviour. .. code-block:: pycon >>> from pyasn1.type import univ, namedtype >>> class CodeOrMessage(univ.Choice): ... componentType = namedtype.NamedTypes( ... namedtype.NamedType('code', univ.Integer()), ... namedtype.NamedType('message', univ.OctetString()) ... ) >>> >>> codeOrMessage = CodeOrMessage() >>> print(codeOrMessage.prettyPrint()) CodeOrMessage: >>> codeOrMessage['code'] = 123 >>> print(codeOrMessage.prettyPrint()) CodeOrMessage: code=123 >>> codeOrMessage['message'] = 'my string value' >>> print(codeOrMessage.prettyPrint()) CodeOrMessage: message=b'my string value' >>> Since there could be only a single inner component value in the pyasn1 Choice value object, either of the following methods could be used for fetching it (continuing previous code): .. code-block:: pycon >>> codeOrMessage.getName() 'message' >>> codeOrMessage.getComponent() OctetString(b'my string value') >>> Subtype constraints ------------------- Most ASN.1 types can correspond to an infinite set of values. To adapt to particular application's data model and needs, ASN.1 provides a mechanism for limiting the infinite set to values, that make sense in particular case. Imposing value constraints on an ASN.1 type can also be seen as creating a subtype from its base type. In pyasn1, constraints take shape of immutable objects capable of evaluating given value against constraint-specific requirements. Constraint object is a property of pyasn1 type. Like TagSet property, associated with every pyasn1 type, constraints can never be modified in place. The only way to modify pyasn1 type constraint is to associate new constraint object to a new pyasn1 type object. A handful of different flavors of *constraints* are defined in ASN.1. We will discuss them one by one in the following chapters and also explain how to combine and apply them to types. Single value constraint +++++++++++++++++++++++ This kind of constraint allows for limiting type to a finite, specified set of values. .. code-block:: bash DialButton ::= OCTET STRING ( "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ) Its pyasn1 implementation would look like: .. code-block:: pycon >>> from pyasn1.type import constraint >>> c = constraint.SingleValueConstraint('0','1','2','3','4','5','6','7','8','9') >>> c SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) >>> c('0') >>> c('A') Traceback (most recent call last): ... ValueConstraintError: SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A >>> As can be seen in the snippet above, if a value violates the constraint, an exception will be thrown. A constrained pyasn1 type object holds a reference to a constraint object (or their combination, as will be explained later) and calls it for value verification. .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> class DialButton(univ.OctetString): ... subtypeSpec = constraint.SingleValueConstraint( ... '0','1','2','3','4','5','6','7','8','9' ... ) >>> DialButton('0') DialButton(b'0') >>> DialButton('A') Traceback (most recent call last): ... ValueConstraintError: SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A >>> Constrained pyasn1 value object can never hold a violating value. Value range constraint ++++++++++++++++++++++ A pair of values, compliant to a type to be constrained, denote low and upper bounds of allowed range of values of a type. .. code-block:: bash Teenagers ::= INTEGER (13..19) And in pyasn1 terms: .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> class Teenagers(univ.Integer): ... subtypeSpec = constraint.ValueRangeConstraint(13, 19) >>> Teenagers(14) Teenagers(14) >>> Teenagers(20) Traceback (most recent call last): ... ValueConstraintError: ValueRangeConstraint(13, 19) failed at: 20 >>> ASN.1 MIN and MAX operands can be substituted with floating point infinity values. .. code-block:: bash NegativeInt ::= INTEGER (MIN..-1) PositiveInt ::= INTEGER (1..MAX) And in pyasn1 terms: .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> class NegativeInt(univ.Integer): ... subtypeSpec = constraint.ValueRangeConstraint(float('-inf'), -1) >>> NegativeInt(-1) NegativeInt(-1) >>> NegativeInt(0) Traceback (most recent call last): ... ValueConstraintError: ValueConstraintError: ValueRangeConstraint() failed at: "0" at NegativeInt >>> class PositiveInt(univ.Integer): ... subtypeSpec = constraint.ValueRangeConstraint(1, float('inf')) >> PositiveInt(1) PositiveInt(1) >> PositiveInt(4) PositiveInt(4) >> PositiveInt(-1) Traceback (most recent call last): ... ValueConstraintError: ValueConstraintError: ValueRangeConstraint() failed at: "-1" at PositiveInt Value range constraint usually applies to numeric types. Size constraint +++++++++++++++ It is sometimes convenient to set or limit the allowed size of a data item to be sent from one application to another to manage bandwidth and memory consumption issues. Size constraint specifies the lower and upper bounds of the size of a valid value. .. code-block:: bash TwoBits ::= BIT STRING (SIZE (2)) Express the same grammar in pyasn1: .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> class TwoBits(univ.BitString): ... subtypeSpec = constraint.ValueSizeConstraint(2, 2) >>> TwoBits((1,1)) TwoBits("'11'B") >>> TwoBits((1,1,0)) Traceback (most recent call last): ... ValueConstraintError: ValueSizeConstraint(2, 2) failed at: (1, 1, 0) >>> Size constraint can be applied to potentially massive values - bit or octet strings, SEQUENCE OF/SET OF values. Alphabet constraint +++++++++++++++++++ The permitted alphabet constraint is similar to Single value constraint but constraint applies to individual characters of a value. .. code-block:: bash MorseCode ::= PrintableString (FROM ("."|"-"|" ")) And in pyasn1: .. code-block:: pycon >>> from pyasn1.type import char, constraint >>> class MorseCode(char.PrintableString): ... subtypeSpec = constraint.PermittedAlphabetConstraint(".", "-", " ") >>> MorseCode("...---...") MorseCode('...---...') >>> MorseCode("?") Traceback (most recent call last): ... ValueConstraintError: PermittedAlphabetConstraint(".", "-", " ") failed at: "?" >>> Current implementation does not handle ranges of characters in constraint (FROM "A".."Z" syntax), one has to list the whole set in a range. Constraint combinations +++++++++++++++++++++++ Up to this moment, we used a single constraint per ASN.1 type. The standard, however, allows for combining multiple individual constraints into intersections, unions and exclusions. In pyasn1 data model, all of these methods of constraint combinations are implemented as constraint-like objects holding individual constraint (or combination) objects. Like terminal constraint objects, combination objects are capable to perform value verification at its set of enclosed constraints according to the logic of particular combination. Constraints intersection verification succeeds only if a value is compliant to each constraint in a set. To begin with, the following specification will constitute a valid telephone number: .. code-block:: bash PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE 11) Constraint intersection object serves the logic above: .. code-block:: pycon >>> from pyasn1.type import char, constraint >>> class PhoneNumber(char.NumericString): ... subtypeSpec = constraint.ConstraintsIntersection( ... constraint.PermittedAlphabetConstraint('0','1','2','3','4','5','6', '7','8','9'), ... constraint.ValueSizeConstraint(11, 11) ... ) >>> PhoneNumber('79039343212') PhoneNumber('79039343212') >>> PhoneNumber('?9039343212') Traceback (most recent call last): ... ValueConstraintError: ConstraintsIntersection(PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'), ValueSizeConstraint(11, 11)) failed at: PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9') failed at: "?039343212" >>> PhoneNumber('9343212') Traceback (most recent call last): ... ValueConstraintError: ConstraintsIntersection(PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'), ValueSizeConstraint(11, 11)) failed at: ValueSizeConstraint(10, 10) failed at: "9343212" >>> Union of constraints works by making sure that a value is compliant to any of the constraint in a set. For instance: .. code-block:: bash CapitalOrSmall ::= IA5String (FROM ('A','B','C') | FROM ('a','b','c')) It's important to note, that a value must fully comply to any single constraint in a set. In the specification above, a value of all small or all capital letters is compliant, but a mix of small&capitals is not. Here's its pyasn1 analogue: .. code-block:: pycon >>> from pyasn1.type import char, constraint >>> class CapitalOrSmall(char.IA5String): ... subtypeSpec = constraint.ConstraintsUnion( ... constraint.PermittedAlphabetConstraint('A','B','C'), ... constraint.PermittedAlphabetConstraint('a','b','c') ... ) >>> CapitalOrSmall('ABBA') CapitalOrSmall('ABBA') >>> CapitalOrSmall('abba') CapitalOrSmall('abba') >>> CapitalOrSmall('Abba') Traceback (most recent call last): ... ValueConstraintError: ConstraintsUnion(PermittedAlphabetConstraint('A', 'B', 'C'), PermittedAlphabetConstraint('a', 'b', 'c')) failed at: failed for "Abba" >>> Finally, the exclusion constraint simply negates the logic of value verification at a constraint. In the following example, any integer value is allowed in a type but not zero. .. code-block:: bash NoZero ::= INTEGER (ALL EXCEPT 0) In pyasn1 the above definition would read: .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> class NoZero(univ.Integer): ... subtypeSpec = constraint.ConstraintsExclusion( ... constraint.SingleValueConstraint(0) ... ) >>> NoZero(1) NoZero(1) >>> NoZero(0) Traceback (most recent call last): ... ValueConstraintError: ConstraintsExclusion(SingleValueConstraint(0)) failed at: 0 >>> The depth of such a constraints tree, built with constraint combination objects at its nodes, has not explicit limit. Value verification is performed in a recursive manner till a definite solution is found. Types relationships +++++++++++++++++++ In the course of data processing in an application, it is sometimes convenient to figure out the type relationships between pyasn1 type or value objects. Formally, two things influence pyasn1 types relationship: *tag set* and *subtype constraints*. One pyasn1 type is considered to be a derivative of another if their TagSet and Constraint objects are a derivation of one another. The following example illustrates the concept (we use the same tagset but different constraints for simplicity): .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> i1 = univ.Integer(subtypeSpec=constraint.ValueRangeConstraint(3,8)) >>> i2 = univ.Integer(subtypeSpec=constraint.ConstraintsIntersection( ... constraint.ValueRangeConstraint(3,8), ... constraint.ValueRangeConstraint(4,7) ... ) ) >>> i1.isSameTypeWith(i2) False >>> i1.isSuperTypeOf(i2) True >>> i1.isSuperTypeOf(i1) True >>> i2.isSuperTypeOf(i1) False >>> As can be seen in the above code snippet, there are two methods of any pyasn1 type/value object that test types for their relationship: *isSameTypeWith()* and *isSuperTypeOf()*. The former is self-descriptive while the latter yields true if the argument appears to be a pyasn1 object which has tagset and constraints derived from those of the object being called. Serialization codecs -------------------- In ASN.1 context, `codec `_ is a program that transforms between concrete data structures and a stream of octets, suitable for transmission over the wire. This serialized form of data is sometimes called *substrate* or *essence*. In pyasn1 implementation, substrate takes shape of Python 3 bytes or Python 2 string objects. One of the properties of a codec is its ability to cope with incomplete data and/or substrate what implies codec to be stateful. In other words, when decoder runs out of substrate and data item being recovered is still incomplete, stateful codec would suspend and complete data item recovery whenever the rest of substrate becomes available. Similarly, stateful encoder would encode data items in multiple steps waiting for source data to arrive. Codec restartability is especially important when application deals with large volumes of data and/or runs on low RAM. For an interesting discussion on codecs options and design choices, refer to `Apache ASN.1 project `_ . As of this writing, codecs implemented in pyasn1 are all stateless, mostly to keep the code simple. The pyasn1 package currently supports `BER `_ codec and its variations -- `CER `_ and `DER `_. More ASN.1 codecs are planned for implementation in the future. Encoders ++++++++ Encoder is used for transforming pyasn1 value objects into substrate. Only pyasn1 value objects could be serialized, attempts to process pyasn1 type objects will cause encoder failure. The following code will create a pyasn1 Integer object and serialize it with BER encoder: .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder >>> encoder.encode(univ.Integer(123456)) b'\x02\x03\x01\xe2@' >>> BER standard also defines a so-called *indefinite length* encoding form which makes large data items processing more memory efficient. It is mostly useful when encoder does not have the whole value all at once and the length of the value can not be determined at the beginning of encoding. *Constructed encoding* is another feature of BER closely related to the indefinite length form. In essence, a large scalar value (such as ASN.1 character BitString type) could be chopped into smaller chunks by encoder and transmitted incrementally to limit memory consumption. Unlike indefinite length case, the length of the whole value must be known in advance when using constructed, definite length encoding form. Since pyasn1 codecs are not restartable, pyasn1 encoder may only encode data item all at once. However, even in this case, generating indefinite length encoding may help a low-memory receiver, running a restartable decoder, to process a large data item. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder >>> encoder.encode( ... univ.OctetString('The quick brown fox jumps over the lazy dog'), ... defMode=False, ... maxChunkSize=8 ... ) b'$\x80\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \t\x04\x08he lazy \x04\x03dog\x00\x00' >>> >>> encoder.encode( ... univ.OctetString('The quick brown fox jumps over the lazy dog'), ... maxChunkSize=8 ... ) b'$7\x04\x08The quic\x04\x08k brown \x04\x08fox jump\x04\x08s over \t\x04\x08he lazy \x04\x03dog' The *defMode* encoder parameter disables definite length encoding mode, while the optional *maxChunkSize* parameter specifies desired substrate chunk size that influences memory requirements at the decoder's end. To use CER or DER encoders one needs to explicitly import and call them - the APIs are all compatible. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder as ber_encoder >>> from pyasn1.codec.cer import encoder as cer_encoder >>> from pyasn1.codec.der import encoder as der_encoder >>> ber_encoder.encode(univ.Boolean(True)) b'\x01\x01\x01' >>> cer_encoder.encode(univ.Boolean(True)) b'\x01\x01\xff' >>> der_encoder.encode(univ.Boolean(True)) b'\x01\x01\xff' >>> Decoders ++++++++ In the process of decoding, pyasn1 value objects are created and linked to each other, based on the information contained in the substrate. Thus, the original pyasn1 value object(s) are recovered. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder, decoder >>> substrate = encoder.encode(univ.Boolean(True)) >>> decoder.decode(substrate) (Boolean('True(1)'), b'') >>> Commenting on the code snippet above, pyasn1 decoder accepts substrate as an argument and returns a tuple of pyasn1 value object (possibly a top-level one in case of constructed object) and unprocessed part of input substrate. All pyasn1 decoders can handle both definite and indefinite length encoding modes automatically, explicit switching into one mode to another is not required. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder, decoder >>> substrate = encoder.encode( ... univ.OctetString('The quick brown fox jumps over the lazy dog'), ... defMode=False, ... maxChunkSize=8 ... ) >>> decoder.decode(substrate) (OctetString(b'The quick brown fox jumps over the lazy dog'), b'') >>> Speaking of BER/CER/DER encoding, in many situations substrate may not contain all necessary information needed for complete and accurate ASN.1 values recovery. The most obvious cases include implicitly tagged ASN.1 types and constrained types. As discussed earlier in this tutorial, when an ASN.1 type is implicitly tagged, previous outermost tag is lost and never appears in substrate. If it is the base tag that gets lost, decoder is unable to pick type-specific value decoder at its table of built-in types, and therefore recover the value part, based only on the information contained in substrate. The approach taken by pyasn1 decoder is to use a prototype pyasn1 type object (or a set of them) to *guide* the decoding process by matching [possibly incomplete] tags recovered from substrate with those found in prototype pyasn1 type objects (also called pyasn1 specification object further in this document). .. code-block:: pycon >>> from pyasn1.codec.ber import decoder >>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer()) Integer(12), b'' >>> Decoder would neither modify pyasn1 specification object nor use its current values (if it's a pyasn1 value object), but rather use it as a hint for choosing proper decoder and as a pattern for creating new objects: .. code-block:: pycon >>> from pyasn1.type import univ, tag >>> from pyasn1.codec.ber import encoder, decoder >>> i = univ.Integer(12345).subtype( ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) ... ) >>> substrate = encoder.encode(i) >>> substrate b'\x9f(\x0209' >>> decoder.decode(substrate) Traceback (most recent call last): ... pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec >>> decoder.decode(substrate, asn1Spec=i) (Integer(12345), b'') >>> Notice in the example above, that an attempt to run decoder without passing pyasn1 specification object fails because recovered tag does not belong to any of the built-in types. Another important feature of guided decoder operation is the use of values constraints possibly present in pyasn1 specification object. To explain this, we will decode a random integer object into generic Integer and the constrained one. .. code-block:: pycon >>> from pyasn1.type import univ, constraint >>> from pyasn1.codec.ber import encoder, decoder >>> class DialDigit(univ.Integer): ... subtypeSpec = constraint.ValueRangeConstraint(0,9) >>> substrate = encoder.encode(univ.Integer(13)) >>> decoder.decode(substrate) (Integer(13), b'') >>> decoder.decode(substrate, asn1Spec=DialDigit()) Traceback (most recent call last): ... ValueConstraintError: ValueRangeConstraint(0, 9) failed at: 13 >>> Similarly to encoders, to use CER or DER decoders application has to explicitly import and call them - all APIs are compatible. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder as ber_encoder >>> substrate = ber_encoder.encode(univ.OctetString('http://pyasn1.sf.net')) >>> >>> from pyasn1.codec.ber import decoder as ber_decoder >>> from pyasn1.codec.cer import decoder as cer_decoder >>> from pyasn1.codec.der import decoder as der_decoder >>> >>> ber_decoder.decode(substrate) (OctetString(b'http://pyasn1.sf.net'), b'') >>> cer_decoder.decode(substrate) (OctetString(b'http://pyasn1.sf.net'), b'') >>> der_decoder.decode(substrate) (OctetString(b'http://pyasn1.sf.net'), b'') >>> Advanced topics --------------- Certain, non-trivial, ASN.1 data structures may require special treatment, especially when running deserialization. Decoding untagged types +++++++++++++++++++++++ It has already been mentioned, that ASN.1 has two "special case" types: CHOICE and ANY. They are different from other types in part of tagging - unless these two are additionally tagged, neither of them will have their own tag. Therefore these types become invisible in substrate and can not be recovered without passing pyasn1 specification object to decoder. To explain the issue, we will first prepare a Choice object to deal with: .. code-block:: pycon >>> from pyasn1.type import univ, namedtype >>> class CodeOrMessage(univ.Choice): ... componentType = namedtype.NamedTypes( ... namedtype.NamedType('code', univ.Integer()), ... namedtype.NamedType('message', univ.OctetString()) ... ) >>> >>> codeOrMessage = CodeOrMessage() >>> codeOrMessage['message'] = 'my string value' >>> print(codeOrMessage.prettyPrint()) CodeOrMessage: message=b'my string value' >>> Let's now encode this Choice object and then decode its substrate with and without pyasn1 specification object: .. code-block:: pycon >>> from pyasn1.codec.ber import encoder, decoder >>> substrate = encoder.encode(codeOrMessage) >>> substrate b'\x04\x0fmy string value' >>> encoder.encode(univ.OctetString('my string value')) b'\x04\x0fmy string value' >>> >>> decoder.decode(substrate) (OctetString(b'my string value'), b'') >>> codeOrMessage, substrate = decoder.decode(substrate, asn1Spec=CodeOrMessage()) >>> print(codeOrMessage.prettyPrint()) CodeOrMessage: message=b'my string value' >>> First thing to notice in the listing above is that the substrate produced for our Choice value object is equivalent to the substrate for an OctetString object initialized to the same value. In other words, any information about the Choice component is absent in encoding. Sure enough, that kind of substrate will decode into an OctetString object, unless original Choice type object is passed to decoder to guide the decoding process. Similarly untagged ANY type behaves differently on decoding phase - when decoder bumps into an Any object in pyasn1 specification, it stops decoding and puts all the substrate into a new Any value object in form of an octet string. Concerned application could then re-run decoder with an additional, more exact pyasn1 specification object to recover the contents of Any object. As it was mentioned elsewhere in this documentation, Any type allows for incomplete or changing ASN.1 specification to be handled gracefully by decoder and applications. To illustrate the working of Any type, we'll have to make the stage by encoding a pyasn1 object and then putting its substrate into an any object. .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder, decoder >>> innerSubstrate = encoder.encode(univ.Integer(1234)) >>> innerSubstrate b'\x02\x02\x04\xd2' >>> any = univ.Any(innerSubstrate) >>> any Any(b'\x02\x02\x04\xd2') >>> substrate = encoder.encode(any) >>> substrate b'\x02\x02\x04\xd2' >>> As with Choice type encoding, there is no traces of Any type in substrate. Obviously, the substrate we are dealing with, will decode into the inner [Integer] component, unless pyasn1 specification is given to guide the decoder. Continuing previous code: .. code-block:: pycon >>> from pyasn1.type import univ >>> from pyasn1.codec.ber import encoder, decoder >>> decoder.decode(substrate) (Integer(1234), b'') >>> any, substrate = decoder.decode(substrate, asn1Spec=univ.Any()) >>> any Any(b'\x02\x02\x04\xd2') >>> decoder.decode(str(any)) (Integer(1234), b'') >>> Both CHOICE and ANY types are widely used in practice. Reader is welcome to take a look at `ASN.1 specifications of X.509 applications `_ for more information. Ignoring unknown types ++++++++++++++++++++++ When dealing with a loosely specified ASN.1 structure, the receiving end may not be aware of some types present in the substrate. It may be convenient then to turn decoder into a recovery mode. Whilst there, decoder will not bail out when hit an unknown tag but rather treat it as an Any type. .. code-block:: pycon >>> from pyasn1.type import univ, tag >>> from pyasn1.codec.ber import encoder, decoder >>> taggedInt = univ.Integer(12345).subtype( ... implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 40) ... ) >>> substrate = encoder.encode(taggedInt) >>> decoder.decode(substrate) Traceback (most recent call last): ... pyasn1.error.PyAsn1Error: TagSet(Tag(tagClass=128, tagFormat=0, tagId=40)) not in asn1Spec >>> >>> decoder.decode.defaultErrorState = decoder.stDumpRawValue >>> decoder.decode(substrate) (Any(b'\x9f(\x0209'), '') >>> It's also possible to configure a custom decoder, to handle unknown tags found in substrate. This can be done by means of *defaultRawDecoder* attribute holding a reference to type decoder object. Refer to the source for API details. pyasn1-0.4.8/pyasn1/0000775006321400632140000000000013564027341015620 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/__init__.py0000644006321400632140000000025713551772543017742 0ustar ietingofietingof00000000000000import sys # https://www.python.org/dev/peps/pep-0396/ __version__ = '0.4.8' if sys.version_info[:2] < (2, 4): raise RuntimeError('PyASN1 requires Python 2.4 or later') pyasn1-0.4.8/pyasn1/codec/0000775006321400632140000000000013564027341016675 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/codec/__init__.py0000644006321400632140000000007313551772543021013 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/codec/ber/0000775006321400632140000000000013564027341017445 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/codec/ber/__init__.py0000644006321400632140000000007313551772543021563 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/codec/ber/decoder.py0000644006321400632140000016447413551772543021451 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1 import debug from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.compat.integer import from_bytes from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null 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__ = ['decode'] LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER) noValue = base.noValue class AbstractDecoder(object): protoComponent = None def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,)) def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) class AbstractSimpleDecoder(AbstractDecoder): @staticmethod def substrateCollector(asn1Object, substrate, length): return substrate[:length], substrate[length:] 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 ExplicitTagDecoder(AbstractSimpleDecoder): protoComponent = univ.Any('') def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: return substrateFun( self._createComponent(asn1Spec, tagSet, '', **options), substrate, length ) head, tail = substrate[:length], substrate[length:] value, _ = decodeFun(head, asn1Spec, tagSet, length, **options) if LOG: LOG('explicit tag container carries %d octets of trailing payload ' '(will be lost!): %s' % (len(_), debug.hexdump(_))) return value, tail def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: return substrateFun( self._createComponent(asn1Spec, tagSet, '', **options), substrate, length ) value, substrate = decodeFun(substrate, asn1Spec, tagSet, length, **options) eooMarker, substrate = decodeFun(substrate, allowEoo=True, **options) if eooMarker is eoo.endOfOctets: return value, substrate else: raise error.PyAsn1Error('Missing end-of-octets terminator') explicitTagDecoder = ExplicitTagDecoder() class IntegerDecoder(AbstractSimpleDecoder): 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') head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0, **options), tail value = from_bytes(head, signed=True) return self._createComponent(asn1Spec, tagSet, value, **options), tail class BooleanDecoder(IntegerDecoder): protoComponent = univ.Boolean(0) def _createComponent(self, asn1Spec, tagSet, value, **options): return IntegerDecoder._createComponent( self, asn1Spec, tagSet, value and 1 or 0, **options) class BitStringDecoder(AbstractSimpleDecoder): protoComponent = univ.BitString(()) supportConstructedForm = True def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): head, tail = substrate[:length], substrate[length:] if substrateFun: return substrateFun(self._createComponent( asn1Spec, tagSet, noValue, **options), substrate, length) if not head: raise error.PyAsn1Error('Empty BIT STRING substrate') if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? trailingBits = oct2int(head[0]) if trailingBits > 7: raise error.PyAsn1Error( 'Trailing bits overflow %s' % trailingBits ) value = self.protoComponent.fromOctetString( head[1:], internalFormat=True, padding=trailingBits) return self._createComponent(asn1Spec, tagSet, value, **options), tail 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(null, internalFormat=True) while head: component, head = decodeFun(head, self.protoComponent, substrateFun=substrateFun, **options) trailingBits = oct2int(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 ) return self._createComponent(asn1Spec, tagSet, bitString, **options), tail def indefLenValueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): if substrateFun: return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length) # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector bitString = self.protoComponent.fromOctetString(null, internalFormat=True) while substrate: component, substrate = decodeFun(substrate, self.protoComponent, substrateFun=substrateFun, allowEoo=True, **options) if component is eoo.endOfOctets: break trailingBits = oct2int(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 ) else: raise error.SubstrateUnderrunError('No EOO seen before substrate ends') return self._createComponent(asn1Spec, tagSet, bitString, **options), substrate class OctetStringDecoder(AbstractSimpleDecoder): protoComponent = univ.OctetString('') supportConstructedForm = True def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): head, tail = substrate[:length], substrate[length:] if substrateFun: return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length) if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? return self._createComponent(asn1Spec, tagSet, head, **options), tail 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 = null while head: component, head = decodeFun(head, self.protoComponent, substrateFun=substrateFun, **options) header += component return self._createComponent(asn1Spec, tagSet, header, **options), tail 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) return substrateFun(asn1Object, substrate, length) # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector header = null while substrate: component, substrate = decodeFun(substrate, self.protoComponent, substrateFun=substrateFun, allowEoo=True, **options) if component is eoo.endOfOctets: break header += component else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) return self._createComponent(asn1Spec, tagSet, header, **options), substrate class NullDecoder(AbstractSimpleDecoder): 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') head, tail = substrate[:length], substrate[length:] component = self._createComponent(asn1Spec, tagSet, '', **options) if head: raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length) return component, tail class ObjectIdentifierDecoder(AbstractSimpleDecoder): 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') head, tail = substrate[:length], substrate[length:] if not head: raise error.PyAsn1Error('Empty substrate') head = octs2ints(head) oid = () index = 0 substrateLen = len(head) while index < substrateLen: subId = head[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 = head[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' % head[0]) return self._createComponent(asn1Spec, tagSet, oid, **options), tail class RealDecoder(AbstractSimpleDecoder): 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') head, tail = substrate[:length], substrate[length:] if not head: return self._createComponent(asn1Spec, tagSet, 0.0, **options), tail fo = oct2int(head[0]) head = head[1:] if fo & 0x80: # binary encoding if not head: raise error.PyAsn1Error("Incomplete floating-point value") if LOG: LOG('decoding binary encoded REAL') n = (fo & 0x03) + 1 if n == 4: n = oct2int(head[0]) head = head[1:] eo, head = head[:n], head[n:] if not eo or not head: raise error.PyAsn1Error('Real exponent screwed') e = oct2int(eo[0]) & 0x80 and -1 or 0 while eo: # exponent e <<= 8 e |= oct2int(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 head: # value p <<= 8 p |= oct2int(head[0]) head = head[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 head: raise error.PyAsn1Error("Incomplete floating-point value") if LOG: LOG('decoding character encoded REAL') try: if fo & 0x3 == 0x1: # NR1 value = (int(head), 10, 0) elif fo & 0x3 == 0x2: # NR2 value = float(head) elif fo & 0x3 == 0x3: # NR3 value = float(head) 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 ) return self._createComponent(asn1Spec, tagSet, value, **options), tail class AbstractConstructedDecoder(AbstractDecoder): protoComponent = None class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): protoRecordComponent = None protoSequenceComponent = None def _getComponentTagMap(self, asn1Object, idx): raise NotImplementedError() def _getComponentPositionByType(self, asn1Object, tagSet, idx): raise NotImplementedError() def _decodeComponents(self, substrate, tagSet=None, decodeFun=None, **options): components = [] componentTypes = set() while substrate: component, substrate = decodeFun(substrate, **options) if 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 ) return asn1Object, substrate 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') head, tail = substrate[:length], substrate[length:] 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 return substrateFun(asn1Object, substrate, length) if asn1Spec is None: asn1Object, trailing = self._decodeComponents( head, tagSet=tagSet, decodeFun=decodeFun, **options ) if trailing: if LOG: LOG('Unused trailing %d octets encountered: %s' % ( len(trailing), debug.hexdump(trailing))) return asn1Object, tail asn1Object = asn1Spec.clone() asn1Object.clear() 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 head: 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,) ) component, head = decodeFun(head, componentType, **options) 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): component, rest = decodeFun( containerValue[pos].asOctets(), asn1Spec=openType, **options ) containerValue[pos] = component else: component, rest = decodeFun( asn1Object.getComponentByPosition(idx).asOctets(), asn1Spec=openType, **options ) asn1Object.setComponentByPosition(idx, component) else: inconsistency = asn1Object.isInconsistent if inconsistency: raise inconsistency else: asn1Object = asn1Spec.clone() asn1Object.clear() componentType = asn1Spec.componentType if LOG: LOG('decoding type %r chosen by given `asn1Spec`' % componentType) idx = 0 while head: component, head = decodeFun(head, componentType, **options) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) idx += 1 return asn1Object, tail 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 return substrateFun(asn1Object, substrate, length) if asn1Spec is None: return self._decodeComponents( substrate, tagSet=tagSet, decodeFun=decodeFun, **dict(options, allowEoo=True) ) asn1Object = asn1Spec.clone() asn1Object.clear() 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 substrate: 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,) ) component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options) 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 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) 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): component, rest = decodeFun( containerValue[pos].asOctets(), asn1Spec=openType, **dict(options, allowEoo=True) ) containerValue[pos] = component else: component, rest = decodeFun( asn1Object.getComponentByPosition(idx).asOctets(), asn1Spec=openType, **dict(options, allowEoo=True) ) if component is not eoo.endOfOctets: asn1Object.setComponentByPosition(idx, component) else: inconsistency = asn1Object.isInconsistent if inconsistency: raise inconsistency else: asn1Object = asn1Spec.clone() asn1Object.clear() componentType = asn1Spec.componentType if LOG: LOG('decoding type %r chosen by given `asn1Spec`' % componentType) idx = 0 while substrate: component, substrate = decodeFun(substrate, componentType, allowEoo=True, **options) if component is eoo.endOfOctets: break asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, matchTags=False, matchConstraints=False ) idx += 1 else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) return asn1Object, substrate class SequenceOrSequenceOfDecoder(UniversalConstructedTypeDecoder): protoRecordComponent = univ.Sequence() protoSequenceComponent = univ.SequenceOf() class SequenceDecoder(SequenceOrSequenceOfDecoder): protoComponent = univ.Sequence() class SequenceOfDecoder(SequenceOrSequenceOfDecoder): protoComponent = univ.SequenceOf() class SetOrSetOfDecoder(UniversalConstructedTypeDecoder): protoRecordComponent = univ.Set() protoSequenceComponent = univ.SetOf() class SetDecoder(SetOrSetOfDecoder): protoComponent = univ.Set() class SetOfDecoder(SetOrSetOfDecoder): protoComponent = univ.SetOf() class ChoiceDecoder(AbstractConstructedDecoder): protoComponent = univ.Choice() def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): head, tail = substrate[:length], substrate[length:] if asn1Spec is None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: asn1Object = asn1Spec.clone() if substrateFun: return substrateFun(asn1Object, substrate, length) if asn1Object.tagSet == tagSet: if LOG: LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,)) component, head = decodeFun( head, asn1Object.componentTagMap, **options ) else: if LOG: LOG('decoding %s as untagged CHOICE' % (tagSet,)) component, head = decodeFun( head, asn1Object.componentTagMap, tagSet, length, state, **options ) 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 ) return asn1Object, tail 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: return substrateFun(asn1Object, substrate, length) if asn1Object.tagSet == tagSet: if LOG: LOG('decoding %s as explicitly tagged CHOICE' % (tagSet,)) component, substrate = decodeFun( substrate, asn1Object.componentType.tagMapUnique, **options ) # eat up EOO marker eooMarker, substrate = decodeFun( substrate, allowEoo=True, **options ) if eooMarker is not eoo.endOfOctets: raise error.PyAsn1Error('No EOO seen before substrate ends') else: if LOG: LOG('decoding %s as untagged CHOICE' % (tagSet,)) component, substrate = decodeFun( substrate, asn1Object.componentType.tagMapUnique, tagSet, length, state, **options ) 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 ) return asn1Object, substrate class AnyDecoder(AbstractSimpleDecoder): 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: fullSubstrate = options['fullSubstrate'] # untagged Any container, recover inner header substrate length += len(fullSubstrate) - len(substrate) substrate = fullSubstrate if LOG: LOG('decoding as untagged ANY, substrate %s' % debug.hexdump(substrate)) if substrateFun: return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length) head, tail = substrate[:length], substrate[length:] return self._createComponent(asn1Spec, tagSet, head, **options), tail 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 header = null if LOG: LOG('decoding as tagged ANY') else: fullSubstrate = options['fullSubstrate'] # untagged Any, recover header substrate header = fullSubstrate[:-len(substrate)] if LOG: LOG('decoding as untagged ANY, header substrate %s' % debug.hexdump(header)) # 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) return substrateFun(asn1Object, header + substrate, length + len(header)) if LOG: LOG('assembling constructed serialization') # All inner fragments are of the same type, treat them as octet string substrateFun = self.substrateCollector while substrate: component, substrate = decodeFun(substrate, asn1Spec, substrateFun=substrateFun, allowEoo=True, **options) if component is eoo.endOfOctets: break header += component else: raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) if substrateFun: return header, substrate else: return self._createComponent(asn1Spec, tagSet, header, **options), substrate # character string types class UTF8StringDecoder(OctetStringDecoder): protoComponent = char.UTF8String() class NumericStringDecoder(OctetStringDecoder): protoComponent = char.NumericString() class PrintableStringDecoder(OctetStringDecoder): protoComponent = char.PrintableString() class TeletexStringDecoder(OctetStringDecoder): protoComponent = char.TeletexString() class VideotexStringDecoder(OctetStringDecoder): protoComponent = char.VideotexString() class IA5StringDecoder(OctetStringDecoder): protoComponent = char.IA5String() class GraphicStringDecoder(OctetStringDecoder): protoComponent = char.GraphicString() class VisibleStringDecoder(OctetStringDecoder): protoComponent = char.VisibleString() class GeneralStringDecoder(OctetStringDecoder): protoComponent = char.GeneralString() class UniversalStringDecoder(OctetStringDecoder): protoComponent = char.UniversalString() class BMPStringDecoder(OctetStringDecoder): protoComponent = char.BMPString() # "useful" types class ObjectDescriptorDecoder(OctetStringDecoder): protoComponent = useful.ObjectDescriptor() class GeneralizedTimeDecoder(OctetStringDecoder): protoComponent = useful.GeneralizedTime() class UTCTimeDecoder(OctetStringDecoder): protoComponent = useful.UTCTime() tagMap = { univ.Integer.tagSet: IntegerDecoder(), univ.Boolean.tagSet: BooleanDecoder(), univ.BitString.tagSet: BitStringDecoder(), univ.OctetString.tagSet: OctetStringDecoder(), univ.Null.tagSet: NullDecoder(), univ.ObjectIdentifier.tagSet: ObjectIdentifierDecoder(), univ.Enumerated.tagSet: IntegerDecoder(), univ.Real.tagSet: RealDecoder(), univ.Sequence.tagSet: SequenceOrSequenceOfDecoder(), # conflicts with SequenceOf univ.Set.tagSet: SetOrSetOfDecoder(), # conflicts with SetOf univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any # character string types char.UTF8String.tagSet: UTF8StringDecoder(), char.NumericString.tagSet: NumericStringDecoder(), char.PrintableString.tagSet: PrintableStringDecoder(), char.TeletexString.tagSet: TeletexStringDecoder(), char.VideotexString.tagSet: VideotexStringDecoder(), char.IA5String.tagSet: IA5StringDecoder(), char.GraphicString.tagSet: GraphicStringDecoder(), char.VisibleString.tagSet: VisibleStringDecoder(), char.GeneralString.tagSet: GeneralStringDecoder(), char.UniversalString.tagSet: UniversalStringDecoder(), char.BMPString.tagSet: BMPStringDecoder(), # useful types useful.ObjectDescriptor.tagSet: ObjectDescriptorDecoder(), useful.GeneralizedTime.tagSet: GeneralizedTimeDecoder(), useful.UTCTime.tagSet: UTCTimeDecoder() } # Type-to-codec map for ambiguous ASN.1 types typeMap = { univ.Set.typeId: SetDecoder(), univ.SetOf.typeId: SetOfDecoder(), univ.Sequence.typeId: SequenceDecoder(), univ.SequenceOf.typeId: SequenceOfDecoder(), univ.Choice.typeId: ChoiceDecoder(), univ.Any.typeId: AnyDecoder() } # Put in non-ambiguous types for faster codec lookup for typeDecoder in tagMap.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in typeMap: typeMap[typeId] = typeDecoder (stDecodeTag, stDecodeLength, stGetValueDecoder, stGetValueDecoderByAsn1Spec, stGetValueDecoderByTag, stTryAsExplicitTag, stDecodeValue, stDumpRawValue, stErrorCondition, stStop) = [x for x in range(10)] class Decoder(object): defaultErrorState = stErrorCondition #defaultErrorState = stDumpRawValue defaultRawDecoder = AnyDecoder() supportIndefLength = True # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap={}): self.__tagMap = tagMap self.__typeMap = typeMap # Tag & TagSet objects caches self.__tagCache = {} self.__tagSetCache = {} self.__eooSentinel = ints2octs((0, 0)) def __call__(self, substrate, asn1Spec=None, tagSet=None, length=None, state=stDecodeTag, decodeFun=None, substrateFun=None, **options): if LOG: LOG('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate))) allowEoo = options.pop('allowEoo', False) # Look for end-of-octets sentinel if allowEoo and self.supportIndefLength: if substrate[:2] == self.__eooSentinel: if LOG: LOG('end-of-octets sentinel found') return eoo.endOfOctets, substrate[2:] value = noValue tagMap = self.__tagMap typeMap = self.__typeMap tagCache = self.__tagCache tagSetCache = self.__tagSetCache fullSubstrate = substrate while state is not stStop: if state is stDecodeTag: if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on tag decoding' ) # Decode tag isShortTag = True firstOctet = substrate[0] substrate = substrate[1:] try: lastTag = tagCache[firstOctet] except KeyError: integerTag = oct2int(firstOctet) tagClass = integerTag & 0xC0 tagFormat = integerTag & 0x20 tagId = integerTag & 0x1F if tagId == 0x1F: isShortTag = False lengthOctetIdx = 0 tagId = 0 try: while True: integerTag = oct2int(substrate[lengthOctetIdx]) lengthOctetIdx += 1 tagId <<= 7 tagId |= (integerTag & 0x7F) if not integerTag & 0x80: break substrate = substrate[lengthOctetIdx:] except IndexError: raise error.SubstrateUnderrunError( 'Short octet stream on long tag decoding' ) 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 if not substrate: raise error.SubstrateUnderrunError( 'Short octet stream on length decoding' ) firstOctet = oct2int(substrate[0]) if firstOctet < 128: size = 1 length = firstOctet elif firstOctet > 128: size = firstOctet & 0x7F # encoded in size bytes encodedLength = octs2ints(substrate[1:size + 1]) # 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: size = 1 length = -1 substrate = substrate[size:] if length == -1: if not self.supportIndefLength: raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') else: if len(substrate) < length: raise error.SubstrateUnderrunError('%d-octet short' % (length - len(substrate))) state = stGetValueDecoder if LOG: LOG('value length decoded into %d, payload substrate is: %s' % (length, debug.hexdump(length == -1 and substrate or substrate[: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 substrateFun = lambda a, b, c: (a, b[:c]) options.update(fullSubstrate=fullSubstrate) if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun, **options ) else: value, substrate = concreteDecoder.valueDecoder( substrate, asn1Spec, tagSet, length, stGetValueDecoder, self, substrateFun, **options ) if LOG: LOG('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or value, substrate and debug.hexdump(substrate) or '')) 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 = explicitTagDecoder 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) return value, substrate #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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 #: #: 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(tagMap, typeMap) # XXX # non-recursive decoding; return position rather than substrate pyasn1-0.4.8/pyasn1/codec/ber/encoder.py0000644006321400632140000006613513551772543021456 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys from pyasn1 import debug from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.compat.integer import to_bytes from pyasn1.compat.octets import (int2oct, oct2int, ints2octs, null, str2octs, isOctetsType) 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): supportIndefLenMode = True # An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)` eooIntegerSubstrate = (0, 0) eooOctetsSubstrate = ints2octs(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 = null 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: exc = sys.exc_info() raise error.PyAsn1Error( 'Error encoding %r: %s' % (value, exc[1])) 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(ints2octs(header)))) header += self.encodeLength(len(substrate), defModeOverride) if LOG: LOG('encoded %s octets (tag + payload) into %s' % ( len(substrate), debug.hexdump(ints2octs(header)))) if isOctets: substrate = ints2octs(header) + substrate if not defModeOverride: substrate += self.eooOctetsSubstrate else: substrate = header + substrate if not defModeOverride: substrate += self.eooIntegerSubstrate if not isOctets: substrate = ints2octs(substrate) return substrate class EndOfOctetsEncoder(AbstractItemEncoder): def encodeValue(self, value, asn1Spec, encodeFun, **options): return null, 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 int2oct(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 = null 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 isOctetsType(value): 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 isOctetsType(value): 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 = null 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 null, 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 RealEncoder(AbstractItemEncoder): supportIndefLenMode = 0 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 null, False, True if b == 10: if LOG: LOG('encoding REAL into character form') return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', 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 = null if e == 0 or e == -1: eo = int2oct(e & 0xff) else: while e not in (0, -1): eo = int2oct(e & 0xff) + eo e >>= 8 if e == 0 and eo and oct2int(eo[0]) & 0x80: eo = int2oct(0) + eo if e == -1 and eo and not (oct2int(eo[0]) & 0x80): eo = int2oct(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 = int2oct(n & 0xff) + eo po = null while m: po = int2oct(m & 0xff) + po m >>= 8 substrate = int2oct(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 = null 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 inconsistency 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 inconsistency 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 null.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 isOctetsType(value): value = asn1Spec.clone(value).asOctets() return value, not options.get('defMode', True), True tagMap = { 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.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 typeMap = { 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.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 Encoder(object): fixedDefLengthMode = None fixedChunkSize = None # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap={}): self.__tagMap = tagMap self.__typeMap = typeMap 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 #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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(tagMap, typeMap) pyasn1-0.4.8/pyasn1/codec/ber/eoo.py0000644006321400632140000000116213551772543020606 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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() pyasn1-0.4.8/pyasn1/codec/cer/0000775006321400632140000000000013564027341017446 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/codec/cer/__init__.py0000644006321400632140000000007313551772543021564 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/codec/cer/decoder.py0000644006321400632140000000724113551772543021436 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1 import error from pyasn1.codec.ber import decoder from pyasn1.compat.octets import oct2int from pyasn1.type import univ __all__ = ['decode'] class BooleanDecoder(decoder.AbstractSimpleDecoder): protoComponent = univ.Boolean(0) def valueDecoder(self, substrate, asn1Spec, tagSet=None, length=None, state=None, decodeFun=None, substrateFun=None, **options): head, tail = substrate[:length], substrate[length:] if not head or length != 1: raise error.PyAsn1Error('Not single-octet Boolean payload') byte = oct2int(head[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) return self._createComponent(asn1Spec, tagSet, value, **options), tail # TODO: prohibit non-canonical encoding BitStringDecoder = decoder.BitStringDecoder OctetStringDecoder = decoder.OctetStringDecoder RealDecoder = decoder.RealDecoder tagMap = decoder.tagMap.copy() tagMap.update( {univ.Boolean.tagSet: BooleanDecoder(), univ.BitString.tagSet: BitStringDecoder(), univ.OctetString.tagSet: OctetStringDecoder(), univ.Real.tagSet: RealDecoder()} ) typeMap = decoder.typeMap.copy() # Put in non-ambiguous types for faster codec lookup for typeDecoder in tagMap.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in typeMap: typeMap[typeId] = typeDecoder class Decoder(decoder.Decoder): pass #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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(tagMap, decoder.typeMap) pyasn1-0.4.8/pyasn1/codec/cer/encoder.py0000644006321400632140000002230113551772543021442 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1 import error from pyasn1.codec.ber import encoder from pyasn1.compat.octets import str2octs, null from pyasn1.type import univ from pyasn1.type import useful __all__ = ['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 = str2octs('\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 null.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 null, True, True chunks = self._encodeComponents( value, asn1Spec, encodeFun, **options) return null.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 = null comps = [] compsMap = {} if asn1Spec is None: # instance of ASN.1 schema inconsistency = value.isInconsistent if inconsistency: raise inconsistency 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 tagMap = encoder.tagMap.copy() tagMap.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() }) typeMap = encoder.typeMap.copy() typeMap.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 Encoder(encoder.Encoder): fixedDefLengthMode = False fixedChunkSize = 1000 #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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(tagMap, typeMap) # EncoderFactory queries class instance and builds a map of tags -> encoders pyasn1-0.4.8/pyasn1/codec/der/0000775006321400632140000000000013564027341017447 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/codec/der/__init__.py0000644006321400632140000000007313551772543021565 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/codec/der/decoder.py0000644006321400632140000000524213551772543021436 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1.codec.cer import decoder from pyasn1.type import univ __all__ = ['decode'] class BitStringDecoder(decoder.BitStringDecoder): supportConstructedForm = False class OctetStringDecoder(decoder.OctetStringDecoder): supportConstructedForm = False # TODO: prohibit non-canonical encoding RealDecoder = decoder.RealDecoder tagMap = decoder.tagMap.copy() tagMap.update( {univ.BitString.tagSet: BitStringDecoder(), univ.OctetString.tagSet: OctetStringDecoder(), univ.Real.tagSet: RealDecoder()} ) typeMap = decoder.typeMap.copy() # Put in non-ambiguous types for faster codec lookup for typeDecoder in tagMap.values(): if typeDecoder.protoComponent is not None: typeId = typeDecoder.protoComponent.__class__.typeId if typeId is not None and typeId not in typeMap: typeMap[typeId] = typeDecoder class Decoder(decoder.Decoder): supportIndefLength = False #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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(tagMap, typeMap) pyasn1-0.4.8/pyasn1/codec/der/encoder.py0000644006321400632140000000600113551772543021442 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1 import error from pyasn1.codec.cer import encoder from pyasn1.type import univ __all__ = ['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 tagMap = encoder.tagMap.copy() tagMap.update({ # Set & SetOf have same tags univ.Set.tagSet: SetEncoder() }) typeMap = encoder.typeMap.copy() typeMap.update({ # Set & SetOf have same tags univ.Set.typeId: SetEncoder() }) class Encoder(encoder.Encoder): fixedDefLengthMode = True fixedChunkSize = 0 #: 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` (Python 3) or :py:class:`str` (Python 2) #: 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(tagMap, typeMap) pyasn1-0.4.8/pyasn1/codec/native/0000775006321400632140000000000013564027341020163 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/codec/native/__init__.py0000644006321400632140000000007313551772543022301 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/codec/native/decoder.py0000644006321400632140000001676713551772543022170 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1 import debug from pyasn1 import error 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 AbstractScalarDecoder(object): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(pyObject) class BitStringDecoder(AbstractScalarDecoder): def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject)) class SequenceOrSetDecoder(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 SequenceOfOrSetOfDecoder(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 ChoiceDecoder(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 tagMap = { univ.Integer.tagSet: AbstractScalarDecoder(), univ.Boolean.tagSet: AbstractScalarDecoder(), univ.BitString.tagSet: BitStringDecoder(), univ.OctetString.tagSet: AbstractScalarDecoder(), univ.Null.tagSet: AbstractScalarDecoder(), univ.ObjectIdentifier.tagSet: AbstractScalarDecoder(), univ.Enumerated.tagSet: AbstractScalarDecoder(), univ.Real.tagSet: AbstractScalarDecoder(), univ.Sequence.tagSet: SequenceOrSetDecoder(), # conflicts with SequenceOf univ.Set.tagSet: SequenceOrSetDecoder(), # conflicts with SetOf univ.Choice.tagSet: ChoiceDecoder(), # conflicts with Any # character string types char.UTF8String.tagSet: AbstractScalarDecoder(), char.NumericString.tagSet: AbstractScalarDecoder(), char.PrintableString.tagSet: AbstractScalarDecoder(), char.TeletexString.tagSet: AbstractScalarDecoder(), char.VideotexString.tagSet: AbstractScalarDecoder(), char.IA5String.tagSet: AbstractScalarDecoder(), char.GraphicString.tagSet: AbstractScalarDecoder(), char.VisibleString.tagSet: AbstractScalarDecoder(), char.GeneralString.tagSet: AbstractScalarDecoder(), char.UniversalString.tagSet: AbstractScalarDecoder(), char.BMPString.tagSet: AbstractScalarDecoder(), # useful types useful.ObjectDescriptor.tagSet: AbstractScalarDecoder(), useful.GeneralizedTime.tagSet: AbstractScalarDecoder(), useful.UTCTime.tagSet: AbstractScalarDecoder() } # Put in ambiguous & non-ambiguous types for faster codec lookup typeMap = { univ.Integer.typeId: AbstractScalarDecoder(), univ.Boolean.typeId: AbstractScalarDecoder(), univ.BitString.typeId: BitStringDecoder(), univ.OctetString.typeId: AbstractScalarDecoder(), univ.Null.typeId: AbstractScalarDecoder(), univ.ObjectIdentifier.typeId: AbstractScalarDecoder(), univ.Enumerated.typeId: AbstractScalarDecoder(), univ.Real.typeId: AbstractScalarDecoder(), # ambiguous base types univ.Set.typeId: SequenceOrSetDecoder(), univ.SetOf.typeId: SequenceOfOrSetOfDecoder(), univ.Sequence.typeId: SequenceOrSetDecoder(), univ.SequenceOf.typeId: SequenceOfOrSetOfDecoder(), univ.Choice.typeId: ChoiceDecoder(), univ.Any.typeId: AbstractScalarDecoder(), # character string types char.UTF8String.typeId: AbstractScalarDecoder(), char.NumericString.typeId: AbstractScalarDecoder(), char.PrintableString.typeId: AbstractScalarDecoder(), char.TeletexString.typeId: AbstractScalarDecoder(), char.VideotexString.typeId: AbstractScalarDecoder(), char.IA5String.typeId: AbstractScalarDecoder(), char.GraphicString.typeId: AbstractScalarDecoder(), char.VisibleString.typeId: AbstractScalarDecoder(), char.GeneralString.typeId: AbstractScalarDecoder(), char.UniversalString.typeId: AbstractScalarDecoder(), char.BMPString.typeId: AbstractScalarDecoder(), # useful types useful.ObjectDescriptor.typeId: AbstractScalarDecoder(), useful.GeneralizedTime.typeId: AbstractScalarDecoder(), useful.UTCTime.typeId: AbstractScalarDecoder() } class Decoder(object): # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap): self.__tagMap = tagMap self.__typeMap = typeMap 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 #: 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(tagMap, typeMap) pyasn1-0.4.8/pyasn1/codec/native/encoder.py0000644006321400632140000001750213551772543022166 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: from collections import OrderedDict except ImportError: OrderedDict = dict from pyasn1 import debug from pyasn1 import error 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 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 inconsistency 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 inconsistency return [encodeFun(x, **options) for x in value] class ChoiceEncoder(SequenceEncoder): pass class AnyEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return value.asOctets() tagMap = { 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.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 typeMap = { 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.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 Encoder(object): # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap={}): self.__tagMap = tagMap self.__typeMap = typeMap 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 #: 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` #: can be produced (whenever available) 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 = Encoder(tagMap, typeMap) pyasn1-0.4.8/pyasn1/compat/0000775006321400632140000000000013564027341017103 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/compat/__init__.py0000644006321400632140000000007313551772543021221 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/compat/binary.py0000644006321400632140000000127213551772543020750 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from sys import version_info if version_info[0:2] < (2, 6): def bin(value): bitstring = [] if value > 0: prefix = '0b' elif value < 0: prefix = '-0b' value = abs(value) else: prefix = '0b0' while value: if value & 1 == 1: bitstring.append('1') else: bitstring.append('0') value >>= 1 bitstring.reverse() return prefix + ''.join(bitstring) else: bin = bin pyasn1-0.4.8/pyasn1/compat/calling.py0000644006321400632140000000057313551772543021100 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from sys import version_info __all__ = ['callable'] if (2, 7) < version_info[:2] < (3, 2): import collections def callable(x): return isinstance(x, collections.Callable) else: callable = callable pyasn1-0.4.8/pyasn1/compat/dateandtime.py0000644006321400632140000000074213551772543021744 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import time from datetime import datetime from sys import version_info __all__ = ['strptime'] if version_info[:2] <= (2, 4): def strptime(text, dateFormat): return datetime(*(time.strptime(text, dateFormat)[0:6])) else: def strptime(text, dateFormat): return datetime.strptime(text, dateFormat) pyasn1-0.4.8/pyasn1/compat/integer.py0000644006321400632140000000565413551772543021131 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import platform implementation = platform.python_implementation() except (ImportError, AttributeError): implementation = 'CPython' from pyasn1.compat.octets import oct2int, null, ensureString if sys.version_info[0:2] < (3, 2) or implementation != 'CPython': from binascii import a2b_hex, b2a_hex if sys.version_info[0] > 2: long = int def from_bytes(octets, signed=False): if not octets: return 0 value = long(b2a_hex(ensureString(octets)), 16) if signed and oct2int(octets[0]) & 0x80: return value - (1 << len(octets) * 8) return value def to_bytes(value, signed=False, length=0): if value < 0: if signed: bits = bitLength(value) # two's complement form maxValue = 1 << bits valueToEncode = (value + maxValue) % maxValue else: raise OverflowError('can\'t convert negative int to unsigned') elif value == 0 and length == 0: return null else: bits = 0 valueToEncode = value hexValue = hex(valueToEncode)[2:] if hexValue.endswith('L'): hexValue = hexValue[:-1] if len(hexValue) & 1: hexValue = '0' + hexValue # padding may be needed for two's complement encoding if value != valueToEncode or length: hexLength = len(hexValue) * 4 padLength = max(length, bits) if padLength > hexLength: hexValue = '00' * ((padLength - hexLength - 1) // 8 + 1) + hexValue elif length and hexLength - length > 7: raise OverflowError('int too big to convert') firstOctet = int(hexValue[:2], 16) if signed: if firstOctet & 0x80: if value >= 0: hexValue = '00' + hexValue elif value < 0: hexValue = 'ff' + hexValue octets_value = a2b_hex(hexValue) return octets_value def bitLength(number): # bits in unsigned number hexValue = hex(abs(number)) bits = len(hexValue) - 2 if hexValue.endswith('L'): bits -= 1 if bits & 1: bits += 1 bits *= 4 # TODO: strip lhs zeros return bits else: def from_bytes(octets, signed=False): return int.from_bytes(bytes(octets), 'big', signed=signed) 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) def bitLength(number): return int(number).bit_length() pyasn1-0.4.8/pyasn1/compat/octets.py0000644006321400632140000000251713551772543020770 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from sys import version_info if version_info[0] <= 2: int2oct = chr # noinspection PyPep8 ints2octs = lambda s: ''.join([int2oct(x) for x in s]) null = '' oct2int = ord # TODO: refactor to return a sequence of ints # noinspection PyPep8 octs2ints = lambda s: [oct2int(x) for x in s] # noinspection PyPep8 str2octs = lambda x: x # noinspection PyPep8 octs2str = lambda x: x # noinspection PyPep8 isOctetsType = lambda s: isinstance(s, str) # noinspection PyPep8 isStringType = lambda s: isinstance(s, (str, unicode)) # noinspection PyPep8 ensureString = str else: ints2octs = bytes # noinspection PyPep8 int2oct = lambda x: ints2octs((x,)) null = ints2octs() # noinspection PyPep8 oct2int = lambda x: x # noinspection PyPep8 octs2ints = lambda x: x # noinspection PyPep8 str2octs = lambda x: x.encode('iso-8859-1') # noinspection PyPep8 octs2str = lambda x: x.decode('iso-8859-1') # noinspection PyPep8 isOctetsType = lambda s: isinstance(s, bytes) # noinspection PyPep8 isStringType = lambda s: isinstance(s, str) # noinspection PyPep8 ensureString = bytes pyasn1-0.4.8/pyasn1/compat/string.py0000644006321400632140000000077113551772543020775 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from sys import version_info if version_info[:2] <= (2, 5): def partition(string, sep): try: a, c = string.split(sep, 1) except ValueError: a, b, c = string, '', '' else: b = sep return a, b, c else: def partition(string, sep): return string.partition(sep) pyasn1-0.4.8/pyasn1/debug.py0000644006321400632140000000721613551772543017273 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import logging import sys from pyasn1 import __version__ from pyasn1 import error from pyasn1.compat.octets import octs2ints __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 '' if hasattr(logging, 'NullHandler'): NullHandler = logging.NullHandler else: # Python 2.6 and older class NullHandler(logging.Handler): def emit(self, record): pass 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=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)), octs2ints(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() pyasn1-0.4.8/pyasn1/error.py0000644006321400632140000000432113551772543017330 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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. """ 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 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. """ pyasn1-0.4.8/pyasn1/type/0000775006321400632140000000000013564027341016601 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1/type/__init__.py0000644006321400632140000000007313551772543020717 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/pyasn1/type/base.py0000644006321400632140000005356213551772543020105 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys from pyasn1 import error from pyasn1.compat import calling 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 = set( ('__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 calling.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: exType, exValue, exTb = sys.exc_info() raise exType('%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): return self is other and True or 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 if sys.version_info[0] <= 2: def __nonzero__(self): return self._value and True or False else: def __bool__(self): return self._value and True or False 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 if sys.version_info[0] <= 2: def __nonzero__(self): return bool(self.components) else: 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 pyasn1-0.4.8/pyasn1/type/char.py0000644006321400632140000002620513551772543020102 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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 Python 2 :class:`str` or Python 3 :class:`bytes`. When used in octet-stream context, |ASN.1| type assumes "|encoding|" encoding. Keyword Args ------------ value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object :class:`unicode` object (Python 2) or :class:`str` (Python 3), alternatively :class:`str` (Python 2) or :class:`bytes` (Python 3) 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:`unicode` (Python 2) or :class:`str` (Python 3) 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. """ if sys.version_info[0] <= 2: def __str__(self): try: # `str` is Py2 text representation return self._value.encode(self.encoding) except UnicodeEncodeError: exc = sys.exc_info()[1] raise error.PyAsn1UnicodeEncodeError( "Can't encode string '%s' with codec " "%s" % (self._value, self.encoding), exc ) def __unicode__(self): return unicode(self._value) def prettyIn(self, value): try: if isinstance(value, unicode): return value elif isinstance(value, str): return value.decode(self.encoding) elif isinstance(value, (tuple, list)): return self.prettyIn(''.join([chr(x) for x in value])) elif isinstance(value, univ.OctetString): return value.asOctets().decode(self.encoding) else: return unicode(value) except (UnicodeDecodeError, LookupError): exc = sys.exc_info()[1] raise error.PyAsn1UnicodeDecodeError( "Can't decode string '%s' with codec " "%s" % (value, self.encoding), exc ) def asOctets(self, padding=True): return str(self) def asNumbers(self, padding=True): return tuple([ord(x) for x in str(self)]) else: def __str__(self): # `unicode` is Py3 text representation return str(self._value) def __bytes__(self): try: return self._value.encode(self.encoding) except UnicodeEncodeError: exc = sys.exc_info()[1] 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): exc = sys.exc_info()[1] 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() pyasn1-0.4.8/pyasn1/type/constraint.py0000664006321400632140000005316413564027254021353 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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: raise error.ValueConstraintError( '%s failed at: %r' % (self, sys.exc_info()[1]) ) 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): return self is other and True or 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 if sys.version_info[0] <= 2: def __nonzero__(self): return self._values and True or False else: def __bool__(self): return self._values and True or False 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 __sub__(self, constraint): return self.__class__(*(self._set.difference(constraint))) 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 pyasn1-0.4.8/pyasn1/type/error.py0000644006321400632140000000036613551772543020316 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # from pyasn1.error import PyAsn1Error class ValueConstraintError(PyAsn1Error): pass pyasn1-0.4.8/pyasn1/type/namedtype.py0000644006321400632140000003776013551772543021163 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys from pyasn1 import error from pyasn1.type import tag from pyasn1.type import tagmap __all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes'] try: any except NameError: any = lambda x: bool(filter(bool, x)) 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) if sys.version_info[0] <= 2: def __nonzero__(self): return self.__namedTypesLen > 0 else: 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 pyasn1-0.4.8/pyasn1/type/namedval.py0000644006321400632140000001142613551772543020753 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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),) ) pyasn1-0.4.8/pyasn1/type/opentype.py0000644006321400632140000000544013551772543021026 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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) pyasn1-0.4.8/pyasn1/type/tag.py0000644006321400632140000002241613551772543017740 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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) pyasn1-0.4.8/pyasn1/type/tagmap.py0000644006321400632140000000566613551772543020446 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/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 KeyError() 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 pyasn1-0.4.8/pyasn1/type/univ.py0000644006321400632140000032457113551772543020155 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import math import sys from pyasn1 import error from pyasn1.codec.ber import eoo from pyasn1.compat import binary from pyasn1.compat import integer from pyasn1.compat import octets 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) if sys.version_info[0] <= 2: def __div__(self, value): if isinstance(value, float): return Real(self._value / value) else: return self.clone(self._value / value) def __rdiv__(self, value): if isinstance(value, float): return Real(value / self._value) else: return self.clone(value / self._value) else: 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) if sys.version_info[0] <= 2: def __long__(self): return long(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) if sys.version_info[0:2] > (2, 5): 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: raise error.PyAsn1Error( 'Can\'t coerce %r into integer: %s' % (value, sys.exc_info()[1]) ) 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() if sys.version_info[0] < 3: SizedIntegerBase = long else: SizedIntegerBase = int class SizedInteger(SizedIntegerBase): bitLength = leadingZeroBits = None def setBitLength(self, bitLength): self.bitLength = bitLength self.leadingZeroBits = max(bitLength - integer.bitLength(self), 0) return self def __len__(self): if self.bitLength is None: self.setBitLength(integer.bitLength(self)) 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 self._value def __float__(self): return float(self._value) if sys.version_info[0] < 3: def __long__(self): return 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(octets.octs2ints(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 = binary.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: raise error.PyAsn1Error('%s.fromHexString() error: %s' % (cls.__name__, sys.exc_info()[1])) 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: raise error.PyAsn1Error('%s.fromBinaryString() error: %s' % (cls.__name__, sys.exc_info()[1])) 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:`str` (Py2) or :class:`bytes` (Py3) Text string like '\\\\x01\\\\xff' (Py2) or b'\\\\x01\\\\xff' (Py3) """ value = SizedInteger(integer.from_bytes(value) >> 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 octets.isStringType(value): 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, intTypes): return SizedInteger(value) else: raise error.PyAsn1Error( 'Bad BitString initializer type \'%s\'' % (value,) ) try: # noinspection PyStatementEffect all except NameError: # Python 2.4 # noinspection PyShadowingBuiltins def all(iterable): for element in iterable: if not element: return False return True 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 Python 2 :class:`str` or Python 3 :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:`str` (Python 2) or :class:`bytes` (Python 3), alternatively class:`unicode` object (Python 2) or :class:`str` (Python 3) 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:`unicode` (Python 2) or :class:`str` (Python 3) 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) if sys.version_info[0] <= 2: def prettyIn(self, value): if isinstance(value, str): return value elif isinstance(value, unicode): try: return value.encode(self.encoding) except (LookupError, UnicodeEncodeError): exc = sys.exc_info()[1] raise error.PyAsn1UnicodeEncodeError( "Can't encode string '%s' with codec " "%s" % (value, self.encoding), exc ) elif isinstance(value, (tuple, list)): try: return ''.join([chr(x) for x in value]) except ValueError: raise error.PyAsn1Error( "Bad %s initializer '%s'" % (self.__class__.__name__, value) ) else: return str(value) def __str__(self): return str(self._value) def __unicode__(self): try: return self._value.decode(self.encoding) except UnicodeDecodeError: exc = sys.exc_info()[1] raise error.PyAsn1UnicodeDecodeError( "Can't decode string '%s' with codec " "%s" % (self._value, self.encoding), exc ) def asOctets(self): return str(self._value) def asNumbers(self): return tuple([ord(x) for x in self._value]) else: def prettyIn(self, value): if isinstance(value, bytes): return value elif isinstance(value, str): try: return value.encode(self.encoding) except UnicodeEncodeError: exc = sys.exc_info()[1] 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: exc = sys.exc_info()[1] 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 octets.ints2octs(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 octets.ints2octs(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(octets.str2octs('')) # Optimization for faster codec lookup typeId = OctetString.getTypeId() def prettyIn(self, value): if value: return value return octets.str2octs('') if sys.version_info[0] <= 2: intTypes = (int, long) else: intTypes = (int,) numericTypes = intTypes + (float,) 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 octets.isStringType(value): if '-' in value: raise error.PyAsn1Error( '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: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) ) try: tupleOfInts = tuple([int(subOid) for subOid in value if subOid >= 0]) except (ValueError, TypeError): raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1]) ) 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 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], numericTypes) or not isinstance(value[1], intTypes) or not isinstance(value[2], intTypes)): 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, intTypes): return self.__normalizeBase10((value, 10, 0)) elif isinstance(value, float) or octets.isStringType(value): if octets.isStringType(value): 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))) if sys.version_info[0] <= 2: def __div__(self, value): return self.clone(float(self) / value) def __rdiv__(self, value): return self.clone(value / float(self)) else: 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)) if sys.version_info[0] <= 2: def __long__(self): return long(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))) if sys.version_info[0:2] > (2, 5): 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 if sys.version_info[0] <= 2: def __nonzero__(self): return bool(float(self)) else: 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: raise IndexError(sys.exc_info()[1]) def __setitem__(self, idx, value): try: self.setComponentByPosition(idx, value) except error.PyAsn1Error: raise IndexError(sys.exc_info()[1]) 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: raise ValueError(sys.exc_info()[1]) 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: exc = sys.exc_info()[1] 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 octets.isStringType(idx): try: return self.getComponentByName(idx) except error.PyAsn1Error: # duck-typing dict raise KeyError(sys.exc_info()[1]) else: try: return self.getComponentByPosition(idx) except error.PyAsn1Error: # duck-typing list raise IndexError(sys.exc_info()[1]) def __setitem__(self, idx, value): if octets.isStringType(idx): try: self.setComponentByName(idx, value) except error.PyAsn1Error: # duck-typing dict raise KeyError(sys.exc_info()[1]) else: try: self.setComponentByPosition(idx, value) except error.PyAsn1Error: # duck-typing list raise IndexError(sys.exc_info()[1]) 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: exc = sys.exc_info()[1] 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 if sys.version_info[0] <= 2: def __nonzero__(self): return self._componentValues and True or False else: def __bool__(self): return self._componentValues and True or False 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 Python 2 :class:`str` or Python 3 :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:`str` (Python 2) or :class:`bytes` (Python 3), alternatively :class:`unicode` object (Python 2) or :class:`str` (Python 3) 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:`unicode` (Python 2) or :class:`str` (Python 3) 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? pyasn1-0.4.8/pyasn1/type/useful.py0000644006321400632140000001237013551772543020466 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import datetime from pyasn1 import error from pyasn1.compat import dateandtime from pyasn1.compat import string 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 = string.partition(text, '+') else: text, plusminus, tz = string.partition(text, '-') 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 = string.partition(text, '.') else: text, _, ms = string.partition(text, ',') 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 = dateandtime.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 pyasn1-0.4.8/pyasn1.egg-info/0000775006321400632140000000000013564027341017312 5ustar ietingofietingof00000000000000pyasn1-0.4.8/pyasn1.egg-info/PKG-INFO0000644006321400632140000000277313564027341020416 0ustar ietingofietingof00000000000000Metadata-Version: 1.2 Name: pyasn1 Version: 0.4.8 Summary: ASN.1 types and codecs Home-page: https://github.com/etingof/pyasn1 Author: Ilya Etingof Author-email: etingof@gmail.com Maintainer: Ilya Etingof License: BSD Description: Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208) 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 :: 2 Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Communications Classifier: Topic :: Software Development :: Libraries :: Python Modules pyasn1-0.4.8/pyasn1.egg-info/SOURCES.txt0000644006321400632140000001241413564027341021176 0ustar ietingofietingof00000000000000CHANGES.rst LICENSE.rst MANIFEST.in README.md TODO.rst setup.cfg setup.py docs/Makefile docs/tutorial.rst docs/source/changelog.rst docs/source/conf.py docs/source/contents.rst docs/source/download.rst docs/source/example-use-case.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/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/binary.py pyasn1/compat/calling.py pyasn1/compat/dateandtime.py pyasn1/compat/integer.py pyasn1/compat/octets.py pyasn1/compat/string.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/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/compat/test_binary.py tests/compat/test_integer.py tests/compat/test_octets.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.pypyasn1-0.4.8/pyasn1.egg-info/dependency_links.txt0000644006321400632140000000000113564027341023356 0ustar ietingofietingof00000000000000 pyasn1-0.4.8/pyasn1.egg-info/top_level.txt0000644006321400632140000000000713564027341022037 0ustar ietingofietingof00000000000000pyasn1 pyasn1-0.4.8/pyasn1.egg-info/zip-safe0000644006321400632140000000000113551772550020745 0ustar ietingofietingof00000000000000 pyasn1-0.4.8/setup.cfg0000644006321400632140000000015213564027341016222 0ustar ietingofietingof00000000000000[bdist_wheel] universal = 1 [metadata] license_file = LICENSE.rst [egg_info] tag_build = tag_date = 0 pyasn1-0.4.8/setup.py0000644006321400632140000000611313551772544016126 0ustar ietingofietingof00000000000000#!/usr/bin/env python # # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import os import sys 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 :: 2 Programming Language :: Python :: 2.4 Programming Language :: Python :: 2.5 Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.2 Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Topic :: Communications Topic :: Software Development :: Libraries :: Python Modules """ def howto_install_setuptools(): print(""" Error: You need setuptools Python package! It's very easy to install it, just type: wget https://bootstrap.pypa.io/ez_setup.py python ez_setup.py Then you could make eggs from this package. """) if sys.version_info[:2] < (2, 4): print("ERROR: this package requires Python 2.4 or later!") sys.exit(1) try: from setuptools import setup, Command params = { 'zip_safe': True } except ImportError: for arg in sys.argv: if 'egg' in arg: howto_install_setuptools() sys.exit(1) from distutils.core import setup, Command params = {} params.update({ 'name': 'pyasn1', 'version': open(os.path.join('pyasn1', '__init__.py')).read().split('\'')[1], 'description': 'ASN.1 types and codecs', 'long_description': 'Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)', 'maintainer': 'Ilya Etingof ', 'author': 'Ilya Etingof', 'author_email': 'etingof@gmail.com', 'url': 'https://github.com/etingof/pyasn1', 'platforms': ['any'], 'classifiers': [x for x in classifiers.split('\n') if x], 'license': 'BSD', 'packages': ['pyasn1', 'pyasn1.type', 'pyasn1.compat', 'pyasn1.codec', 'pyasn1.codec.ber', 'pyasn1.codec.cer', 'pyasn1.codec.der', 'pyasn1.codec.native']}) # handle unittest discovery feature try: import unittest2 as unittest except ImportError: import unittest class PyTest(Command): user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): suite = unittest.TestLoader().loadTestsFromNames( ['tests.__main__.suite'] ) unittest.TextTestRunner(verbosity=2).run(suite) params['cmdclass'] = { 'test': PyTest, 'tests': PyTest, } setup(**params) pyasn1-0.4.8/tests/0000775006321400632140000000000013564027341015547 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/__init__.py0000644006321400632140000000007313551772543017665 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/__main__.py0000644006321400632140000000077213551772543017654 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/base.py0000644006321400632140000000070213551772543017037 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/0000775006321400632140000000000013564027341016624 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/codec/__init__.py0000644006321400632140000000007313551772543020742 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/codec/__main__.py0000644006321400632140000000102113551772543020715 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: import unittest suite = unittest.TestLoader().loadTestsFromNames( ['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) pyasn1-0.4.8/tests/codec/ber/0000775006321400632140000000000013564027341017374 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/codec/ber/__init__.py0000644006321400632140000000007313551772543021512 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/codec/ber/__main__.py0000644006321400632140000000071013551772543021471 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/ber/test_decoder.py0000644006321400632140000016345413551772543022434 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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 decoder from pyasn1.codec.ber import eoo from pyasn1.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error class LargeTagDecoderTestCase(BaseTestCase): def testLargeTag(self): assert decoder.decode(ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))) == (1, null) def testLongTag(self): assert decoder.decode(ints2octs((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(ints2octs((0x9f, 0x80, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) == decoder.decode( ints2octs((0x9f, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) class DecoderCacheTestCase(BaseTestCase): def testCache(self): assert decoder.decode(ints2octs((0x1f, 2, 1, 0))) == decoder.decode(ints2octs((0x1f, 2, 1, 0))) class IntegerDecoderTestCase(BaseTestCase): def testPosInt(self): assert decoder.decode(ints2octs((2, 1, 12))) == (12, null) def testNegInt(self): assert decoder.decode(ints2octs((2, 1, 244))) == (-12, null) def testZero(self): assert decoder.decode(ints2octs((2, 0))) == (0, null) def testZeroLong(self): assert decoder.decode(ints2octs((2, 1, 0))) == (0, null) def testMinusOne(self): assert decoder.decode(ints2octs((2, 1, 255))) == (-1, null) def testPosLong(self): assert decoder.decode( ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) ) == (0xffffffffffffffff, null) def testNegLong(self): assert decoder.decode( ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) ) == (-0xffffffffffffffff, null) def testSpec(self): try: decoder.decode( ints2octs((2, 1, 12)), asn1Spec=univ.Null() ) == (12, null) except PyAsn1Error: pass else: assert 0, 'wrong asn1Spec worked out' assert decoder.decode( ints2octs((2, 1, 12)), asn1Spec=univ.Integer() ) == (12, null) def testTagFormat(self): try: decoder.decode(ints2octs((34, 1, 12))) except PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(ints2octs((1, 1, 1))) == (1, null) def testTrueNeg(self): assert decoder.decode(ints2octs((1, 1, 255))) == (1, null) def testExtraTrue(self): assert decoder.decode(ints2octs((1, 1, 1, 0, 120, 50, 50))) == (1, ints2octs((0, 120, 50, 50))) def testFalse(self): assert decoder.decode(ints2octs((1, 1, 0))) == (0, null) def testTagFormat(self): try: decoder.decode(ints2octs((33, 1, 1))) except PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' class BitStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( ints2octs((3, 3, 1, 169, 138)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) def testIndefMode(self): assert decoder.decode( ints2octs((3, 3, 1, 169, 138)) ) == ((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1), null) def testDefModeChunked(self): assert decoder.decode( ints2octs((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), null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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), null) def testDefModeChunkedSubst(self): assert decoder.decode( ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)), substrateFun=lambda a, b, c: (b, b[c:]) ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138)), str2octs('')) def testIndefModeChunkedSubst(self): assert decoder.decode( ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), substrateFun=lambda a, b, c: (b, str2octs('')) ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), str2octs('')) def testTypeChecking(self): try: decoder.decode(ints2octs((35, 4, 2, 2, 42, 42))) except PyAsn1Error: pass else: assert 0, 'accepted mis-encoded bit-string constructed out of an integer' class OctetStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) ) == (str2octs('Quick brown fox'), null) def testIndefMode(self): assert decoder.decode( ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) ) == (str2octs('Quick brown fox'), null) def testDefModeChunked(self): assert decoder.decode( ints2octs( (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)) ) == (str2octs('Quick brown fox'), null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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)) ) == (str2octs('Quick brown fox'), null) def testDefModeChunkedSubst(self): assert decoder.decode( ints2octs( (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:]) ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), str2octs('')) def testIndefModeChunkedSubst(self): assert decoder.decode( ints2octs((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, str2octs('')) ) == (ints2octs( (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)), str2octs('')) 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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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:]) ) == (ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), str2octs('')) def testIndefModeSubst(self): assert decoder.decode( ints2octs(( 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, str2octs('')) ) == (ints2octs( (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), str2octs('')) class NullDecoderTestCase(BaseTestCase): def testNull(self): assert decoder.decode(ints2octs((5, 0))) == (null, null) def testTagFormat(self): try: decoder.decode(ints2octs((37, 0))) except 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( ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) ) == ((1, 3, 6, 0, 0xffffe), null) def testEdge1(self): assert decoder.decode( ints2octs((6, 1, 39)) ) == ((0, 39), null) def testEdge2(self): assert decoder.decode( ints2octs((6, 1, 79)) ) == ((1, 39), null) def testEdge3(self): assert decoder.decode( ints2octs((6, 1, 120)) ) == ((2, 40), null) def testEdge4(self): assert decoder.decode( ints2octs((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) ) == ((2, 0xffffffff), null) def testEdge5(self): assert decoder.decode( ints2octs((6, 1, 0x7F)) ) == ((2, 47), null) def testEdge6(self): assert decoder.decode( ints2octs((6, 2, 0x81, 0x00)) ) == ((2, 48), null) def testEdge7(self): assert decoder.decode( ints2octs((6, 3, 0x81, 0x34, 0x03)) ) == ((2, 100, 3), null) def testEdge8(self): assert decoder.decode( ints2octs((6, 2, 133, 0)) ) == ((2, 560), null) def testEdge9(self): assert decoder.decode( ints2octs((6, 4, 0x88, 0x84, 0x87, 0x02)) ) == ((2, 16843570), null) def testNonLeading0x80(self): assert decoder.decode( ints2octs((6, 5, 85, 4, 129, 128, 0)), ) == ((2, 5, 4, 16384), null) def testLeading0x80Case1(self): try: decoder.decode( ints2octs((6, 5, 85, 4, 128, 129, 0)) ) except PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case2(self): try: decoder.decode( ints2octs((6, 7, 1, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7F)) ) except PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case3(self): try: decoder.decode( ints2octs((6, 2, 0x80, 1)) ) except PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testLeading0x80Case4(self): try: decoder.decode( ints2octs((6, 2, 0x80, 0x7F)) ) except PyAsn1Error: pass else: assert 0, 'Leading 0x80 tolerated' def testTagFormat(self): try: decoder.decode(ints2octs((38, 1, 239))) except PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' def testZeroLength(self): try: decoder.decode(ints2octs((6, 0, 0))) except PyAsn1Error: pass else: assert 0, 'zero length tolerated' def testIndefiniteLength(self): try: decoder.decode(ints2octs((6, 128, 0))) except PyAsn1Error: pass else: assert 0, 'indefinite length tolerated' def testReservedLength(self): try: decoder.decode(ints2octs((6, 255, 0))) except PyAsn1Error: pass else: assert 0, 'reserved length tolerated' def testLarge1(self): assert decoder.decode( ints2octs((0x06, 0x11, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB7, 0x17)) ) == ((2, 18446744073709551535184467440737095), null) def testLarge2(self): assert decoder.decode( ints2octs((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) ) == ((2, 999, 18446744073709551535184467440737095), null) class RealDecoderTestCase(BaseTestCase): def testChar(self): assert decoder.decode( ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) ) == (univ.Real((123, 10, 11)), null) def testBin1(self): # check base = 2 assert decoder.decode( # (0.5, 2, 0) encoded with base = 2 ints2octs((9, 3, 128, 255, 1)) ) == (univ.Real((1, 2, -1)), null) def testBin2(self): # check base = 2 and scale factor assert decoder.decode( # (3.25, 2, 0) encoded with base = 8 ints2octs((9, 3, 148, 255, 13)) ) == (univ.Real((26, 2, -3)), null) def testBin3(self): # check base = 16 assert decoder.decode( # (0.00390625, 2, 0) encoded with base = 16 ints2octs((9, 3, 160, 254, 1)) ) == (univ.Real((1, 2, -8)), null) def testBin4(self): # check exponent = 0 assert decoder.decode( # (1, 2, 0) encoded with base = 2 ints2octs((9, 3, 128, 0, 1)) ) == (univ.Real((1, 2, 0)), null) def testBin5(self): # case of 2 octs for exponent and negative exponent assert decoder.decode( # (3, 2, -1020) encoded with base = 16 ints2octs((9, 4, 161, 255, 1, 3)) ) == (univ.Real((3, 2, -1020)), null) # TODO: this requires Real type comparison fix # def testBin6(self): # assert decoder.decode( # ints2octs((9, 5, 162, 0, 255, 255, 1)) # ) == (univ.Real((1, 2, 262140)), null) # def testBin7(self): # assert decoder.decode( # ints2octs((9, 7, 227, 4, 1, 35, 69, 103, 1)) # ) == (univ.Real((-1, 2, 76354972)), null) def testPlusInf(self): assert decoder.decode( ints2octs((9, 1, 64)) ) == (univ.Real('inf'), null) def testMinusInf(self): assert decoder.decode( ints2octs((9, 1, 65)) ) == (univ.Real('-inf'), null) def testEmpty(self): assert decoder.decode( ints2octs((9, 0)) ) == (univ.Real(0.0), null) def testTagFormat(self): try: decoder.decode(ints2octs((41, 0))) except PyAsn1Error: pass else: assert 0, 'wrong tagFormat worked out' def testShortEncoding(self): try: decoder.decode(ints2octs((9, 1, 131))) except PyAsn1Error: pass else: assert 0, 'accepted too-short real' if sys.version_info[0:2] > (2, 5): class UniversalStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) class BMPStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) class UTF8StringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc')), null) 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( ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) == (self.s, null) def testIndefMode(self): assert decoder.decode( ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) ) == (self.s, null) def testDefModeChunked(self): assert decoder.decode( ints2octs((48, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) ) == (self.s, null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testSchemalessDecoder(self): assert decoder.decode( ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SequenceOf() ) == (self.s, null) class ExpTaggedSequenceOfDecoderTestCase(BaseTestCase): def testWithSchema(self): s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) s2, r = decoder.decode( ints2octs((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=s ) assert not r assert s2 == [str2octs('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( ints2octs((163, 15, 48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) assert not r assert s2 == [str2octs('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( ints2octs((48, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, null) def testIndefMode(self): assert decoder.decode( ints2octs((48, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testDefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) 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( ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) ) == (self.s, null) def testIndefMode(self): assert decoder.decode( ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)) ) == (self.s, null) def testDefModeChunked(self): assert decoder.decode( ints2octs((49, 19, 36, 17, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110)) ) == (self.s, null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testSchemalessDecoder(self): assert decoder.decode( ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=univ.SetOf() ) == (self.s, null) 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( ints2octs((49, 13, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, null) def testIndefMode(self): assert decoder.decode( ints2octs((49, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testDefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) class SequenceDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), namedtype.NamedType('first-name', univ.OctetString(null)), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testWithOptionalAndDefaultedDefMode(self): assert decoder.decode( ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) == (self.s, null) def testWithOptionalAndDefaultedIndefMode(self): assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeChunked(self): assert decoder.decode( ints2octs( (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, null) def testWithOptionalAndDefaultedIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( ints2octs((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:]) ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( ints2octs((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, str2octs('')) ) == (ints2octs( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) def testTagFormat(self): try: decoder.decode( ints2octs((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) except 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(null)), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(2, univ.Integer(1)) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert decoder.decode( ints2octs((48, 2, 5, 0)), asn1Spec=self.s ) == (self.s, null) def testIndefMode(self): self.__init() assert decoder.decode( ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testDefModeChunked(self): self.__init() assert decoder.decode( ints2octs((48, 2, 5, 0)), asn1Spec=self.s ) == (self.s, null) def testIndefModeChunked(self): self.__init() assert decoder.decode( ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithOptionalDefMode(self): self.__initWithOptional() assert decoder.decode( ints2octs((48, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, null) def testWithOptionaIndefMode(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((48, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs( (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, null) def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) 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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1][0] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs( (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(null)), namedtype.NamedType('first-name', univ.OctetString(null)), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testWithOptionalAndDefaultedDefMode(self): assert decoder.decode( ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) == (self.s, null) def testWithOptionalAndDefaultedIndefMode(self): assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeChunked(self): assert decoder.decode( ints2octs( (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, null) def testWithOptionalAndDefaultedIndefModeChunked(self): assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( ints2octs((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:]) ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( ints2octs((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, str2octs('')) ) == (ints2octs( (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) def testTagFormat(self): try: decoder.decode( ints2octs((16, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)) ) except 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(null)), namedtype.OptionalNamedType('first-name', univ.OctetString()), namedtype.DefaultedNamedType('age', univ.Integer(33)), ) ) def __init(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) def __initWithOptional(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) def __initWithDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(2, univ.Integer(1)) def __initWithOptionalAndDefaulted(self): self.s.clear() self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) def testDefMode(self): self.__init() assert decoder.decode( ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testIndefMode(self): self.__init() assert decoder.decode( ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testDefModeChunked(self): self.__init() assert decoder.decode( ints2octs((49, 2, 5, 0)), asn1Spec=self.s ) == (self.s, null) def testIndefModeChunked(self): self.__init() assert decoder.decode( ints2octs((49, 128, 5, 0, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithOptionalDefMode(self): self.__initWithOptional() assert decoder.decode( ints2octs((49, 15, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) == (self.s, null) def testWithOptionalIndefMode(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithOptionalDefModeChunked(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithOptionalIndefModeChunked(self): self.__initWithOptional() assert decoder.decode( ints2octs((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, null) def testWithDefaultedDefMode(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((49, 5, 5, 0, 2, 1, 1)), asn1Spec=self.s ) == (self.s, null) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert decoder.decode( ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)), asn1Spec=self.s ) == (self.s, null) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeReordered(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedIndefModeReordered(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedDefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) def testWithOptionalAndDefaultedIndefModeChunked(self): self.__initWithOptionalAndDefaulted() assert decoder.decode( ints2octs((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, null) 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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(ints2octs((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(null)), namedtype.NamedType('number', univ.Integer(0)), namedtype.NamedType('string', univ.OctetString()) ) ) def testBySpec(self): self.s.setComponentByPosition(0, univ.Null(null)) assert decoder.decode( ints2octs((5, 0)), asn1Spec=self.s ) == (self.s, null) def testWithoutSpec(self): self.s.setComponentByPosition(0, univ.Null(null)) assert decoder.decode(ints2octs((5, 0))) == (self.s, null) assert decoder.decode(ints2octs((5, 0))) == (univ.Null(null), null) def testUndefLength(self): self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) assert decoder.decode(ints2octs((36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0)), asn1Spec=self.s) == (self.s, null) def testExplicitTag(self): s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4)) s.setComponentByPosition(0, univ.Null(null)) assert decoder.decode(ints2octs((164, 2, 5, 0)), asn1Spec=s) == (s, null) def testExplicitTagUndefLength(self): s = self.s.subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 4)) s.setComponentByPosition(0, univ.Null(null)) assert decoder.decode(ints2octs((164, 128, 5, 0, 0, 0)), asn1Spec=s) == (s, null) class AnyDecoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) self.s = univ.Any() def testByUntagged(self): assert decoder.decode( ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s ) == (univ.Any('\004\003fox'), null) def testTaggedEx(self): s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(ints2octs((164, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null) def testTaggedIm(self): s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(ints2octs((132, 5, 4, 3, 102, 111, 120)), asn1Spec=s) == (s, null) def testByUntaggedIndefMode(self): assert decoder.decode( ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s ) == (univ.Any('\004\003fox'), null) def testTaggedExIndefMode(self): s = univ.Any('\004\003fox').subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null) def testTaggedImIndefMode(self): s = univ.Any('\004\003fox').subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)) assert decoder.decode(ints2octs((164, 128, 4, 3, 102, 111, 120, 0, 0)), asn1Spec=s) == (s, null) def testByUntaggedSubst(self): assert decoder.decode( ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c: (b, b[c:]) ) == (ints2octs((4, 3, 102, 111, 120)), str2octs('')) def testTaggedExSubst(self): assert decoder.decode( ints2octs((164, 5, 4, 3, 102, 111, 120)), asn1Spec=self.s, substrateFun=lambda a, b, c: (b, b[c:]) ) == (ints2octs((164, 5, 4, 3, 102, 111, 120)), str2octs('')) class EndOfOctetsTestCase(BaseTestCase): def testUnexpectedEoo(self): try: decoder.decode(ints2octs((0, 0))) except PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted at top level' def testExpectedEoo(self): result, remainder = decoder.decode(ints2octs((0, 0)), allowEoo=True) assert eoo.endOfOctets.isSameTypeWith(result) and result == eoo.endOfOctets and result is eoo.endOfOctets assert remainder == null def testDefiniteNoEoo(self): try: decoder.decode(ints2octs((0x23, 0x02, 0x00, 0x00))) except PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted inside definite-length encoding' def testIndefiniteEoo(self): result, remainder = decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x00))) assert result == () and remainder == null, 'incorrect decoding of indefinite length end-of-octets' def testNoLongFormEoo(self): try: decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x81, 0x00))) except PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted with invalid long-form length' def testNoConstructedEoo(self): try: decoder.decode(ints2octs((0x23, 0x80, 0x20, 0x00))) except PyAsn1Error: pass else: assert 0, 'end-of-contents octets accepted with invalid constructed encoding' def testNoEooData(self): try: decoder.decode(ints2octs((0x23, 0x80, 0x00, 0x01, 0x00))) except 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(null)), namedtype.NamedType('first-name', univ.OctetString(null)), namedtype.NamedType('age', univ.Integer(33)) ) ) self.s.setComponentByPosition(0, univ.Null(null)) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) self.s.setComponentByPosition(2, univ.Integer(1)) self.substrate = ints2octs([48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1]) def testOctetString(self): s, _ = decoder.decode(univ.OctetString(self.substrate), asn1Spec=self.s) assert self.s == s def testAny(self): s, _ = decoder.decode(univ.Any(self.substrate), asn1Spec=self.s) assert self.s == s class ErrorOnDecodingTestCase(BaseTestCase): def testErrorCondition(self): decode = decoder.Decoder(decoder.tagMap, decoder.typeMap) try: asn1Object, rest = decode(str2octs('abc')) except PyAsn1Error: exc = sys.exc_info()[1] assert isinstance(exc, PyAsn1Error), ( 'Unexpected exception raised %r' % (exc,)) else: assert False, 'Unexpected decoder result %r' % (asn1Object,) def testRawDump(self): decode = decoder.Decoder(decoder.tagMap, decoder.typeMap) decode.defaultErrorState = decoder.stDumpRawValue asn1Object, rest = decode(ints2octs( (31, 8, 2, 1, 1, 131, 3, 2, 1, 12))) 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 == ints2octs((131, 3, 2, 1, 12)), ( 'Unexpected rest of substrate after raw dump %r' % rest) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/codec/ber/test_encoder.py0000644006321400632140000015012713551772543022437 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import ints2octs 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) == ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1)) class IntegerEncoderTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(univ.Integer(12)) == ints2octs((2, 1, 12)) def testNegInt(self): assert encoder.encode(univ.Integer(-12)) == ints2octs((2, 1, 244)) def testZero(self): assert encoder.encode(univ.Integer(0)) == ints2octs((2, 1, 0)) def testCompactZero(self): encoder.IntegerEncoder.supportCompactZero = True substrate = encoder.encode(univ.Integer(0)) encoder.IntegerEncoder.supportCompactZero = False assert substrate == ints2octs((2, 0)) def testMinusOne(self): assert encoder.encode(univ.Integer(-1)) == ints2octs((2, 1, 255)) def testPosLong(self): assert encoder.encode( univ.Integer(0xffffffffffffffff) ) == ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) def testNegLong(self): assert encoder.encode( univ.Integer(-0xffffffffffffffff) ) == ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) class IntegerEncoderWithSchemaTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(12, asn1Spec=univ.Integer()) == ints2octs((2, 1, 12)) def testNegInt(self): assert encoder.encode(-12, asn1Spec=univ.Integer()) == ints2octs((2, 1, 244)) def testZero(self): assert encoder.encode(0, asn1Spec=univ.Integer()) == ints2octs((2, 1, 0)) def testPosLong(self): assert encoder.encode( 0xffffffffffffffff, asn1Spec=univ.Integer() ) == ints2octs((2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255)) class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 1)) def testFalse(self): assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) class BooleanEncoderWithSchemaTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(True, asn1Spec=univ.Boolean()) == ints2octs((1, 1, 1)) def testFalse(self): assert encoder.encode(False, asn1Spec=univ.Boolean()) == ints2octs((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) == ints2octs((3, 3, 1, 169, 138)) def testIndefMode(self): assert encoder.encode( self.b, defMode=False ) == ints2octs((3, 3, 1, 169, 138)) def testDefModeChunked(self): assert encoder.encode( self.b, maxChunkSize=1 ) == ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)) def testIndefModeChunked(self): assert encoder.encode( self.b, defMode=False, maxChunkSize=1 ) == ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) def testEmptyValue(self): assert encoder.encode(univ.BitString([])) == ints2octs((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) == ints2octs((3, 3, 1, 169, 138)) def testIndefMode(self): assert encoder.encode( self.b, asn1Spec=self.s, defMode=False ) == ints2octs((3, 3, 1, 169, 138)) def testDefModeChunked(self): assert encoder.encode( self.b, asn1Spec=self.s, maxChunkSize=1 ) == ints2octs((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 ) == ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) def testEmptyValue(self): assert encoder.encode([], asn1Spec=self.s) == ints2octs((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) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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('')) == ints2octs((5, 0)) class NullEncoderWithSchemaTestCase(BaseTestCase): def testNull(self): assert encoder.encode(None, univ.Null()) == ints2octs((5, 0)) class ObjectIdentifierEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( univ.ObjectIdentifier((1, 3, 6, 0, 0xffffe)) ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) def testEdge1(self): assert encoder.encode( univ.ObjectIdentifier((0, 39)) ) == ints2octs((6, 1, 39)) def testEdge2(self): assert encoder.encode( univ.ObjectIdentifier((1, 39)) ) == ints2octs((6, 1, 79)) def testEdge3(self): # 01111111 assert encoder.encode( univ.ObjectIdentifier((2, 40)) ) == ints2octs((6, 1, 120)) def testEdge4(self): # 10010000|10000000|10000000|10000000|01001111 assert encoder.encode( univ.ObjectIdentifier((2, 0xffffffff)) ) == ints2octs((6, 5, 0x90, 0x80, 0x80, 0x80, 0x4F)) def testEdge5(self): # 01111111 assert encoder.encode( univ.ObjectIdentifier((2, 47)) ) == ints2octs((6, 1, 0x7F)) def testEdge6(self): # 10000001|00000000 assert encoder.encode( univ.ObjectIdentifier((2, 48)) ) == ints2octs((6, 2, 0x81, 0x00)) def testEdge7(self): # 10000001|00110100|00000003 assert encoder.encode( univ.ObjectIdentifier((2, 100, 3)) ) == ints2octs((6, 3, 0x81, 0x34, 0x03)) def testEdge8(self): # 10000101|00000000 assert encoder.encode( univ.ObjectIdentifier((2, 560)) ) == ints2octs((6, 2, 133, 0)) def testEdge9(self): # 10001000|10000100|10000111|0000010 assert encoder.encode( univ.ObjectIdentifier((2, 16843570)) ) == ints2octs((6, 4, 0x88, 0x84, 0x87, 0x02)) def testEdgeA(self): assert encoder.encode( univ.ObjectIdentifier((2, 5)) ) == ints2octs((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)) ) == ints2octs((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)) ) == ints2octs((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() ) == ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) class RealEncoderTestCase(BaseTestCase): def testChar(self): assert encoder.encode( univ.Real((123, 10, 11)) ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((9, 3, 148, 255, 13)) def testBin3(self): # change binEncBase in the RealEncoder instance => for all further Real binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, 16 assert encoder.encode( univ.Real((0.00390625, 2, 0)) # check encbase = 16 ) == ints2octs((9, 3, 160, 254, 1)) encoder.typeMap[univ.Real.typeId].binEncBase = binEncBase def testBin4(self): # choose binEncBase automatically for all further Real (testBin[4-7]) binEncBase, encoder.typeMap[univ.Real.typeId].binEncBase = encoder.typeMap[univ.Real.typeId].binEncBase, None assert encoder.encode( univ.Real((1, 2, 0)) # check exponent = 0 ) == ints2octs((9, 3, 128, 0, 1)) encoder.typeMap[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) ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((9, 7, 195, 4, 4, 141, 21, 156, 1)) def testPlusInf(self): assert encoder.encode(univ.Real('inf')) == ints2octs((9, 1, 64)) def testMinusInf(self): assert encoder.encode(univ.Real('-inf')) == ints2octs((9, 1, 65)) def testZero(self): assert encoder.encode(univ.Real(0)) == ints2octs((9, 0)) class RealEncoderWithSchemaTestCase(BaseTestCase): def testChar(self): assert encoder.encode( (123, 10, 11), asn1Spec=univ.Real() ) == ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) if sys.version_info[0:2] > (2, 5): class UniversalStringEncoderTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode(char.UniversalString(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (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( sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UniversalString() ) == ints2octs((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(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class BMPStringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.BMPString() ) == ints2octs((30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' class UTF8StringEncoderTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode(char.UTF8String(sys.version_info[0] >= 3 and 'abc' or unicode('abc'))) == ints2octs( (12, 3, 97, 98, 99)), 'Incorrect encoding' class UTF8StringEncoderWithSchemaTestCase(BaseTestCase): def testEncoding(self): assert encoder.encode( sys.version_info[0] >= 3 and 'abc' or unicode('abc'), asn1Spec=char.UTF8String() ) == ints2octs((12, 3, 97, 98, 99)), 'Incorrect encoding' class SequenceOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SequenceOf() s.clear() assert encoder.encode(s) == ints2octs((48, 0)) def testDefMode(self): s = univ.SequenceOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((48, 0)) def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((49, 0)) def testDefMode(self): s = univ.SetOf() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((49, 0)) def testDefMode(self): assert encoder.encode( self.v, asn1Spec=self.s ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs( (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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs((48, 2, 5, 0)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == ints2octs((48, 128, 5, 0, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == ints2octs((48, 2, 5, 0)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == ints2octs((48, 128, 5, 0, 0, 0)) def testWithOptionalDefMode(self): self.__initWithOptional() assert encoder.encode(self.s) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs( (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) == ints2octs((48, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == ints2octs((48, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode(self.s) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs( (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 ) == ints2octs((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) == ints2octs((101, 5, 48, 3, 2, 1, 12)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == ints2octs((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) == ints2octs((48, 5, 160, 3, 1, 1, 1)) def testIndefMode(self): assert encoder.encode( self.s, defMode=False ) == ints2octs((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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((49, 2, 5, 0)) def testIndefMode(self): self.__init() assert encoder.encode( self.s, defMode=False ) == ints2octs((49, 128, 5, 0, 0, 0)) def testDefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == ints2octs((49, 2, 5, 0)) def testIndefModeChunked(self): self.__init() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == ints2octs((49, 128, 5, 0, 0, 0)) def testWithOptionalDefMode(self): self.__initWithOptional() assert encoder.encode(self.s) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs( (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) == ints2octs((49, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefMode(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False ) == ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithDefaultedDefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=True, maxChunkSize=4 ) == ints2octs((49, 5, 5, 0, 2, 1, 1)) def testWithDefaultedIndefModeChunked(self): self.__initWithDefaulted() assert encoder.encode( self.s, defMode=False, maxChunkSize=4 ) == ints2octs((49, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedDefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode(self.s) == ints2octs( (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 ) == ints2octs((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 ) == ints2octs( (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 ) == ints2octs((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) == ints2octs((5, 0)) def testDefModeOptionTwo(self): s = univ.Choice() s.setComponentByPosition(0, univ.OctetString('quick brown')) assert encoder.encode(s) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((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) == ints2octs((164, 2, 5, 0)) def testUndefLength(self): self.s.setComponentByPosition(2, univ.OctetString('abcdefgh')) assert encoder.encode(self.s, defMode=False, maxChunkSize=3) == ints2octs( (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) == ints2octs( (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) == ints2octs((4, 3, 102, 111, 120)) def testTaggedEx(self): s = self.s.subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4) ) assert encoder.encode(s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((132, 5, 4, 3, 102, 111, 120)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/codec/cer/0000775006321400632140000000000013564027341017375 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/codec/cer/__init__.py0000644006321400632140000000007313551772543021513 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/codec/cer/__main__.py0000644006321400632140000000071013551772543021472 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/cer/test_decoder.py0000644006321400632140000002745213551772543022432 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(ints2octs((1, 1, 255))) == (1, null) def testFalse(self): assert decoder.decode(ints2octs((1, 1, 0))) == (0, null) def testEmpty(self): try: decoder.decode(ints2octs((1, 0))) except PyAsn1Error: pass def testOverflow(self): try: decoder.decode(ints2octs((1, 2, 0, 0))) except PyAsn1Error: pass class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((3, 3, 6, 170, 128)) ) == (((1, 0) * 5), null) def testLongMode(self): assert decoder.decode( ints2octs((3, 127, 6) + (170,) * 125 + (128,)) ) == (((1, 0) * 501), null) # TODO: test failures on short chunked and long unchunked substrate samples class OctetStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), ) == (str2octs('Quick brown fox'), null) def testLongMode(self): assert decoder.decode( ints2octs((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) ) == (str2octs('Q' * 1001), null) # 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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((48, 128, 2, 1, 1, 2, 1, 12, 0, 0)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs( (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) pyasn1-0.4.8/tests/codec/cer/test_encoder.py0000644006321400632140000007476513551772543022455 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import ints2octs from pyasn1.error import PyAsn1Error class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 255)) def testFalse(self): assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) class BitStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.BitString((1, 0) * 5) ) == ints2octs((3, 3, 6, 170, 128)) def testLongMode(self): assert encoder.encode(univ.BitString((1, 0) * 501)) == ints2octs((3, 127, 6) + (170,) * 125 + (128,)) class OctetStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == ints2octs((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) ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((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') ) == ints2octs((23, 13, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 49, 50, 90)) def testWithMinutes(self): assert encoder.encode( useful.UTCTime('9908011201Z') ) == ints2octs((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) == ints2octs((48, 128, 0, 0)) def testDefMode1(self): s = univ.SequenceOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('ab')) assert encoder.encode(s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((48, 128, 0, 0)) def testIndefMode1(self): self.s.clear() self.s.append('a') self.s.append('ab') assert encoder.encode(self.s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((49, 128, 0, 0)) def testDefMode1(self): s = univ.SetOf() s.append(univ.OctetString('a')) s.append(univ.OctetString('ab')) assert encoder.encode(s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((49, 128, 0, 0)) def testIndefMode1(self): self.s.clear() self.s.append('a') self.s.append('ab') assert encoder.encode(self.s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((49, 128, 5, 0, 0, 0)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s ) == ints2octs((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 ) == ints2octs((49, 128, 2, 1, 1, 5, 0, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s ) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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 ) == ints2octs((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) == ints2octs((48, 128, 5, 0, 0, 0)) def testWithOptionalIndefMode(self): self.__initWithOptional() assert encoder.encode( self.s ) == ints2octs((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 ) == ints2octs((48, 128, 5, 0, 2, 1, 1, 0, 0)) def testWithOptionalAndDefaultedIndefMode(self): self.__initWithOptionalAndDefaulted() assert encoder.encode( self.s ) == ints2octs((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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs((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) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) def testDefaultWithDefaultAndOptional(self): s = self.__initDefaultWithDefaultAndOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testDefaultWithOptional(self): s = self.__initDefaultWithOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((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) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) def testOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((48, 128, 48, 128, 4, 4, 116, 101, 115, 116, 0, 0, 0, 0)) def testOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/codec/der/0000775006321400632140000000000013564027341017376 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/codec/der/__init__.py0000644006321400632140000000007313551772543021514 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/codec/der/__main__.py0000644006321400632140000000071013551772543021473 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/der/test_decoder.py0000644006321400632140000002722013551772543022424 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import ints2octs, null from pyasn1.error import PyAsn1Error class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((3, 127, 6) + (170,) * 125 + (128,)) ) == (((1, 0) * 501), null) def testIndefMode(self): try: decoder.decode( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((48, 8, 2, 1, 1, 49, 3, 2, 1, 12)), asn1Spec=self.s ) assert not r assert s[0] == 1 assert s[1][0] == ints2octs((2, 1, 12)) def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((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] == ints2octs((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( ints2octs((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( ints2octs((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( ints2octs((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( ints2octs( (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) pyasn1-0.4.8/tests/codec/der/test_encoder.py0000644006321400632140000004601713551772543022443 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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 encoder from pyasn1.compat.octets import ints2octs class OctetStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == ints2octs((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) ) == ints2octs((4, 130, 39, 16) + (81,) * 10000) class BitStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.BitString((1,)) ) == ints2octs((3, 2, 7, 128)) def testDefModeLong(self): assert encoder.encode( univ.BitString((1,) * 80000) ) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs( (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) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) def testDefModeOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((48, 0)) def testDefModeDefaultWithDefaultAndOptional(self): s = self.__initDefaultWithDefaultAndOptional() assert encoder.encode(s) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeDefaultWithDefault(self): s = self.__initDefaultWithDefault() assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeDefaultWithOptional(self): s = self.__initDefaultWithOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((48, 11, 48, 9, 4, 4, 116, 101, 115, 116, 2, 1, 123)) def testDefModeOptionalWithDefault(self): s = self.__initOptionalWithDefault() assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) def testDefModeOptionalWithOptional(self): s = self.__initOptionalWithOptional() assert encoder.encode(s) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((48, 8, 48, 6, 4, 4, 116, 101, 115, 116)) def testDefModeOptional(self): s = self.__initOptional() assert encoder.encode(s) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((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) == ints2octs((48, 0)) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/codec/native/0000775006321400632140000000000013564027341020112 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/codec/native/__init__.py0000644006321400632140000000007313551772543022230 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/codec/native/__main__.py0000644006321400632140000000071513551772543022214 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/native/test_decoder.py0000644006321400632140000000712013551772543023135 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/codec/native/test_encoder.py0000644006321400632140000000764513551772543023163 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import str2octs 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) == str2octs('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': str2octs('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) == str2octs('fox') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/compat/0000775006321400632140000000000013564027341017032 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/compat/__init__.py0000644006321400632140000000007313551772543021150 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/compat/__main__.py0000644006321400632140000000075013551772543021133 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: import unittest suite = unittest.TestLoader().loadTestsFromNames( ['tests.compat.test_binary.suite', 'tests.compat.test_integer.suite', 'tests.compat.test_octets.suite'] ) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/compat/test_binary.py0000644006321400632140000000226113551772543021735 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: import unittest from tests.base import BaseTestCase from pyasn1.compat import binary class BinaryTestCase(BaseTestCase): def test_bin_zero(self): assert '0b0' == binary.bin(0) def test_bin_noarg(self): try: binary.bin() except TypeError: pass except: assert 0, 'bin() tolerates no arguments' def test_bin_allones(self): assert '0b1111111111111111111111111111111111111111111111111111111111111111' == binary.bin(0xffffffffffffffff) def test_bin_allzeros(self): assert '0b0' == binary.bin(0x0000000) def test_bin_pos(self): assert '0b1000000010000000100000001' == binary.bin(0x01010101) def test_bin_neg(self): assert '-0b1000000010000000100000001' == binary.bin(-0x01010101) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/compat/test_integer.py0000644006321400632140000000265713551772543022117 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: import unittest from tests.base import BaseTestCase from pyasn1.compat import integer class IntegerTestCase(BaseTestCase): if sys.version_info[0] > 2: def test_from_bytes_zero(self): assert 0 == integer.from_bytes(bytes([0]), signed=False) def test_from_bytes_unsigned(self): assert -66051 == integer.from_bytes(bytes([254, 253, 253]), signed=True) def test_from_bytes_signed(self): assert 66051 == integer.from_bytes(bytes([0, 1, 2, 3]), signed=False) def test_from_bytes_empty(self): assert 0 == integer.from_bytes(bytes([])) else: def test_from_bytes_zero(self): assert 0 == integer.from_bytes('\x00', signed=False) def test_from_bytes_unsigned(self): assert -66051 == integer.from_bytes('\xfe\xfd\xfd', signed=True) def test_from_bytes_signed(self): assert 66051 == integer.from_bytes('\x01\x02\x03', signed=False) def test_from_bytes_empty(self): assert 0 == integer.from_bytes('') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/compat/test_octets.py0000644006321400632140000000673613551772543021765 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: import unittest from tests.base import BaseTestCase from pyasn1.compat import octets class OctetsTestCase(BaseTestCase): if sys.version_info[0] > 2: def test_ints2octs(self): assert [1, 2, 3] == list(octets.ints2octs([1, 2, 3])) def test_ints2octs_empty(self): assert not octets.ints2octs([]) def test_int2oct(self): assert [12] == list(octets.int2oct(12)) def test_octs2ints(self): assert [1, 2, 3] == list(octets.octs2ints(bytes([1, 2, 3]))) def test_octs2ints_empty(self): assert not octets.octs2ints(bytes([])) def test_oct2int(self): assert 12 == octets.oct2int(bytes([12]))[0] def test_str2octs(self): assert bytes([1, 2, 3]) == octets.str2octs('\x01\x02\x03') def test_str2octs_empty(self): assert not octets.str2octs('') def test_octs2str(self): assert '\x01\x02\x03' == octets.octs2str(bytes([1, 2, 3])) def test_octs2str_empty(self): assert not octets.octs2str(bytes([])) def test_isOctetsType(self): assert octets.isOctetsType('abc') == False assert octets.isOctetsType(123) == False assert octets.isOctetsType(bytes()) == True def test_isStringType(self): assert octets.isStringType('abc') == True assert octets.isStringType(123) == False assert octets.isStringType(bytes()) == False def test_ensureString(self): assert 'abc'.encode() == octets.ensureString('abc'.encode()) assert bytes([1, 2, 3]) == octets.ensureString([1, 2, 3]) else: def test_ints2octs(self): assert '\x01\x02\x03' == octets.ints2octs([1, 2, 3]) def test_ints2octs_empty(self): assert not octets.ints2octs([]) def test_int2oct(self): assert '\x0c' == octets.int2oct(12) def test_octs2ints(self): assert [1, 2, 3] == octets.octs2ints('\x01\x02\x03') def test_octs2ints_empty(self): assert not octets.octs2ints('') def test_oct2int(self): assert 12 == octets.oct2int('\x0c') def test_str2octs(self): assert '\x01\x02\x03' == octets.str2octs('\x01\x02\x03') def test_str2octs_empty(self): assert not octets.str2octs('') def test_octs2str(self): assert '\x01\x02\x03' == octets.octs2str('\x01\x02\x03') def test_octs2str_empty(self): assert not octets.octs2str('') def test_isOctetsType(self): assert octets.isOctetsType('abc') == True assert octets.isOctetsType(123) == False assert octets.isOctetsType(unicode('abc')) == False def test_isStringType(self): assert octets.isStringType('abc') == True assert octets.isStringType(123) == False assert octets.isStringType(unicode('abc')) == True def test_ensureString(self): assert 'abc' == octets.ensureString('abc') assert '123' == octets.ensureString(123) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/test_debug.py0000644006321400632140000000173013551772543020254 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/type/0000775006321400632140000000000013564027341016530 5ustar ietingofietingof00000000000000pyasn1-0.4.8/tests/type/__init__.py0000644006321400632140000000007313551772543020646 0ustar ietingofietingof00000000000000# This file is necessary to make this directory a package. pyasn1-0.4.8/tests/type/__main__.py0000644006321400632140000000123613551772543020631 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/type/test_char.py0000644006321400632140000001307513551772543021071 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import pickle import sys try: import unittest2 as unittest except ImportError: import unittest from tests.base import BaseTestCase from pyasn1.type import char from pyasn1.type import univ from pyasn1.type import constraint from pyasn1.compat.octets import ints2octs from pyasn1.error import PyAsn1Error class AbstractStringTestCase(object): initializer = () encoding = 'us-ascii' asn1Type = None def setUp(self): BaseTestCase.setUp(self) self.asn1String = self.asn1Type(ints2octs(self.initializer), encoding=self.encoding) self.pythonString = ints2octs(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): if sys.version_info[0] < 3: assert str(self.asn1String) == self.pythonString.encode(self.encoding), '__str__() fails' else: assert bytes(self.asn1String) == self.pythonString.encode(self.encoding), '__str__() fails' def testPrintable(self): if sys.version_info[0] < 3: assert unicode(self.asn1String) == self.pythonString, '__str__() fails' else: 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 if sys.version_info[:2] > (2, 4): 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 if sys.version_info[0] > 2: # Somehow comparison of UTF-32 encoded strings does not work in Py2 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) pyasn1-0.4.8/tests/type/test_constraint.py0000664006321400632140000002621313564027254022334 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/type/test_namedtype.py0000644006321400632140000001031513551772543022134 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/type/test_namedval.py0000644006321400632140000000345213551772543021741 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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()) == set([('off', 0), ('on', 1)]) assert set(self.e.keys()) == set(['off', 'on']) assert set(self.e) == set(['off', 'on']) assert set(self.e.values()) == set([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) pyasn1-0.4.8/tests/type/test_opentype.py0000644006321400632140000000516413551772543022017 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import str2octs 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(str2octs('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(str2octs('xxx')) self.s['blob'] = univ.Integer(123) suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/type/test_tag.py0000644006321400632140000001062213551772543020722 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import sys try: import unittest2 as unittest except ImportError: 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) pyasn1-0.4.8/tests/type/test_univ.py0000644006321400632140000020727013551772543021137 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import math import pickle import sys try: import unittest2 as unittest except ImportError: 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.compat.octets import str2octs, ints2octs, octs2ints, octs2str 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' def testSizeOf(self): try: if hasattr(sys, 'getsizeof'): sys.getsizeof(univ.noValue) # TODO: remove when Py2.5 support is gone elif sys.version_info > (2, 6): raise unittest.SkipTest("no sys.getsizeof() method") except PyAsn1Error: assert False, 'sizeof failed for NoValue object' except TypeError: # TODO: remove when Py2.5 support is gone if sys.version_info > (2, 6): raise unittest.SkipTest("sys.getsizeof() raises TypeError") 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' if sys.version_info[0] > 2: def testDivFloat(self): assert univ.Integer(3) / 2 == 1.5, '__div__() fails' def testRdivFloat(self): assert 3 / univ.Integer(2) == 1.5, '__rdiv__() fails' else: def testDivFloat(self): assert univ.Integer(3) / 2 == 1, '__div__() fails' def testRdivFloat(self): assert 3 / univ.Integer(2) == 1, '__rdiv__() fails' def testRdivInt(self): assert 6 / univ.Integer(3) == 2, '__rdiv__() fails' if sys.version_info[0] > 2: 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' if sys.version_info[0:2] > (2, 5): 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 if sys.version_info[:2] > (2, 4): 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() == ints2octs((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 = ints2octs(self.initializer).decode(self.encoding) self.encodedPythonString = self.pythonString.encode(self.encoding) self.numbersString = tuple(octs2ints(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): if sys.version_info[0] < 3: assert str(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' else: assert bytes(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' def testPrintable(self): if sys.version_info[0] < 3: assert str(univ.OctetString(self.encodedPythonString, encoding=self.encoding)) == self.encodedPythonString, '__str__() fails' assert unicode(univ.OctetString(self.pythonString, encoding=self.encoding)) == self.pythonString, 'unicode init fails' else: 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 if sys.version_info[:2] > (2, 4): 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 = ints2octs((0xff, 0xfe)) if sys.version_info < (3, 0): text = serialized.decode('iso-8859-1') else: text = octs2str(serialized) try: univ.OctetString(text, encoding='us-ascii') except PyAsn1UnicodeEncodeError: pass # TODO: remove when Py2.5 support is gone else: if sys.version_info > (2, 6): assert False, 'Unicode encoding error not caught' def testDecodeError(self): serialized = ints2octs((0xff, 0xfe)) octetString = univ.OctetString(serialized, encoding='us-ascii') try: if sys.version_info < (3, 0): unicode(octetString) else: str(octetString) except PyAsn1UnicodeDecodeError: pass # TODO: remove when Py2.5 support is gone else: if sys.version_info > (2, 6): assert False, 'Unicode decoding error not caught' 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' if sys.version_info[0] > 2: # Somehow comparison of UTF-32 encoded strings does not work in Py2 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") == ints2octs((133, 238, 188, 14, 192)), 'bin init fails' def testHexStr(self): assert univ.OctetString(hexValue="FA9823C43E43510DE3422") == ints2octs((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)) == ints2octs((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") == ints2octs((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) == str2octs('') assert univ.Null(False) == str2octs('') assert univ.Null('') == str2octs('') assert univ.Null(None) == str2octs('') 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' if sys.version_info[0:2] > (2, 5): 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' if sys.version_info[0] < 3: s = s.decode() 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 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] == str2octs('abc'), 'set by idx fails' self.s1[0] = 'cba' assert self.s1[0] == str2octs('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(str2octs('abc')))) try: s.setComponentByPosition( 0, univ.OctetString().subtype( 'abc', subtypeSpec=constraint.SingleValueConstraint(str2octs('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(str2octs('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] == [str2octs('xxx')] assert s[-2:] == [str2octs('yyy'), str2octs('zzz')] assert s[1:2] == [str2octs('yyy')] def testSetItem(self): s = self.s1.clone() s.append('xxx') s[2] = 'yyy' assert len(s) == 3 assert s[1] == str2octs('') def testSetItemSlice(self): s = self.s1.clone() s[:1] = ['xxx'] assert s == [str2octs('xxx')] s[-2:] = ['yyy', 'zzz'] assert s == [str2octs('yyy'), str2octs('zzz')] s[1:2] = ['yyy'] assert s == [str2octs('yyy'), str2octs('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) == [str2octs(x) for x in ['abc', '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) == [str2octs(x) for x in ['abc', 'def', 'ghi']] def testCount(self): self.s1.clear() for x in ['abc', 'def', 'abc']: self.s1.append(x) assert self.s1.count(str2octs('abc')) == 2 assert self.s1.count(str2octs('def')) == 1 assert self.s1.count(str2octs('ghi')) == 0 def testIndex(self): self.s1.clear() for x in ['abc', 'def', 'abc']: self.s1.append(x) assert self.s1.index(str2octs('abc')) == 0 assert self.s1.index(str2octs('def')) == 1 assert self.s1.index(str2octs('abc'), 1) == 2 def testSort(self): self.s1.clear() self.s1[0] = 'b' self.s1[1] = 'a' assert list(self.s1) == [str2octs('b'), str2octs('a')] self.s1.sort() assert list(self.s1) == [str2octs('a'), str2octs('b')] def testStaticDef(self): class SequenceOf(univ.SequenceOf): componentType = univ.OctetString('') s = SequenceOf() s[0] = 'abc' assert len(s) == 1 assert s == [str2octs('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) == str2octs('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) == str2octs('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) == str2octs('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) == str2octs('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 == [str2octs('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') == str2octs('abc'), 'set by name fails' def testByKey(self): self.s1['name'] = 'abc' assert self.s1['name'] == str2octs('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(str2octs('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()) == [str2octs('abc'), str2octs('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()) == [(x[0], str2octs(x[1])) for x in [('name', 'abc'), ('nick', 'def')]] + [('age', 123)] def testUpdate(self): self.s1.clear() assert list(self.s1.values()) == [str2octs(''), str2octs(''), 34] self.s1.update(**{'name': 'abc', 'nick': 'def', 'age': 123}) assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'abc'), ('nick', 'def')]] + [('age', 123)] self.s1.update(('name', 'ABC')) assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'ABC'), ('nick', 'def')]] + [('age', 123)] self.s1.update(name='CBA') assert list(self.s1.items()) == [(x[0], str2octs(x[1])) for x in [('name', 'CBA'), ('nick', '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'] == str2octs('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] == str2octs('') 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) == str2octs('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] == str2octs('') 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) == str2octs('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.OptionalNamedType('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 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()) == [str2octs('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', str2octs('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()) == [str2octs('abc'), 123] assert list(s.items()) == [('field-0', str2octs('abc')), ('field-1', 123)] s['field-0'] = univ.OctetString('def') assert list(s.values()) == [str2octs('def'), 123] s['field-1'] = univ.OctetString('ghi') assert list(s.values()) == [str2octs('def'), str2octs('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'] == str2octs('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] == str2octs('abc'), 'set by idx fails' self.s1.setComponentByPosition(0, self.s1[0].clone('cba')) assert self.s1[0] == str2octs('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 == [str2octs('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 == [str2octs('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 ) == str2octs('abc'), 'set by name fails' def testByTypeWithInstance(self): self.s1.setComponentByType(univ.OctetString.tagSet, univ.OctetString('abc')) assert self.s1.getComponentByType( univ.OctetString.tagSet ) == str2octs('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'] == str2octs('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) == str2octs('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) == str2octs('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'] == str2octs('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 ) == str2octs('abc') def testOuterByTypeWithInstanceValue(self): self.s1.setComponentByType( univ.OctetString.tagSet, univ.OctetString('abc') ) assert self.s1.getComponentByType( univ.OctetString.tagSet ) == str2octs('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 == str2octs('abc'), '__cmp__() fails' def testGetComponent(self): self.s1.setComponentByType(univ.OctetString.tagSet, 'abc') assert self.s1.getComponent() == str2octs('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 == str2octs('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'] == str2octs('test') suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) if __name__ == '__main__': unittest.TextTestRunner(verbosity=2).run(suite) pyasn1-0.4.8/tests/type/test_useful.py0000644006321400632140000001125613551772543021456 0ustar ietingofietingof00000000000000# # This file is part of pyasn1 software. # # Copyright (c) 2005-2019, Ilya Etingof # License: http://snmplabs.com/pyasn1/license.html # import datetime import pickle import sys from copy import deepcopy try: import unittest2 as unittest except ImportError: 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)