The pyasn1 package is designed to help Python programmers tacklingnetwork protocols and file formats at the comfort of their Pythonprompt. The tool struggles to capture all aspects of a rathercomplicated ASN.1 system and to represent it on the Python terms.
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 pyasn1classes into Python built-ins:
With ASN.1 design, serialisation codecs are decoupled from data objects,so you could turn every single ASN.1 object into many differentserialised forms. As of this moment, pyasn1 supports BER, DER, CER andPython built-ins codecs. The extremely compact PER encoding is expectedto be introduced in the upcoming pyasn1 release.
I wanted to try Python's Geemap module, I installed it via conda install geemap -c conda-forge. But when importing it in my pyhton code I have this error message :The 'pyasn1-modules>=0.2.1' distribution was not found and is required by google-auth. So I updated pyasn1-modules, and now I have version 0.2.8 but the errors remains.If someone has a idea...
This tutorial and algorithms, implemented by pyasn1 library, arelargely based on the information read in the bookASN.1 - Communication between heterogeneous systemsby Olivier Dubuisson. Another relevant resource isA Layman's Guide to a Subset of ASN.1, BER, and DER by Burton S. Kaliski.It's advised to refer to these books for more in-depth knowledge on thesubject of ASN.1.
As of this writing, pyasn1 library implements most of standard ASN.1 datastructures in a rather detailed and feature-rich manner. Another highlyimportant capability of the library is its data serialization facilities.The last component of the standard - ASN.1 compiler is planned forimplementation in the future.
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 valuedepending of the presense of value initializer on object instantiation.We will further refer to these as pyasn1 type object versus pyasn1value object.
In pyasn1, we have taken a liberal approach and allowed both BIT STRINGstyle and quoted text initializers for the OctetString objects. To avoidpossible collisions, quoted text is the default initialization syntax.
In pyasn1, all character type objects behave like Python strings. None ofthem is currently constrained in terms of valid alphabet so it's up tothe data source to keep an eye on data validation for these types.
In order to continue with the Constructed ASN.1 types, we will first haveto introduce the concept of tagging (and its pyasn1 implementation), assome of the Constructed types rely upon the tagging feature.
As a side note: the "base tag" concept (accessible through the getBaseTag()method) is specific to pyasn1 -- the base tag is used to identify the originalASN.1 type of an object in question. Base tag is never occurs in encodingand is mostly used internally by pyasn1 for choosing type-specific data processing algorithms. The "effective tag" is the one that always appears inencoding and is used on tagSets comparation.
Referring to the above code, the tagSet class attribute is a property of anypyasn1 type object that assigns default tagSet to a pyasn1 value object. Thisdefault tagSet specification can be ignored and effectively replaced by someother tagSet value passed on object instantiation.
It's important to understand that the tag set property of pyasn1 type/valueobject can never be modifed in place. In other words, a pyasn1 type/valueobject can never change its tags. The only way is to create a new pyasn1type/value object and associate different tag set with it.
However, Sequence type guarantees the ordering of Sequence value componentsto match their declaration order. By contrast, components of theSet type can be ordered to best suite application's needs.Record ::= SEQUENCE id INTEGER, room [0] INTEGER OPTIONAL, house [1] INTEGER DEFAULT 0Up to this moment, the only method we used for creating new pyasn1 typesis Python sub-classing. With this method, a new, named Python class is createdwhat mimics type derivation in ASN.1 grammar. However, ASN.1 also allows fordefining anonymous subtypes (room and house components in the example above).To support anonymous subtyping in pyasn1, a cloning operation on an existingpyasn1 type object can be invoked what creates a new instance of originalobject with possibly modified properties.
The NamedTypes class instance holds a sequence of NameType, OptionalNamedTypeor DefaultedNamedType objects which, in turn, refer to pyasn1 type objects thatrepresent inner SEQUENCE components specification.
In pyasn1, constraints take shape of immutable objects capableof 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 modifiedin place. The only way to modify pyasn1 type constraint is to associatenew constraint object to a new pyasn1 type object.
As can be seen in the snippet above, if a value violates the constraint, anexception will be thrown. A constrainted pyasn1 type object holds areference to a constraint object (or their combination, as will be explainedlater) and calls it for value verification.
In pyasn1 data model, all of these methods of constraint combinations areimplemented as constraint-like objects holding individual constraint (orcombination) objects. Like terminal constraint objects, combination objectsare capable to perform value verification at its set of enclosed constraintsaccording to the logic of particular combination.
It's important to note, that a value must fully comply to any singleconstraint in a set. In the specification above, a value of all small orall capital letters is compliant, but a mix of small&capitals is not. Here's its pyasn1 analogue:
In the course of data processing in an application, it is sometimesconvenient to figure out the type relationships between pyasn1 type orvalue objects. Formally, two things influence pyasn1 types relationship:tag set and subtype constraints. One pyasn1 type is consideredto be a derivative of another if their TagSet and Constraint objects area derivation of one another.
As can be seen in the above code snippet, there are two methods of any pyasn1type/value object that test types for their relationship:isSameTypeWith() and isSuperTypeOf(). The former is self-descriptive while the latter yields true if the argument appearsto be a pyasn1 object which has tagset and constraints derived from thoseof the object being called.
Since pyasn1 codecs are not restartable, pyasn1 encoder may only encode dataitem 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.
Commenting on the code snippet above, pyasn1 decoder accepts substrateas an argument and returns a tuple of pyasn1 value object (possiblya top-level one in case of constructed object) and unprocessed partof input substrate.
As discussed earlier in this handbook, when an ASN.1 type is implicitlytagged, 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-specificvalue decoder at its table of built-in types, and therefore recoverthe value part, based only on the information contained in substrate. Theapproach taken by pyasn1 decoder is to use a prototype pyasn1 type object (ora set of them) to guide the decoding process by matching [possiblyincomplete] tags recovered from substrate with those found in prototype pyasn1type objects (also called pyasn1 specification object further in this paper).
Decoder would neither modify pyasn1 specification object nor useits current values (if it's a pyasn1 value object), but rather use it asa hint for choosing proper decoder and as a pattern for creating new objects:
Another important feature of guided decoder operation is the use ofvalues constraints possibly present in pyasn1 specification object.To explain this, we will decode a random integer object into generic Integerand the constrained one.
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 willhave their own tag. Therefore these types become invisible in substrateand can not be recovered without passing pyasn1 specification object todecoder.
Similarily untagged ANY type behaves differently on decoding phase - whendecoder bumps into an Any object in pyasn1 specification, it stops decodingand puts all the substrate into a new Any value object in form of an octetstring. Concerned application could then re-run decoder with an additional,more exact pyasn1 specification object to recover the contents of Anyobject.
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:
Although pyasn1 software is almost a decade old and used in many productionenvironments, it still may have bugs and non-implemented pieces. Anyonewho happens to run into such defect is welcome to complain topyasn1 mailing listor better yet fix the issue and sendme the patch.
Typically, pyasn1 is used for building arbitrary protocol support intovarious applications. This involves manual translation of ASN.1 datastructures into their pyasn1 implementations. To save time and effort,data structures for some of the popular protocols are pre-programmedand kept for further re-use in form of thepyasn1-modules package. For instance, many structures for PKI (X.509,PKCS#*, CRMF, OCSP), LDAP and SNMP are present.Applications authors are advised to import and use relevant modules from that package whenever needed protocol structures are already there. New protocol modules contributions are welcome.
f5d0e4f075