Index: tools/telemetry/third_party/gsutil/third_party/pyasn1/doc/pyasn1-tutorial.html |
diff --git a/tools/telemetry/third_party/gsutil/third_party/pyasn1/doc/pyasn1-tutorial.html b/tools/telemetry/third_party/gsutil/third_party/pyasn1/doc/pyasn1-tutorial.html |
deleted file mode 100644 |
index 2eb82f1e936d568406566584863c22f57fae7696..0000000000000000000000000000000000000000 |
--- a/tools/telemetry/third_party/gsutil/third_party/pyasn1/doc/pyasn1-tutorial.html |
+++ /dev/null |
@@ -1,2405 +0,0 @@ |
-<html> |
-<title> |
-PyASN1 programmer's manual |
-</title> |
-<head> |
-</head> |
-<body> |
-<center> |
-<table width=60%> |
-<tr> |
-<td> |
- |
-<h3> |
-PyASN1 programmer's manual |
-</h3> |
- |
-<p align=right> |
-<i>written by <a href=mailto:ilya@glas.net>Ilya Etingof</a>, 2011-2012</i> |
-</p> |
- |
-<p> |
-Free and open-source pyasn1 library makes it easier for programmers and |
-network engineers to develop, debug and experiment with ASN.1-based protocols |
-using Python programming language as a tool. |
-</p> |
- |
-<p> |
-Abstract Syntax Notation One |
-(<a href=http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_1x>ASN.1</a>) |
-is a set of |
-<a href=http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-X.693-0207w.zip> |
-ITU standards</a> concered with provisioning instrumentation for developing |
-data exchange protocols in a robust, clear and interoperabable way for |
-various IT systems and applications. Most of the efforts are targeting the |
-following areas: |
-<ul> |
-<li>Data structures: the standard introduces a collection of basic data types |
-(similar to integers, bits, strings, arrays and records in a programming |
-language) that can be used for defining complex, possibly nested data |
-structures representing domain-specific data units. |
-<li>Serialization protocols: domain-specific data units expressed in ASN.1 |
-types could be converted into a series of octets for storage or transmission |
-over the wire and then recovered back into their structured form on the |
-receiving end. This process is immune to various hardware and software |
-related dependencies. |
-<li>Data description language: could be used to describe particular set of |
-domain-specific data structures and their relationships. Such a description |
-could be passed to an ASN.1 compiler for automated generation of program |
-code that represents ASN.1 data structures in language-native environment |
-and handles data serialization issues. |
-</ul> |
-</p> |
- |
-<p> |
-This tutorial and algorithms, implemented by pyasn1 library, are |
-largely based on the information read in the book |
-<a href="http://www.oss.com/asn1/dubuisson.html"> |
-ASN.1 - Communication between heterogeneous systems</a> |
-by Olivier Dubuisson. Another relevant resource is |
-<a href=ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc> |
-A Layman's Guide to a Subset of ASN.1, BER, and DER</a> by Burton S. Kaliski. |
-It's advised to refer to these books for more in-depth knowledge on the |
-subject of ASN.1. |
-</p> |
- |
-<p> |
-As of this writing, pyasn1 library implements most of standard ASN.1 data |
-structures in a rather detailed and feature-rich manner. Another highly |
-important capability of the library is its data serialization facilities. |
-The last component of the standard - ASN.1 compiler is planned for |
-implementation in the future. |
-</p> |
- |
-</p> |
-The pyasn1 library was designed to follow the pre-1995 ASN.1 specification |
-(also known as X.208). Later, post 1995, revision (X.680) introduced |
-significant changes most of which have not yet been supported by pyasn1. |
-</p> |
- |
-<h3> |
-Table of contents |
-</h3> |
- |
-<p> |
-<ul> |
-<li><a href="#1">1. Data model for ASN.1 types</a> |
-<li><a href="#1.1">1.1 Scalar types</a> |
-<li><a href="#1.1.1">1.1.1 Boolean type</a> |
-<li><a href="#1.1.2">1.1.2 Null type</a> |
-<li><a href="#1.1.3">1.1.3 Integer type</a> |
-<li><a href="#1.1.4">1.1.4 Enumerated type</a> |
-<li><a href="#1.1.5">1.1.5 Real type</a> |
-<li><a href="#1.1.6">1.1.6 Bit string type</a> |
-<li><a href="#1.1.7">1.1.7 OctetString type</a> |
-<li><a href="#1.1.8">1.1.8 ObjectIdentifier type</a> |
-<li><a href="#1.1.9">1.1.9 Character string types</a> |
-<li><a href="#1.1.10">1.1.10 Useful types</a> |
-<li><a href="#1.2">1.2 Tagging</a> |
-<li><a href="#1.3">1.3 Constructed types</a> |
-<li><a href="#1.3.1">1.3.1 Sequence and Set types</a> |
-<li><a href="#1.3.2">1.3.2 SequenceOf and SetOf types</a> |
-<li><a href="#1.3.3">1.3.3 Choice type</a> |
-<li><a href="#1.3.4">1.3.4 Any type</a> |
-<li><a href="#1.4">1.4 Subtype constraints</a> |
-<li><a href="#1.4.1">1.4.1 Single value constraint</a> |
-<li><a href="#1.4.2">1.4.2 Value range constraint</a> |
-<li><a href="#1.4.3">1.4.3 Size constraint</a> |
-<li><a href="#1.4.4">1.4.4 Alphabet constraint</a> |
-<li><a href="#1.4.5">1.4.5 Constraint combinations</a> |
-<li><a href="#1.5">1.5 Types relationships</a> |
-<li><a href="#2">2. Codecs</a> |
-<li><a href="#2.1">2.1 Encoders</a> |
-<li><a href="#2.2">2.2 Decoders</a> |
-<li><a href="#2.2.1">2.2.1 Decoding untagged types</a> |
-<li><a href="#2.2.2">2.2.2 Ignoring unknown types</a> |
-<li><a href="#3">3. Feedback and getting help</a> |
-</ul> |
- |
- |
-<a name="1"></a> |
-<h3> |
-1. Data model for ASN.1 types |
-</h3> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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 presense of value initializer on object instantiation. |
-We will further refer to these as <i>pyasn1 type object</i> versus <i>pyasn1 |
-value object</i>. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-It would be an error to perform an operation on a pyasn1 type object |
-as it holds no value to deal with: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> asn1IntegerType = univ.Integer() |
->>> asn1IntegerType - 2 |
-... |
-pyasn1.error.PyAsn1Error: No value for __coerce__() |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.1"></a> |
-<h4> |
-1.1 Scalar types |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<a name="1.1.1"></a> |
-<h4> |
-1.1.1 Boolean type |
-</h4> |
- |
-<p> |
-This is the simplest type those values could be either True or False. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-;; type specification |
-FunFactorPresent ::= BOOLEAN |
- |
-;; values declaration and assignment |
-pythonFunFactor FunFactorPresent ::= TRUE |
-cobolFunFactor FunFactorPresent :: FALSE |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-And here's pyasn1 version of it: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.1.2"></a> |
-<h4> |
-1.1.2 Null type |
-</h4> |
- |
-<p> |
-The NULL type is sometimes used to express the absense of any information. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-;; type specification |
-Vote ::= CHOICE { |
- agreed BOOLEAN, |
- skip NULL |
-} |
-</td></tr></table> |
- |
-;; value declaration and assignment |
-myVote Vote ::= skip:NULL |
-</pre> |
- |
-<p> |
-We will explain the CHOICE type later in this paper, meanwhile the NULL |
-type: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> skip = univ.Null() |
->>> skip |
-Null('') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.1.3"></a> |
-<h4> |
-1.1.3 Integer type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-;; values specification |
-age-of-universe INTEGER ::= 13750000000 |
-mean-martian-surface-temperature INTEGER ::= -63 |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-A rather strigntforward mapping into pyasn1: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> ageOfUniverse = univ.Integer(13750000000) |
->>> ageOfUniverse |
-Integer(13750000000) |
->>> |
->>> meanMartianSurfaceTemperature = univ.Integer(-63) |
->>> meanMartianSurfaceTemperature |
-Integer(-63) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-ASN.1 allows to assign human-friendly names to particular values of |
-an INTEGER type. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-Temperature ::= INTEGER { |
- freezing(0), |
- boiling(100) |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The Temperature type expressed in pyasn1: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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 this paper). |
-</p> |
- |
-<a name="1.1.4"></a> |
-<h4> |
-1.1.4 Enumerated type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-error-status ::= ENUMERATED { |
- no-error(0), |
- authentication-error(10), |
- authorization-error(20), |
- general-failure(51) |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-When constructing Enumerated type we will use two pyasn1 features: values |
-labels (as mentioned above) and value constraint (will be described in |
-more details later on). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<a name="1.1.5"></a> |
-<h4> |
-1.1.5 Real type |
-</h4> |
- |
-<p> |
-Values of the Real type are a three-component tuple of mantissa, base and |
-exponent. All three are integers. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-pi ::= REAL { mantissa 314159, base 10, exponent -5 } |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Corresponding pyasn1 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. |
- |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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). |
-</p> |
- |
-<a name="1.1.6"></a> |
-<h4> |
-1.1.6 Bit string type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-public-key BIT STRING ::= '1010111011110001010110101101101 |
- 1011000101010000010110101100010 |
- 0110101010000111101010111111110'B |
- |
-signature BIT STRING ::= 'AF01330CD932093392100B39FF00DE0'H |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The pyasn1 BitString objects can initialize from native ASN.1 notation |
-(base 2 or base 16 strings) or from a Python tuple of binary components. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> publicKey = univ.BitString( |
-... "'1010111011110001010110101101101" |
-... "1011000101010000010110101100010" |
-... "0110101010000111101010111111110'B" |
-) |
->>> publicKey |
-BitString("'10101110111100010101101011011011011000101010000010110101100010\ |
-0110101010000111101010111111110'B") |
->>> signature = univ.BitString( |
-... "'AF01330CD932093392100B39FF00DE0'H" |
-... ) |
->>> signature |
-BitString("'101011110000000100110011000011001101100100110010000010010011001\ |
-1100100100001000000001011001110011111111100000000110111100000'B") |
->>> fingerprint = univ.BitString( |
-... (1, 0, 1, 1 ,0, 1, 1, 1, 0, 1, 0, 1) |
-... ) |
->>> fingerprint |
-BitString("'101101110101'B") |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-bit-mask BIT STRING ::= { |
- read-flag(0), |
- write-flag(2), |
- run-flag(4) |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-To express this in pyasn1, we will employ the named values feature (as with |
-Enumeration type). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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("'10001'B") |
->>> tuple(bitMask) |
-(1, 0, 0, 0, 1) |
->>> bitMask[4] |
-1 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The BitString objects mimic the properties of Python tuple type in part |
-of immutable sequence object protocol support. |
-</p> |
- |
-<a name="1.1.7"></a> |
-<h4> |
-1.1.7 OctetString type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-thumbnail OCTET STRING ::= '1000010111101110101111000000111011'B |
-thumbnail OCTET STRING ::= 'FA9823C43E43510DE3422'H |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-welcome-message OCTET STRING ::= "Welcome to ASN.1 wilderness!" |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-In pyasn1, we have taken a liberal approach and allowed both BIT STRING |
-style and quoted text initializers for the OctetString objects. To avoid |
-possible collisions, quoted text is the default initialization syntax. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> thumbnail = univ.OctetString( |
-... binValue='1000010111101110101111000000111011' |
-... ) |
->>> thumbnail |
-OctetString(hexValue='85eebcec0') |
->>> thumbnail = univ.OctetString( |
-... hexValue='FA9823C43E43510DE3422' |
-... ) |
->>> thumbnail |
-OctetString(hexValue='fa9823c43e4351de34220') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Most frequent usage of the OctetString class is to instantiate it with |
-a text string. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-OctetString objects support the immutable sequence object protocol. |
-In other words, they behave like Python 3 bytes (or Python 2 strings). |
-</p> |
- |
-<p> |
-When running pyasn1 on Python 3, it's better to use the bytes objects for |
-OctetString instantiation, as it's more reliable and efficient. |
-</p> |
- |
-<p> |
-Additionally, OctetString's can also be instantiated with a sequence of |
-8-bit integers (ASCII codes). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> univ.OctetString((77, 101, 101, 103, 111)) |
-OctetString(b'Meego') |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-It is sometimes convenient to express OctetString instances as 8-bit |
-characters (Python 3 bytes or Python 2 strings) or 8-bit integers. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> octetString = univ.OctetString('ABCDEF') |
->>> octetString.asNumbers() |
-(65, 66, 67, 68, 69, 70) |
->>> octetString.asOctets() |
-b'ABCDEF' |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.1.8"></a> |
-<h4> |
-1.1.8 ObjectIdentifier type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-internet-id OBJECT IDENTIFIER ::= { |
- iso(1) identified-organization(3) dod(6) internet(1) |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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') |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-A more human-friendly "dotted" notation is also supported. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> univ.ObjectIdentifier('1.3.6.1') |
-ObjectIdentifier('1.3.6.1') |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Symbolic names of the arcs of object identifier, sometimes present in |
-ASN.1 specifications, are not preserved and used in pyasn1 objects. |
-</p> |
- |
-<p> |
-The ObjectIdentifier objects mimic the properties of Python tuple type in |
-part of immutable sequence object protocol support. |
-</p> |
- |
-<a name="1.1.9"></a> |
-<h4> |
-1.1.9 Character string types |
-</h4> |
- |
-<p> |
-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 nowdays, 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. |
-</p> |
- |
-<p> |
-The two types are specific to ASN.1 are NumericString and PrintableString. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-welcome-message ::= PrintableString { |
- "Welcome to ASN.1 text types" |
-} |
- |
-dial-pad-numbers ::= NumericString { |
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Their pyasn1 implementations are: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The following types came to ASN.1 from ISO standards on character sets. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The last three types are relatively recent addition to the family of |
-character string types: UniversalString, BMPString, UTF8String. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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) |
-У попа была собака |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<a name="1.1.10"></a> |
-<h4> |
-1.1.10 Useful types |
-</h4> |
- |
-<p> |
-There are three so-called useful types defined in the standard: |
-ObjectDescriptor, GeneralizedTime, UTCTime. They all are subtypes |
-of GraphicString or VisibleString types therefore useful types are |
-character string types. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import useful |
->>> descrBER = useful.ObjectDescriptor( |
- "Basic encoding of a single ASN.1 type" |
-) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-;; 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" |
-</pre> |
-</td></tr></table> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import useful |
->>> moscowTime = useful.GeneralizedTime("20110308120000.0") |
->>> utcTime = useful.UTCTime("9803081200Z") |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Despite their intended use, these types possess no special, time-related, |
-handling in pyasn1. They are just printable strings. |
-</p> |
- |
-<a name="1.2"></a> |
-<h4> |
-1.2 Tagging |
-</h4> |
- |
-<p> |
-In order to continue with 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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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 <i>tag</i> 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. |
-</p> |
- |
-<p> |
-For that reason almost every ASN.1 type has a tag (which is actually a |
-BER type) associated with it by default. |
-</p> |
- |
-<p> |
-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). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-MyIntegerType ::= [12] INTEGER |
-MyOctetString ::= [APPLICATION 0] OCTET STRING |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-In pyasn1, tags are implemented as immutable, tuple-like objects: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-When tagging in IMPLICIT mode, the outermost existing tag is dropped and |
-replaced with a new one. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-MyIntegerType ::= [12] IMPLICIT INTEGER |
-MyOctetString ::= [APPLICATION 0] EXPLICIT OCTET STRING |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-To model both modes of tagging, a specialized container TagSet object (holding |
-zero, one or more Tag objects) is used in pyasn1. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import tag |
->>> tagSet = tag.TagSet( |
-... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10), # base tag |
-... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # effective tag |
-... ) |
->>> 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)) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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 original |
-ASN.1 type of an object in question. Base tag is never occurs in encoding |
-and is mostly used internally by pyasn1 for choosing type-specific data |
-processing algorithms. The "effective tag" is the one that always appears in |
-encoding and is used on tagSets comparation. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import tag |
->>> tagSet1 = tag.TagSet( |
-... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # base tag |
-... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 10) # effective tag |
-... ) |
->>> tagSet2 = tagSet1.tagExplicitly( |
-... tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 20) |
-... ) |
->>> tagSet1.isSuperTagSetOf(tagSet2) |
-True |
->>> tagSet2.isSuperTagSetOf(tagSet1) |
-False |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-We will complete this discussion on tagging with a real-world example. The |
-following ASN.1 tagged type: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-MyIntegerType ::= [12] EXPLICIT INTEGER |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-could be expressed in pyasn1 like this: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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.getTagSet() |
-TagSet(Tag(tagClass=0, tagFormat=0, tagId=2), |
- Tag(tagClass=128, tagFormat=32, tagId=12)) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-It's important to understand that the tag set property of pyasn1 type/value |
-object can never be modifed 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. |
-</p> |
- |
- |
-<a name="1.3"></a> |
-<h4> |
-1.3 Constructed types |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-In pyasn1 implementation, constructed ASN.1 types behave like |
-Python sequences, and also support additional component addressing methods, |
-specific to particular constructed type. |
-</p> |
- |
-<a name="1.3.1"></a> |
-<h4> |
-1.3.1 Sequence and Set types |
-</h4> |
- |
-<p> |
-The Sequence and Set types have many similar properties: |
-</p> |
-<ul> |
-<li>they can hold any number of inner components of different types |
-<li>every component has a human-friendly identifier |
-<li>any component can have a default value |
-<li>some components can be absent. |
-</ul> |
- |
-<p> |
-However, Sequence type guarantees the ordering of Sequence value components |
-to match their declaration order. By contrast, components of the |
-Set type can be ordered to best suite application's needs. |
-<p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-Record ::= SEQUENCE { |
- id INTEGER, |
- room [0] INTEGER OPTIONAL, |
- house [1] INTEGER DEFAULT 0 |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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)) |
-... ) |
-... ) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-All pyasn1 constructed type classes have a class attribute <b>componentType</b> |
-that represent default type specification. Its value is a NamedTypes object. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-Finally, invocation of a subtype() method of pyasn1 type objects in the code |
-above returns an implicitly tagged copy of original object. |
-</p> |
- |
-<p> |
-Once a SEQUENCE or SET type is decleared with pyasn1, it can be instantiated |
-and initialized (continuing the above code): |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> record = Record() |
->>> record.setComponentByName('id', 123) |
->>> print(record.prettyPrint()) |
-Record: |
- id=123 |
->>> |
->>> record.setComponentByPosition(1, 321) |
->>> print(record.prettyPrint()) |
-Record: |
- id=123 |
- room=321 |
->>> |
->>> record.setDefaultComponents() |
->>> print(record.prettyPrint()) |
-Record: |
- id=123 |
- room=321 |
- house=0 |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Inner components of pyasn1 Sequence/Set objects could be accessed using the |
-following methods: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> record.getComponentByName('id') |
-Integer(123) |
->>> record.getComponentByPosition(1) |
-Integer(321) |
->>> record[2] |
-Integer(0) |
->>> for idx in range(len(record)): |
-... print(record.getNameByPosition(idx), record.getComponentByPosition(idx)) |
-id 123 |
-room 321 |
-house 0 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The Set type share all the properties of Sequence type, and additionally |
-support by-tag component addressing (as all Set components have distinct |
-types). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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().getTagSet(), 121343) |
->>> gamer.setComponentByType(univ.OctetString().getTagSet(), 'Pascal') |
->>> gamer.setComponentByType(univ.ObjectIdentifier().getTagSet(), (1,3,7,2)) |
->>> print(gamer.prettyPrint()) |
-Gamer: |
- score=121343 |
- player=b'Pascal' |
- id=1.3.7.2 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.3.2"></a> |
-<h4> |
-1.3.2 SequenceOf and SetOf types |
-</h4> |
- |
-<p> |
-Both, SequenceOf and SetOf types resemble an unlimited size list of components. |
-All the components must be of the same type. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-Progression ::= SEQUENCE OF INTEGER |
- |
-arithmeticProgression Progression ::= { 1, 3, 5, 7 } |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-SequenceOf and SetOf types are expressed by the very similar pyasn1 type |
-objects. Their components can only be addressed by position and they |
-both have a property of automatic resize. |
-</p> |
- |
-<p> |
-To specify inner component type, the <b>componentType</b> class attribute |
-should refer to another pyasn1 type object. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> class Progression(univ.SequenceOf): |
-... componentType = univ.Integer() |
->>> arithmeticProgression = Progression() |
->>> arithmeticProgression.setComponentByPosition(1, 111) |
->>> print(arithmeticProgression.prettyPrint()) |
-Progression: |
--empty- 111 |
->>> arithmeticProgression.setComponentByPosition(0, 100) |
->>> print(arithmeticProgression.prettyPrint()) |
-Progression: |
-100 111 |
->>> |
->>> for idx in range(len(arithmeticProgression)): |
-... arithmeticProgression.getComponentByPosition(idx) |
-Integer(100) |
-Integer(111) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Any scalar or constructed pyasn1 type object can serve as an inner component. |
-Missing components are prohibited in SequenceOf/SetOf value objects. |
-</p> |
- |
-<a name="1.3.3"></a> |
-<h4> |
-1.3.3 Choice type |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-CodeOrMessage ::= CHOICE { |
- code INTEGER, |
- message OCTET STRING |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-In pyasn1 implementation, 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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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.setComponentByName('code', 123) |
->>> print(codeOrMessage.prettyPrint()) |
-CodeOrMessage: |
- code=123 |
->>> codeOrMessage.setComponentByName('message', 'my string value') |
->>> print(codeOrMessage.prettyPrint()) |
-CodeOrMessage: |
- message=b'my string value' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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): |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> codeOrMessage.getName() |
-'message' |
->>> codeOrMessage.getComponent() |
-OctetString(b'my string value') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="1.3.4"></a> |
-<h4> |
-1.3.4 Any type |
-</h4> |
- |
-<p> |
-The ASN.1 ANY type is a kind of wildcard or placeholder that matches |
-any other type without knowing it in advance. Like CHOICE type, ANY |
-has no base tag. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-Error ::= SEQUENCE { |
- code INTEGER, |
- parameter ANY DEFINED BY code |
-} |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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). |
-</p> |
- |
-<p> |
-Values of the ANY type contain serialized ASN.1 value(s) in form of |
-an octet string. Therefore pyasn1 Any value object share the properties of |
-pyasn1 OctetString object. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-There will be some more talk and code snippets covering Any type in the codecs |
-chapters that follow. |
-</p> |
- |
-<a name="1.4"></a> |
-<h4> |
-1.4 Subtype constraints |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-Imposing value constraints on an ASN.1 type can also be seen as creating |
-a subtype from its base type. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-A handful of different flavors of <i>constraints</i> 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. |
-</p> |
- |
-<a name="1.4.1"></a> |
-<h4> |
-1.4.1 Single value constraint |
-</h4> |
- |
-<p> |
-This kind of constraint allows for limiting type to a finite, specified set |
-of values. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-DialButton ::= OCTET STRING ( |
- "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |
-) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Its pyasn1 implementation would look like: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-As can be seen in the snippet above, if a value violates the constraint, an |
-exception will be thrown. A constrainted pyasn1 type object holds a |
-reference to a constraint object (or their combination, as will be explained |
-later) and calls it for value verification. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- SingleValueConstraint(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) failed at: A |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Constrained pyasn1 value object can never hold a violating value. |
-</p> |
- |
-<a name="1.4.2"></a> |
-<h4> |
-1.4.2 Value range constraint |
-</h4> |
- |
-<p> |
-A pair of values, compliant to a type to be constrained, denote low and upper |
-bounds of allowed range of values of a type. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-Teenagers ::= INTEGER (13..19) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-And in pyasn1 terms: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ValueRangeConstraint(13, 19) failed at: 20 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Value range constraint usually applies numeric types. |
-</p> |
- |
-<a name="1.4.3"></a> |
-<h4> |
-1.4.3 Size constraint |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-TwoBits ::= BIT STRING (SIZE (2)) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Express the same grammar in pyasn1: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ValueSizeConstraint(2, 2) failed at: (1, 1, 0) |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Size constraint can be applied to potentially massive values - bit or octet |
-strings, SEQUENCE OF/SET OF values. |
-</p> |
- |
-<a name="1.4.4"></a> |
-<h4> |
-1.4.4 Alphabet constraint |
-</h4> |
- |
-<p> |
-The permitted alphabet constraint is similar to Single value constraint |
-but constraint applies to individual characters of a value. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-MorseCode ::= PrintableString (FROM ("."|"-"|" ")) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-And in pyasn1: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import char, constraint |
->>> class MorseCode(char.PrintableString): |
-... subtypeSpec = constraint.PermittedAlphabetConstraint(".", "-", " ") |
->>> MorseCode("...---...") |
-MorseCode('...---...') |
->>> MorseCode("?") |
-Traceback (most recent call last): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- PermittedAlphabetConstraint(".", "-", " ") failed at: "?" |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Current implementation does not handle ranges of characters in constraint |
-(FROM "A".."Z" syntax), one has to list the whole set in a range. |
-</p> |
- |
-<a name="1.4.5"></a> |
-<h4> |
-1.4.5 Constraint combinations |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-PhoneNumber ::= NumericString (FROM ("0".."9")) (SIZE 11) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Constraint intersection object serves the logic above: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ConstraintsIntersection( |
- PermittedAlphabetConstraint('0','1','2','3','4','5','6','7','8','9'), |
- ValueSizeConstraint(11, 11)) failed at: |
- ValueSizeConstraint(10, 10) failed at: "9343212" |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Union of constraints works by making sure that a value is compliant |
-to any of the constraint in a set. For instance: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-CapitalOrSmall ::= IA5String (FROM ('A','B','C') | FROM ('a','b','c')) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ConstraintsUnion(PermittedAlphabetConstraint('A', 'B', 'C'), |
- PermittedAlphabetConstraint('a', 'b', 'c')) failed at: failed for "Abba" |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
-NoZero ::= INTEGER (ALL EXCEPT 0) |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-In pyasn1 the above definition would read: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ConstraintsExclusion(SingleValueConstraint(0)) failed at: 0 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<a name="1.5"></a> |
-<h4> |
-1.5 Types relationships |
-</h4> |
- |
-<p> |
-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: |
-<i>tag set</i> and <i>subtype constraints</i>. One pyasn1 type is considered |
-to be a derivative of another if their TagSet and Constraint objects are |
-a derivation of one another. |
-</p> |
- |
-<p> |
-The following example illustrates the concept (we use the same tagset but |
-different constraints for simplicity): |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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: |
-<b>isSameTypeWith</b>() and <b>isSuperTypeOf</b>(). 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. |
-</p> |
- |
-<a name="2"></a> |
-<h3> |
-2. Codecs |
-</h3> |
- |
-<p> |
-In ASN.1 context, |
-<a href=http://en.wikipedia.org/wiki/Codec>codec</a> |
-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 <i>substrate</i> or <i>essence</i>. |
-</p> |
- |
-<p> |
-In pyasn1 implementation, substrate takes shape of Python 3 bytes or |
-Python 2 string objects. |
-</p> |
- |
-<p> |
-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 |
-<a href=http://directory.apache.org/subprojects/asn1/>Apache ASN.1 project</a> |
-. |
-</p> |
- |
-<p> |
-As of this writing, codecs implemented in pyasn1 are all stateless, mostly |
-to keep the code simple. |
-</p> |
- |
-<p> |
-The pyasn1 package currently supports |
-<a href=http://en.wikipedia.org/wiki/Basic_encoding_rules>BER</a> codec and |
-its variations -- |
-<a href=http://en.wikipedia.org/wiki/Canonical_encoding_rules>CER</a> and |
-<a href=http://en.wikipedia.org/wiki/Distinguished_encoding_rules>DER</a>. |
-More ASN.1 codecs are planned for implementation in the future. |
-</p> |
- |
-<a name="2.1"></a> |
-<h4> |
-2.1 Encoders |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-The following code will create a pyasn1 Integer object and serialize it with |
-BER encoder: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.type import univ |
->>> from pyasn1.codec.ber import encoder |
->>> encoder.encode(univ.Integer(123456)) |
-b'\x02\x03\x01\xe2@' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-BER standard also defines a so-called <i>indefinite length</i> 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. |
-</p> |
- |
-<p> |
-<i>Constructed encoding</i> 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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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' |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-The <b>defMode</b> encoder parameter disables definite length encoding mode, |
-while the optional <b>maxChunkSize</b> parameter specifies desired |
-substrate chunk size that influences memory requirements at the decoder's end. |
-</p> |
- |
-<p> |
-To use CER or DER encoders one needs to explicitly import and call them - the |
-APIs are all compatible. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="2.2"></a> |
-<h4> |
-2.2 Decoders |
-</h4> |
- |
-<p> |
-In the process of decoding, pyasn1 value objects are created and linked to |
-each other, based on the information containted in the substrate. Thus, |
-the original pyasn1 value object(s) are recovered. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-All pyasn1 decoders can handle both definite and indefinite length |
-encoding modes automatically, explicit switching into one mode |
-to another is not required. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-As discussed earlier in this handbook, 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 <i>guide</i> 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 paper). |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> from pyasn1.codec.ber import decoder |
->>> decoder.decode(b'\x02\x01\x0c', asn1Spec=univ.Integer()) |
-Integer(12), b'' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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): |
-... |
-pyasn1.type.error.ValueConstraintError: |
- ValueRangeConstraint(0, 9) failed at: 13 |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Similarily to encoders, to use CER or DER decoders application has to |
-explicitly import and call them - all APIs are compatible. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<a name="2.2.1"></a> |
-<h4> |
-2.2.1 Decoding untagged types |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-To explain the issue, we will first prepare a Choice object to deal with: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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.setComponentByName('message', 'my string value') |
->>> print(codeOrMessage.prettyPrint()) |
-CodeOrMessage: |
- message=b'my string value' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Let's now encode this Choice object and then decode its substrate |
-with and without pyasn1 specification object: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<p> |
-Similarily 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. |
-</p> |
- |
-<p> |
-As it was mentioned elsewhere in this paper, Any type allows for incomplete |
-or changing ASN.1 specification to be handled gracefully by decoder and |
-applications. |
-</p> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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' |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-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: |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-Both CHOICE and ANY types are widely used in practice. Reader is welcome to |
-take a look at |
-<a href=http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt> |
-ASN.1 specifications of X.509 applications</a> for more information. |
-</p> |
- |
-<a name="2.2.2"></a> |
-<h4> |
-2.2.2 Ignoring unknown types |
-</h4> |
- |
-<p> |
-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. |
-</p> |
- |
-<table bgcolor="lightgray" border=0 width=100%><TR><TD> |
-<pre> |
->>> 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'), '') |
->>> |
-</pre> |
-</td></tr></table> |
- |
-<p> |
-It's also possible to configure a custom decoder, to handle unknown tags |
-found in substrate. This can be done by means of <b>defaultRawDecoder</b> |
-attribute holding a reference to type decoder object. Refer to the source |
-for API details. |
-</p> |
- |
-<a name="3"></a> |
-<h3> |
-3. Feedback and getting help |
-</h3> |
- |
-<p> |
-Although pyasn1 software is almost a decade old and used in many production |
-environments, it still may have bugs and non-implemented pieces. Anyone |
-who happens to run into such defect is welcome to complain to |
-<a href=mailto:pyasn1-users@lists.sourceforge.net>pyasn1 mailing list</a> |
-or better yet fix the issue and send |
-<a href=mailto:ilya@glas.net>me</a> the patch. |
-</p> |
- |
-<p> |
-Typically, pyasn1 is used for building arbitrary protocol support into |
-various applications. This involves manual translation of ASN.1 data |
-structures into their pyasn1 implementations. To save time and effort, |
-data structures for some of the popular protocols are pre-programmed |
-and kept for further re-use in form of the |
-<a href=http://sourceforge.net/projects/pyasn1/files/pyasn1-modules/> |
-pyasn1-modules package</a>. 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. |
-</p> |
- |
-<p> |
-And finally, the latest pyasn1 package revision is available for free |
-download from |
-<a href=http://sourceforge.net/projects/pyasn1/>project home</a> and |
-also from the |
-<a href=http://pypi.python.org/pypi>Python package repository</a>. |
-</p> |
- |
-<hr> |
- |
-</td> |
-</tr> |
-</table> |
-</center> |
-</body> |
-</html> |